ts-aggregator/project_template/project_template.cpp
2022-12-13 12:36:06 +04:00

417 lines
14 KiB
C++

#include "stdafx.h"
#include <iostream>
#include "Method.h"
#include "Dsa.h"
#include "Aic.h"
#include "AicWeights.h"
#include "Normalization.h"
#include "Mape.h"
#include "SMape.h"
#include "Vovk.h"
#include "NoTrendNoSeasonality.h"
#include "NoTrendAddSeasonality.h"
#include "NoTrendMultSeasonality.h"
#include "AddTrendNoSeasonality.h"
#include "AddTrendAddSeasonality.h"
#include "AddTrendMultSeasonality.h"
#include "MultTrendNoSeasonality.h"
#include "MultTrendAddSeasonality.h"
#include "MultTrendMultSeasonality.h"
#include "DATrendNoSeasonality.h"
#include "DATrendAddSeasonality.h"
#include "DATrendMultSeasonality.h"
#include "DMTrendNoSeasonality.h"
#include "DMTrendAddSeasonality.h"
#include "DMTrendMultSeasonality.h"
#include "Tsaur.h"
#include "A.h"
#include "Fuzzy.h"
#include "FuzzyWithSets.h"
#include "File.h"
#include <vector>
#include "Param.h"
#include <sstream>
#include <direct.h>
#include <string>
#include <limits>
#include <math.h>
#include "Transformation.h"
#include "nlopt.hpp"
#include "nlopt.h"
#include "BIC.h"
int iMethod; // íîìåð òåêóùåãî ìåòîäà
const int n = 29; // êîëè÷åñòâî ìåòîäîâ, ÷òîá ëèøíåãî ïàìÿòè íå æðàòü
int numberParam; // ÷èñëî ïàðàìåòðîâ ó ìåòîäà
Method** m = new Method*[n];
Estimation* est1 = new SMape();
int ii; // ñ÷åò÷èê èòåðàöèé
double round (double value) {
return floor(value + 0.5);
}
double myRound(double num) {
double n = ((double)round(num * 1000)) / 1000;
return n;
}
void printTs(vector<double> ts) {
for (unsigned int i = 0; i < ts.size(); i++) {
cout << ts[i];
cout << " ";
}
}
double getEstimation(const std::vector<double> &x, std::vector<double> &grad, void *f_data)
{
ii++; // ñ÷åò÷èê èòåðàöèé
int radix = 10; //ñèñòåìà ñ÷èñëåíèÿ
char sbuffer[10]; //ðåçóëüòàò
for (int iiParam = 0; iiParam < numberParam; iiParam++)
{
m[iMethod]->setParam(itoa(iiParam, sbuffer, radix), myRound(x[iiParam]));
}
m[iMethod]->createModelForEstimation();
double smapeValue = myRound(est1->getValue(m[iMethod]->x, m[iMethod]->getForecast()));
return smapeValue;
}
int main(int argc, char* argv[])
{
Param* bestParams = new Param();
double bestSmape = DBL_MAX;
double bestAic = DBL_MAX;
int bestMethodIndex = 0;
setlocale(LC_ALL, "Russian");
string path;
string fileName;
string s;
if (argc < 1) {
cout << "set ts file like 'project_template.exe 1.csv count_forecast period!!!";
return 0;
} else {
stringstream ss;
ss << argv[1];
ss >> s;
int found = 0;
int offset =0;
do {
found = s.find("\\", found +1);
if (found > 0) {
offset = found;
cout << found << "\n";
}
} while (found!=std::string::npos);
if (offset ==0) {
fileName = s.substr(offset, s.length());
} else {
fileName = s.substr(offset+1, s.length());
}
path = s.substr(0, offset);
}
// îáúåêò äëÿ ðàáîòû ñ ôàéëàìè: çàãðóçèòü è ñîõðàíèòü ÂÐ
vector<double> timeSeries = File::readFile(argv[1]);
Transformation *transform = new Transformation(timeSeries);
transform->seasonalPeriod = atof(argv[3]);
// timeSeries = transform->Normalization();
//transform->setTimeSeries(tsTransform);
transform->lambdaEstimation();
timeSeries = transform->ModifiedBoxCox();
Normalization * norm = new Normalization();
//timeSeries = norm->normalizeTimeSeria(timeSeries);
// ñêîëüêî òî÷åê áóäåì ïðîãíîçèðîâàòü
int pointForecast = 18;
if (strcmp(argv[2], "") != 0) {
pointForecast = atof(argv[2]);
}
int p = 12;
if (strcmp(argv[3], "") != 0) {
p = atof(argv[3]);
}
double alpha = 0.1;
double delta = 0.2;
double gamma = 0.4;
double phi = 0.1;
int countRulesIn = 1;
int countFuzzyParts = 2;
// äàëåå çàäàåì ïàðàìåòðû, ñïåöèôè÷íûå äëÿ ìåòîäîâ
//...
// òàê êàê èñïîëüçîâàòü áóäåì âñå ìåòîäû (èëè îáúåäèíÿòü â êîëëåêòèâû) íóæíî
// âñå èõ ïðîèíèöèàëèçèðîâàòü è çàãíàòü â ìàññèâ
m[0] = new NoTrendNoSeasonality(timeSeries, pointForecast);
m[1] = new NoTrendAddSeasonality(timeSeries, pointForecast);
m[2] = new NoTrendMultSeasonality(timeSeries, pointForecast);
m[3] = new AddTrendNoSeasonality(timeSeries, pointForecast);
m[4] = new MultTrendNoSeasonality(timeSeries, pointForecast);
m[5] = new DATrendNoSeasonality(timeSeries, pointForecast);
m[6] = new DMTrendNoSeasonality(timeSeries, pointForecast);
m[7] = new AddTrendAddSeasonality(timeSeries, pointForecast);
m[8] = new MultTrendAddSeasonality(timeSeries, pointForecast);
m[9] = new DATrendAddSeasonality(timeSeries, pointForecast);
m[10] = new DMTrendAddSeasonality(timeSeries, pointForecast);
m[11] = new AddTrendMultSeasonality(timeSeries, pointForecast);
m[12] = new MultTrendMultSeasonality(timeSeries, pointForecast);
m[13] = new DATrendMultSeasonality(timeSeries, pointForecast);
m[14] = new DMTrendMultSeasonality(timeSeries, pointForecast);
m[15] = new Dsa(timeSeries, pointForecast);
m[16] = new Fuzzy("None", "None", timeSeries, pointForecast);
m[17] = new Fuzzy("Add", "None", timeSeries, pointForecast);
m[18] = new Fuzzy("None", "Add", timeSeries, pointForecast);
m[19] = new Fuzzy("Add", "Add", timeSeries, pointForecast);
m[20] = new FuzzyWithSets("None", "None", timeSeries, pointForecast);
m[21] = new FuzzyWithSets("None", "Add", timeSeries, pointForecast);
m[22] = new FuzzyWithSets("None", "Mult", timeSeries, pointForecast);
m[23] = new FuzzyWithSets("Add", "None", timeSeries, pointForecast);
m[24] = new FuzzyWithSets("Add", "Add", timeSeries, pointForecast);
m[25] = new FuzzyWithSets("Add", "Mult", timeSeries, pointForecast);
m[26] = new FuzzyWithSets("Mult", "None", timeSeries, pointForecast);
m[27] = new FuzzyWithSets("Mult", "Add", timeSeries, pointForecast);
m[28] = new FuzzyWithSets("Mult", "Mult", timeSeries, pointForecast);
//m[29] = new Tsaur(timeSeries, pointForecast);
AicWeights *aicWeights = new AicWeights();
vector<double> aicValues;
vector<vector<double>> modelsResults;
vector<Param*> optimal;
string smapeResults = "";
for (int i = 15; i < n; i++) {
iMethod = i;
m[i]->setParam("p", p);
// âûçîâåì ìåòîä îïòèìèçàöèè îäíîãî ïàðàìåòðà
//Estimation *est1 = new SMape();
Estimation *est1 = new Bic(algoritm::RMSE, m[i]->getNamberParam());
//optimal.push_back(m[i]->optimize(est1));
numberParam = m[i]->getNamberParam();
if (numberParam == 1) // äëÿ îäíîãî ïàðàìåòðà ïðîùå ïåðåáîð ïî ñåòêå
{
optimal.push_back(m[i]->optimize(est1));
m[i]->setParam("alpha", optimal[optimal.size()-1]->alpha);
}
else
{
// âåêòîðà äëÿ íà÷àëüíûõ, ìèíèìàëüíûõ è ìàêñèìàëüíûõ çíà÷åíèé ïàðàìåòðîâ
std::vector<double> x(numberParam);
std::vector<double> lb(numberParam);
std::vector<double> ub(numberParam);
// óñòàíàâëèâàåì ïàðàìåòðû
for (int iParam = 0; iParam < numberParam; iParam++)
{
lb[iParam] = 0.01; // ìèíèìàëüíîå çíà÷åíèå ïàðàìåòðà
ub[iParam] = 0.99; // ìàêñèìàëüíîå çíà÷åíèå ïåðåìåòðà
x[iParam] = 0.3; // íà÷àëüíîå çíà÷åíèå ïàðàìåòðà
}
// ñîçäàåì îñíîâíîé ìåòîä îïòèìèçàöèè
nlopt::opt opt(nlopt::AUGLAG, numberParam);
// ñîçäàåì âñïîìàãàòåëüíûé ìåòîä îïòèìèçàöèè
nlopt::opt subOpt(nlopt::GN_ORIG_DIRECT_L, numberParam);
subOpt.set_lower_bounds(lb);
subOpt.set_upper_bounds(ub);
// óñòàíàâëèâàåì ïàðàìåòðû îñíîâíîãî ìåòîäà îïòèìèçàöèè
opt.set_lower_bounds(lb);
opt.set_upper_bounds(ub);
opt.set_local_optimizer(subOpt);
// â çàâèñèìîñòè îò ÷èñëà ïàðàìåòðîâ, óñòàíàâëèâàåì êîëè÷åñòâî èòåðàöèé îïòèìèçàöèè
if (numberParam == 2)
{
subOpt.set_maxeval(10000);
opt.set_maxeval(10000);
}
else if (numberParam == 3)
{
subOpt.set_maxeval(50000);
opt.set_maxeval(50000);
}
else
{
subOpt.set_maxeval(100000);
opt.set_maxeval(100000);
}
// çàïóñêàåì îïòèìèçàöèþ
// getEstimation - ìåòîä â ñàìîì ââåðõó, êîòðûé âîçâðàùàåò îøèáêó íà êàæäîé èòåðàöèè
double minf;
opt.set_min_objective(getEstimation, NULL);
nlopt::result subResult = opt.optimize(x, minf);
cout << minf << endl;
// ïîïûòàåìñÿ óëó÷øèòü ïàðàìåòðû
nlopt::opt ssubOpt(nlopt::LN_NELDERMEAD, numberParam);
ssubOpt.set_lower_bounds(lb);
ssubOpt.set_upper_bounds(ub);
ssubOpt.set_maxeval(500);
ssubOpt.set_min_objective(getEstimation, NULL);
nlopt::result Result = ssubOpt.optimize(x, minf);
cout << minf << endl;
if (m[i]->getNamberParam() > 1) {
optimal.push_back(new Param());
}
optimal[optimal.size()-1]->countFuzzyParts = x[0] * 100;
optimal[optimal.size()-1]->countRulesIn = x[1] * 5;
if (i == 15) {
optimal[optimal.size()-1]->sizeLabels = x[2] * 100;
} else {
optimal[optimal.size()-1]->gamma = x[2];
}
if (m[i]->getNamberParam() > 3) {
optimal[optimal.size()-1]->delta = x[3];
if (m[i]->getNamberParam() > 4) {
optimal[optimal.size()-1]->alpha = x[4];
}
}
// â âåêòîðå x íàéäåííûå ïàðàìåòðû, â min - smape
}
// ñîçäàåì ìîäåëü äëÿ òåñòèðîâàíèÿ ïðè ïîìîùè âûáðàííîãî ìåòîäà
// çàäàåì ïàðàìåòðû
m[i]->setParam("alpha", optimal[optimal.size()-1]->alpha);
m[i]->setParam("gamma", optimal[optimal.size()-1]->gamma);
m[i]->setParam("delta", optimal[optimal.size()-1]->delta);
m[i]->setParam("phi", optimal[optimal.size()-1]->phi);
m[i]->setParam("countRulesIn", optimal[optimal.size()-1]->countRulesIn);
m[i]->setParam("countFuzzyParts", optimal[optimal.size()-1]->countFuzzyParts);
m[i]->setParam("lb1", optimal[optimal.size()-1]->lb1);
m[i]->setParam("rb1", optimal[optimal.size()-1]->rb1);
m[i]->setParam("lb2", optimal[optimal.size()-1]->lb2);
m[i]->setParam("rb2", optimal[optimal.size()-1]->rb2);
m[i]->setParam("sizeLabels", optimal[optimal.size()-1]->sizeLabels);
// ñîçäàåì ìîäåëü
m[i]->createModelForEstimation();
// âû÷èñëÿåì îøèáêó
//aicValues.push_back(aic->getValue(4, m[i]->getXEstimation(), m[i]->getForecast()));
//aicValues.push_back(aic->getAiccValue(4, m[i]->getXEstimation(), m[i]->getForecast()));
//aicValues.push_back(aic->getBicValue(4, m[i]->getXEstimation(), m[i]->getForecast()));
//modelsResults.push_back(m[i]->getForecast());
SMape* smape = new SMape();
stringstream ss1;
ss1 << i;
string str1 = ss1.str();
stringstream ss2;
double sm = smape->getValue(m[i]->x, m[i]->getForecast());
double ai = optimal[optimal.size()-1]->estim;
ss2 << sm;
// îïðåäåëÿåì, ÿâëÿþòñÿ ëè äàííûå ïàðàìåòðû ëó÷øèìè
if (ai < bestAic) {
bestAic = ai;
bestParams = optimal[optimal.size()-1];
bestMethodIndex = i;
}
string str2 = ss2.str();
smapeResults = smapeResults + "Smape for " + str1 + " method: " + str2 + " ";
smapeResults = smapeResults + optimal[optimal.size()-1]->toString() + "\n";
// ñîçäàåì ìîäåëü ïðè ïîìîùè âûáðàííîãî ìåòîäà
// ïîëó÷èì è ñîõðàíèì ïðîãíîç
string target = path +"\\"+ fileName+"result";
_mkdir(target.c_str());
string fileNameOut = target + "\\";
char suff[3];
itoa(i, suff, 10);
fileNameOut.append(suff);
fileNameOut.append("out");
m[i]->createModel();
//File::writeFile(fileNameOut, norm->deNormalizeTimeSeria(m[i]->getForecast()));
//transform->setTimeSeries(m[i]->getForecast());
//transform->setTimeSeries(transform->invModifiedBoxCox());
transform->setTimeSeries(m[i]->getForecast());
File::writeFile(fileNameOut, transform->invModifiedBoxCox());
}
Method* bestMethod = m[bestMethodIndex];
// ïîñëå òîãî, êàê îòðàáîòàëè âñå ìîäåëè
// çàäàåì ëó÷øèå ïàðàìåòðû
bestMethod->setParam("alpha", bestParams->alpha);
bestMethod->setParam("gamma", bestParams->gamma);
bestMethod->setParam("delta", bestParams->delta);
bestMethod->setParam("phi", bestParams->phi);
bestMethod->setParam("countRulesIn", bestParams->countRulesIn);
bestMethod->setParam("countFuzzyParts", bestParams->countFuzzyParts);
bestMethod->setParam("lb1", bestParams->lb1);
bestMethod->setParam("rb1", bestParams->rb1);
bestMethod->setParam("lb2", bestParams->lb2);
bestMethod->setParam("rb2", bestParams->rb2);
bestMethod->setParam("sizeLabels", bestParams->sizeLabels);
bestMethod->createModel();
string target = path +"\\"+ fileName+"result";
string fileNameOut = target + "\\";
fileNameOut.append("best");
char _s[3];
itoa(bestMethodIndex, _s, 10);
fileNameOut.append(_s);
//File::writeFile(fileNameOut, norm->deNormalizeTimeSeria(bestMethod->getForecast()));
transform->setTimeSeries(bestMethod->getForecast());
File::writeFile(fileNameOut, transform->invModifiedBoxCox());
string smapeFileName = path +"\\"+ fileName+"result\\smape";
FILE * file = fopen(smapeFileName.c_str(), "w");
if (file) // åñëè åñòü äîñòóï ê ôàéëó,
{
bool result = fputs(smapeResults.c_str(), file); // è çàïèñûâàåì åå â ôàéë
if (!result) // åñëè çàïèñü ïðîèçîøëà óñïåøíî
cout << "Ñòðîêà â ôàéë óñïåøíî çàïèñàíà!"; // âûâîäèì ñîîáùåíèå
fclose(file);
}
return 0;
Vovk *vovk = new Vovk(timeSeries, pointForecast, m);
vector<double> res;
res.push_back(vovk->getForecast());
for (int i = 0; i < pointForecast - 1; i++){
//cout << i + 1 << " " << vovk->getForecast() << endl;
vovk->updateTS(res[res.size() - 1]);
res.push_back(vovk->getForecast());
}
res = norm->deNormalizeTimeSeria(res);
for (int i = 0; i < pointForecast - 1; i++){
cout << i + 1 << " " << res[i] << endl;
}
SMape *smape = new SMape();
cout << "Smape for Vovk " << " method: " << smape->getValue(norm->deNormalizeTimeSeria(m[0]->getXEstimation()), res) << "\n";
vector<double> weights = aicWeights->calculateWeights(aicValues);
vector<double> fuzzyAdoptiveWeights = aicWeights->calculateFuzzyAdaptiveWeights(timeSeries, modelsResults);
cout << "Smape for etalon forecast " << " method: " << smape->getValue(m[21]->getXEstimation(), m[21]->getXEstimation()) << "\n";
delete(m);
return 0;
}