128 lines
3.6 KiB
C++
128 lines
3.6 KiB
C++
//
|
|
// Ìåòîä ýêñïîíåíöèàëüíîãî ñãëàæèâàíèÿ è ïðîãíîçèðîâàíèÿ:
|
|
// äåìïèíã ìóëüòèïëèêàòèâíûé òðåíä, áåç ñåçîííîñòè
|
|
//
|
|
#include "StdAfx.h"
|
|
#include <iostream>
|
|
#include <math.h>
|
|
#include "DMTrendNoSeasonality.h"
|
|
#include "Param.h"
|
|
|
|
// êîíñòðóêòîð ñ çàäàííûìè íåïîñðåäñòâåííî ïàðàìåòðàìè
|
|
DMTrendNoSeasonality::DMTrendNoSeasonality(vector<double> timeSeries, int countPointForecast) {
|
|
this->x = timeSeries;
|
|
this->countPointForecast = countPointForecast;
|
|
this->partition();
|
|
}
|
|
|
|
DMTrendNoSeasonality::~DMTrendNoSeasonality() {
|
|
// îñâîáîæäàåòñÿ ïàìÿòü
|
|
std::vector<double> ().swap(S);
|
|
std::vector<double> ().swap(x);
|
|
std::vector<double> ().swap(T);
|
|
std::vector<double> ().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<double> DMTrendNoSeasonality::getForecast() {
|
|
vector<double> 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;
|
|
}
|