271 lines
7.5 KiB
C++
271 lines
7.5 KiB
C++
#include "StdAfx.h"
|
|
#include "Tsaur.h"
|
|
#include "Param.h"
|
|
#include "float.h"
|
|
#include <iostream>
|
|
|
|
|
|
Tsaur::Tsaur(vector<double> timeSeries, int countPointForecast){
|
|
this->countPointForecast = countPointForecast;
|
|
this->trendType = trendType;
|
|
this->seasonType = seasonType;
|
|
this->x = timeSeries;
|
|
this->partition();
|
|
}
|
|
|
|
void Tsaur::init() {
|
|
S.clear();
|
|
T.clear();
|
|
T.push_back(fuzzyfication(x[1]-x[0]));
|
|
S.push_back(fuzzyfication(x[0]));
|
|
fuzzyForecast.push_back(plusSet(S[0], T[0]));
|
|
}
|
|
|
|
// îïðåäåëèòü óíèâåðñóì äëÿ âðåìåííîãî ðÿäà
|
|
// èùåì ìàêñèìóì, ìèíèìóì, ïðîèçâîäèì ðàçáèåíèå íà çàäàííûå èíòåðâàëû
|
|
void Tsaur::defineUniversum() {
|
|
this->universumMax = x[0];
|
|
this->universumMin = x[0];
|
|
for (int i = 1; i < x.size(); i++) {
|
|
if (universumMax < x[i]) {
|
|
universumMax = x[i];
|
|
}
|
|
if (universumMin > x[i]) {
|
|
universumMin = x[i];
|
|
}
|
|
}
|
|
|
|
// ñîçäàåì ôóíêöèè ïðèíàäëåæíîñòè
|
|
// ïðèíèìàåì ïî óìîë÷àíèþ, ÷òî ñîñåäíèå ïåðåêðûâàþòñÿ íà ïîëîâèíó ìåæäó ñîáîé
|
|
// ðàç åñòü êîëè÷åñòâî èíòåðâàëîâ, òî âû÷èñëÿåì ðàçìåð îñíîâàíèÿ òðåóãîëüíèêà
|
|
double baseSize = (universumMax - universumMin) / countFuzzyParts;
|
|
a.resize(countFuzzyParts + 1);
|
|
for (int i=0; i < countFuzzyParts + 1;i++){
|
|
a[i] = (A(universumMin + (i-1) * baseSize, universumMin + (i+1)*baseSize));
|
|
}
|
|
}
|
|
|
|
// îïåðàöèÿ âû÷èòàíèÿ ìíîæåñòâ
|
|
A Tsaur::minusSet(A a, A b) {
|
|
//if ((a.getLeft()- b.getLeft()) < (a.getRight() - b.getRight())) {
|
|
return A(a.getLeft()- b.getLeft(), a.getRight() - b.getRight());
|
|
//} else {
|
|
// return A(a.getRight() - b.getRight(), a.getLeft()- b.getLeft());
|
|
//}
|
|
}
|
|
|
|
// îïåðàöèÿ âû÷èòàíèÿ ìíîæåñòâ
|
|
A Tsaur::numMinusSet(double num, A a) {
|
|
//if ((num - a.getLeft()) < (num - a.getRight())) {
|
|
return A(num - a.getLeft(), num - a.getRight());
|
|
//} else {
|
|
// return A(num - a.getRight(), num - a.getLeft());
|
|
//}
|
|
}
|
|
|
|
// îïåðàöèÿ äåëåíèÿ ìíîæåñòâ
|
|
A Tsaur::divSet(A a, A b) {
|
|
return A(a.getLeft()/b.getLeft(), a.getRight()/b.getRight());
|
|
}
|
|
|
|
// îïåðàöèÿ äåëåíèÿ ìíîæåñòâ
|
|
A Tsaur::divSet(A a, double b) {
|
|
return A(a.getLeft()/b, a.getRight()/b);
|
|
}
|
|
|
|
// îïåðàöèÿ óìíîæåíèå ìíîæåñòâà íà ÷èñëî
|
|
A Tsaur::multSetNum(double num, A a) {
|
|
//if ((a.getLeft() * num) < (a.getRight() * num)) {
|
|
return A(a.getLeft() * num, a.getRight() * num);
|
|
//} else {
|
|
// return A(a.getRight() * num, a.getLeft() * num);
|
|
//}
|
|
}
|
|
|
|
// îïåðàöèÿ ñëîæåíèÿ ìíîæåñòâ
|
|
A Tsaur::plusSet(A a, A b) {
|
|
return A(a.getLeft()+ b.getLeft(), a.getRight() + b.getRight());
|
|
}
|
|
|
|
// îïåðàöèÿ óìíîæåíèÿ ìíîæåñòâ
|
|
A Tsaur::multSet(A a, A b) {
|
|
//if ((a.getLeft()* b.getLeft()) < (a.getRight() * b.getRight())) {
|
|
return A(a.getLeft()* b.getLeft(), a.getRight() * b.getRight());
|
|
//} else {
|
|
// return A(a.getLeft()* b.getLeft(), a.getRight() * b.getRight());
|
|
//}
|
|
}
|
|
|
|
// ôàççèôèöèðîâàòü òîëüêî îäíó òî÷êó
|
|
// âîçâðàùàåò èíäåêñ ôóíêöèè ïðèíàäëåæíîñòè ñ ìàêñèìàëüíûì çíà÷åíèåì
|
|
A Tsaur::fuzzyfication(double value) {
|
|
// ïåðåáèðàåì âñå ôóíêöèè ïðèíàäëåæíîñòè,
|
|
// åñëè íàøëè íàèáîëüøóþ ñòåïåíü ïðèíàäëåæíîñòè, òî ôèêñèðóåì èíäåêñ ôóíêöèè
|
|
A aMax = a[0];
|
|
for (int j = 0; j < a.size(); j++) {
|
|
if (a[j].getValue(value) > aMax.getValue(value)) {
|
|
aMax = a[j];
|
|
}
|
|
}
|
|
return aMax;
|
|
}
|
|
|
|
|
|
void Tsaur::createModelForEstimation() {
|
|
defineUniversum();
|
|
A fuzzyBetta0 = fuzzyfication(xLearning[1]- xLearning[0]);
|
|
A fuzzyBetta1 = A(lb1,rb1);
|
|
A fuzzyBetta2 = A(lb2,rb2);
|
|
A fuzzyAlpha = A(0, 1);
|
|
|
|
fuzzyTs.clear();
|
|
fuzzyForecast.clear();
|
|
// ôàççèôèêàöèÿ
|
|
fuzzyTs.resize(xLearning.size());
|
|
|
|
init();
|
|
A e;
|
|
//âûïîëíÿåòñÿ ïðîõîä ìîäåëè ïî ñãëàæèâàíèþ è ïðîãíîçèðîâàíèþ countPointForecast òî÷åê
|
|
for (unsigned int t = 0; t < xLearning.size()-1+this->countPointForecast; t++) {
|
|
if (t < xLearning.size()) {
|
|
e = minusSet(fuzzyfication(xLearning[t]), fuzzyForecast[t]);
|
|
} else {
|
|
e = A(0,0);
|
|
}
|
|
S.push_back(plusSet(S[t], multSet(e, fuzzyAlpha)));
|
|
T.push_back(plusSet(plusSet(fuzzyBetta0, multSetNum(t, fuzzyBetta1)), multSetNum(t*t, fuzzyBetta2)));
|
|
fuzzyForecast.push_back(plusSet(multSetNum(alpha, S[t+1]), multSetNum((1-alpha), T[t+1])));
|
|
//fuzzyForecast.push_back(S[t+1]);
|
|
}
|
|
|
|
forecast.clear();
|
|
forecast.resize(fuzzyForecast.size());
|
|
for (unsigned int i = 0; i < fuzzyForecast.size(); i++) {
|
|
if (_finite(defuzzyfication(fuzzyForecast[i])) == 0){
|
|
forecast[i] = (x[x.size()-1]);
|
|
} else {
|
|
forecast[i] = (defuzzyfication(fuzzyForecast[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tsaur::createModel() {
|
|
defineUniversum();
|
|
A fuzzyBetta0 = fuzzyfication(x[1]- x[0]);
|
|
A fuzzyBetta1 = A(lb1,rb1);
|
|
A fuzzyBetta2 = A(lb2,rb2);
|
|
A fuzzyAlpha = A(0, 1);
|
|
|
|
fuzzyTs.clear();
|
|
fuzzyForecast.clear();
|
|
// ôàççèôèêàöèÿ
|
|
fuzzyTs.resize(x.size());
|
|
|
|
init();
|
|
A e;
|
|
//âûïîëíÿåòñÿ ïðîõîä ìîäåëè ïî ñãëàæèâàíèþ è ïðîãíîçèðîâàíèþ countPointForecast òî÷åê
|
|
for (unsigned int t = 0; t < x.size()-1+this->countPointForecast; t++) {
|
|
if (t < x.size()) {
|
|
e = minusSet(fuzzyfication(x[t]), fuzzyForecast[t]);
|
|
} else {
|
|
e = A(0,0);
|
|
}
|
|
S.push_back(plusSet(S[t], multSet(e, fuzzyAlpha)));
|
|
T.push_back(plusSet(plusSet(fuzzyBetta0, multSetNum(t, fuzzyBetta1)), multSetNum(t*t, fuzzyBetta2)));
|
|
fuzzyForecast.push_back(plusSet(multSetNum(alpha, S[t+1]), multSetNum((1-alpha), T[t+1])));
|
|
//fuzzyForecast.push_back(S[t+1]);
|
|
}
|
|
|
|
forecast.clear();
|
|
forecast.resize(fuzzyForecast.size());
|
|
for (unsigned int i = 0; i < fuzzyForecast.size(); i++) {
|
|
if (_finite(defuzzyfication(fuzzyForecast[i])) == 0){
|
|
forecast[i] = (x[x.size()-1]);
|
|
} else {
|
|
forecast[i] = (defuzzyfication(fuzzyForecast[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
// ìåòîä ïîëó÷åíèÿ îöåíêè ìîäåëè
|
|
double Tsaur::calcEstimation(Aic *aic) {
|
|
return aic->getValue(3, this->xEstimation, this->forecast);
|
|
}
|
|
Tsaur::~Tsaur(void) {
|
|
}
|
|
|
|
double Tsaur::defuzzyfication(A a) {
|
|
return a.getValueAtTop();
|
|
}
|
|
|
|
vector<double> Tsaur::defuzzyfication(vector<A> fuz) {
|
|
vector<double> result;
|
|
for (int i =0; i < fuz.size(); i++) {
|
|
result.push_back(defuzzyfication(fuz[i]));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
vector<double> Tsaur::getForecast() {
|
|
vector<double> result;
|
|
for (unsigned int i = forecast.size() - countPointForecast; i < forecast.size(); i++) {
|
|
result.push_back(forecast[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Tsaur::setParam(string paramName, double value) {
|
|
if (paramName.compare("countFuzzyParts") == 0) {
|
|
this->countFuzzyParts = value;
|
|
} else if (paramName.compare("alpha") == 0) {
|
|
this->alpha = value;
|
|
} else if (paramName.compare("lb1") == 0) {
|
|
this->lb1 = value;
|
|
} else if (paramName.compare("rb1") == 0) {
|
|
this->rb1 = value;
|
|
} else if (paramName.compare("lb2") == 0) {
|
|
this->lb2 = value;
|
|
} else if (paramName.compare("rb2") == 0) {
|
|
this->rb2 = value;
|
|
}
|
|
}
|
|
|
|
|
|
// ìåòîä ïîëó÷åíèÿ îïòèìèçèðîâàííîãî çíà÷åíèÿ îäíîãî ïàðàìåòðà
|
|
// TODO: ðåàëèçîâàòü
|
|
Param* Tsaur::optimize(Estimation *est) {
|
|
Param *optimal = new Param();
|
|
double minSmape = 99999;
|
|
for (double a = 0; a < 1; a+= 0.1) {
|
|
cout << "TSAUR " << a << " èç 1" <<"\n";;
|
|
for (double _lb1 = -10; _lb1 < 1; _lb1 += 0.2) {
|
|
for (double _rb1 = _lb1; _rb1 < 1; _rb1 += 0.2) {
|
|
for (double _lb2 = -1; _lb2 < 1; _lb2 += 0.2) {
|
|
for (double _rb2 = _lb2; _rb2 < 1; _rb2 += 0.2) {
|
|
|
|
for (double cfp = 2; cfp < 20;cfp+= 1) {
|
|
this->setParam("countFuzzyParts", cfp);
|
|
this->setParam("alpha", a);
|
|
this->setParam("lb1", _lb1);
|
|
this->setParam("rb1", _rb1);
|
|
this->setParam("lb2", _lb2);
|
|
this->setParam("rb2", _rb2);
|
|
this->createModelForEstimation();
|
|
double smapeValue = est->getValue(getXEstimation(), getForecast());
|
|
if (minSmape > smapeValue) {
|
|
minSmape = smapeValue;
|
|
optimal->countFuzzyParts = cfp;
|
|
optimal->alpha = a;
|
|
optimal->lb1 = _lb1;
|
|
optimal->lb2 = _lb2;
|
|
optimal->rb1 = _rb1;
|
|
optimal->rb2 = _rb2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return optimal;
|
|
} |