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