// // Метод экспоненциального сглаживания и прогнозирования: // аддитивный тренд, без сезонности // #include "StdAfx.h" #include #include "AddTrendNoSeasonality.h" #include "Aic.h" #include "Param.h" // конструктор с заданными непосредственно параметрами AddTrendNoSeasonality::AddTrendNoSeasonality(vector timeSeries, int countPointForecast) { this->x = timeSeries; this->countPointForecast = countPointForecast; this->partition(); this->alpha = 0; this->gamma = 0; } AddTrendNoSeasonality::~AddTrendNoSeasonality() { // освобождается память std::vector ().swap(S); std::vector ().swap(x); std::vector ().swap(T); std::vector ().swap(forecast); } // Задать параметр void AddTrendNoSeasonality::setParam(string paramName, double value) { if (paramName.compare("alpha") == 0) { this->alpha = value; } else if (paramName.compare("gamma") == 0) { this->gamma = value; } } // инициализация модели, задание первоначальных значений void AddTrendNoSeasonality::init() { S.clear(); T.clear(); forecast.clear(); T.push_back(x[1] - x[0]); S.push_back(x[0]); forecast.push_back(S[0] + T[0]); } // сформировать модель void AddTrendNoSeasonality::createModel() { this->init(); // инициализировать модель double e = 0; //выполняется проход модели по сглаживанию и прогнозированию countPointForecast точек for (unsigned int t = 0; t countPointForecast; t++) { // пока не дошли до конца ряда - сглаживаем, иначе строим прогноз if (t < x.size()) { e = x[t]-forecast[t]; } else { e = 0; } S.push_back(S[t] + T[t] + alpha * e); // уровень T.push_back(T[t] + alpha * gamma * e); // тренд forecast.push_back(S[t+1] + T[t+1]); // прогноз } } // сформировать модель void AddTrendNoSeasonality::createModelForEstimation() { this->init(); // инициализировать модель double e = 0; //выполняется проход модели по сглаживанию и прогнозированию countPointForecast точек for (unsigned int t = 0; t < xLearning.size()-1 + this->countPointForecast; t++) { // пока не дошли до конца ряда - сглаживаем, иначе строим прогноз if (t < xLearning.size()) { e = xLearning[t]-forecast[t]; } else { e = 0; } S.push_back(S[t] + T[t] + alpha * e); // уровень T.push_back(T[t] + alpha * gamma * e); // тренд forecast.push_back(S[t+1] + T[t+1]); // прогноз } } // метод получения прогноза vector AddTrendNoSeasonality::getForecast() { vector result; for (unsigned int i = forecast.size() - countPointForecast; i < forecast.size(); i++) { result.push_back(forecast[i]); } return result; } // метод получения оценки модели double AddTrendNoSeasonality::calcEstimation(Aic *aic) { return aic->getValue(3, this->xEstimation, this->forecast); } // метод получения оптимизированного значения одного параметра // TODO: реализовать Param* AddTrendNoSeasonality::optimize(Estimation *est) { Param *optimal = new Param(); double minSmape = 99999; for (double al = 0.1; al < 1; al+= 0.01) { for (double gam = 0.1; gam < 1; gam+= 0.01) { this->setParam("alpha", al); this->setParam("gamma", gam); this->createModelForEstimation(); double smapeValue = est->getValue(getXEstimation(), getForecast()); if (minSmape > smapeValue) { minSmape = smapeValue; optimal->alpha = al; optimal->gamma = gam; } } } return optimal; }