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