308 lines
7.5 KiB
C++
308 lines
7.5 KiB
C++
#include "StdAfx.h"
|
|
#include "Dsa.h"
|
|
#include <iostream>
|
|
#include "Param.h"
|
|
|
|
Dsa::Dsa(vector<double> timeSeries, int countPointForecast){
|
|
this->countPointForecast = countPointForecast;
|
|
this->x = timeSeries;
|
|
this->partition();
|
|
}
|
|
|
|
Dsa::~Dsa(void) {
|
|
}
|
|
|
|
void Dsa::init() {
|
|
defineUniversum();
|
|
fuzzyTs.clear();
|
|
}
|
|
|
|
// îïðåäåëèòü óíèâåðñóì äëÿ âðåìåííîãî ðÿäà
|
|
// èùåì ìàêñèìóì, ìèíèìóì, ïðîèçâîäèì ðàçáèåíèå íà çàäàííûå èíòåðâàëû
|
|
void Dsa::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-sizeLabels) * baseSize, universumMin + (i+sizeLabels)*baseSize));
|
|
}
|
|
}
|
|
|
|
// ôàççèôèöèðîâàòü òîëüêî îäíó òî÷êó
|
|
// âîçâðàùàåò èíäåêñ ôóíêöèè ïðèíàäëåæíîñòè ñ ìàêñèìàëüíûì çíà÷åíèåì
|
|
int Dsa::fuzzyfication(double value) {
|
|
// ïåðåáèðàåì âñå ôóíêöèè ïðèíàäëåæíîñòè,
|
|
// åñëè íàøëè íàèáîëüøóþ ñòåïåíü ïðèíàäëåæíîñòè, òî ôèêñèðóåì èíäåêñ ôóíêöèè
|
|
int indMax = 0;
|
|
double max = a[0].getValue(value);
|
|
for (int j =0; j < a.size(); j++) {
|
|
if (a[j].getValue(value) > max) {
|
|
indMax = j;
|
|
max = a[j].getValue(value);
|
|
}
|
|
}
|
|
return indMax;
|
|
}
|
|
|
|
void Dsa::createRules() {
|
|
rulesIn.clear();
|
|
rulesIn.resize(fuzzyTs.size() - countRulesIn);
|
|
rulesOut.clear();
|
|
rulesOut.resize(fuzzyTs.size() - countRulesIn);
|
|
for (int i=0; i < fuzzyTs.size() - countRulesIn; i ++) {
|
|
vector<int> v;
|
|
v.resize(countRulesIn);
|
|
for (int j=i; j < i + countRulesIn; j++) {
|
|
v[j-i] = fuzzyTs[j];
|
|
}
|
|
rulesIn[i] = v;
|
|
rulesOut[i] = fuzzyTs[i+countRulesIn];
|
|
}
|
|
}
|
|
|
|
|
|
vector<int> Dsa::searchRules(vector<int> inPart) {
|
|
vector<int> res;
|
|
for (int i = 0; i < rulesIn.size(); i++) {
|
|
bool isRuleFound = true;
|
|
for (int j = 0; j < rulesIn[i].size(); j++) {
|
|
if (rulesIn[i][j] != inPart[j]) {
|
|
isRuleFound = false;
|
|
}
|
|
}
|
|
if (isRuleFound) {
|
|
res.push_back(rulesOut[i]);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
vector<int> Dsa::searchRulesForSeason(int index) {
|
|
vector<int> res;
|
|
int i =index - p;
|
|
while (i > 0) {
|
|
res.push_back(fuzzyfication(x[i]));
|
|
i -= p;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
void Dsa::createModelForEstimation() {
|
|
init();
|
|
fuzzyTs.resize(xLearning.size());
|
|
for (int t = 0; t < xLearning.size(); t++) {
|
|
fuzzyTs[t] = fuzzyfication(xLearning[t]);
|
|
}
|
|
createRules();
|
|
|
|
forecast.clear();
|
|
forecast.resize(fuzzyTs.size()+countPointForecast);
|
|
|
|
for (int i=0; i < fuzzyTs.size();i++) {
|
|
forecast[i] = defuzzyfication(fuzzyTs[i]);
|
|
}
|
|
int k = fuzzyTs.size();
|
|
|
|
for (int i=0; i < countPointForecast;i++) {
|
|
vector<int> lastPoints;
|
|
lastPoints.resize(countRulesIn);
|
|
for (int j = countRulesIn; j > 0; j--) {
|
|
lastPoints[countRulesIn -j] = (fuzzyTs[fuzzyTs.size() - j]);
|
|
}
|
|
|
|
double sum = 0;
|
|
|
|
// ñåçîííàÿ êîìïîíåíòà
|
|
vector<int> foundSeasonFuncs = searchRulesForSeason(fuzzyTs.size());
|
|
|
|
for (int j =0; j < foundSeasonFuncs.size(); j++) {
|
|
sum += a[foundSeasonFuncs[j]].getValueAtTop();
|
|
}
|
|
double valueAtSeason = sum / foundSeasonFuncs.size();
|
|
|
|
|
|
forecast[i+k] = (valueAtSeason);
|
|
int index = fuzzyfication(forecast[i+k]);
|
|
// äîáàâèòü ïðîãíîçóþ òî÷êó â êîíåö ðÿäà
|
|
fuzzyTs.push_back(index);
|
|
xLearning.push_back(forecast[i+k]);
|
|
createRules();
|
|
|
|
}
|
|
for (int i=0; i < countPointForecast;i++) {
|
|
if (fuzzyTs.size() > 0)
|
|
fuzzyTs.pop_back();
|
|
if (rulesIn.size() > 0)
|
|
rulesIn.pop_back();
|
|
if (rulesOut.size() > 0)
|
|
rulesOut.pop_back();
|
|
xLearning.pop_back();
|
|
}
|
|
}
|
|
|
|
|
|
// ôàççèèêàöèÿ, ñîçäàòü ñïèñîê ôóíêöèé ïðèíàäëåæíîñòè ïî âñåìó ðÿäó
|
|
void Dsa::createModel() {
|
|
init();
|
|
fuzzyTs.resize(x.size());
|
|
for (int i = 0; i < x.size(); i++) {
|
|
fuzzyTs[i] = fuzzyfication(x[i]);
|
|
}
|
|
createRules();
|
|
|
|
|
|
forecast.clear();
|
|
forecast.resize(fuzzyTs.size()+countPointForecast);
|
|
|
|
for (int i=0; i < fuzzyTs.size();i++) {
|
|
forecast[i] = defuzzyfication(fuzzyTs[i]);
|
|
}
|
|
int k = fuzzyTs.size();
|
|
|
|
for (int i=0; i < countPointForecast;i++) {
|
|
vector<int> lastPoints;
|
|
lastPoints.resize(countRulesIn);
|
|
for (int j = countRulesIn; j > 0; j--) {
|
|
lastPoints[countRulesIn -j] = (fuzzyTs[fuzzyTs.size() - j]);
|
|
}
|
|
|
|
double sum = 0;
|
|
|
|
// ñåçîííàÿ êîìïîíåíòà
|
|
vector<int> foundSeasonFuncs = searchRulesForSeason(fuzzyTs.size());
|
|
|
|
for (int j =0; j < foundSeasonFuncs.size(); j++) {
|
|
sum += a[foundSeasonFuncs[j]].getValueAtTop();
|
|
}
|
|
double valueAtSeason = sum / foundSeasonFuncs.size();
|
|
|
|
|
|
forecast[i+k] = (valueAtSeason);
|
|
int index = fuzzyfication(forecast[i+k]);
|
|
// äîáàâèòü ïðîãíîçóþ òî÷êó â êîíåö ðÿäà
|
|
fuzzyTs.push_back(index);
|
|
x.push_back(forecast[i+k]);
|
|
createRules();
|
|
|
|
}
|
|
for (int i=0; i < countPointForecast;i++) {
|
|
if (fuzzyTs.size() > 0)
|
|
fuzzyTs.pop_back();
|
|
if (rulesIn.size() > 0)
|
|
rulesIn.pop_back();
|
|
if (rulesOut.size() > 0)
|
|
rulesOut.pop_back();
|
|
x.pop_back();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
vector<double> Dsa::getForecast() {
|
|
vector<double> result;
|
|
for (unsigned int i = forecast.size() - countPointForecast; i < forecast.size(); i++) {
|
|
result.push_back(forecast[i]);
|
|
}
|
|
return forecast;
|
|
}
|
|
|
|
double Dsa::defuzzyfication(int index) {
|
|
return this->a[index].getValueAtTop();
|
|
}
|
|
|
|
void Dsa::setParam(string paramName, double value) {
|
|
if (paramName.compare("countFuzzyParts") == 0) {
|
|
this->countFuzzyParts = value;
|
|
} else if (paramName.compare("countRulesIn") == 0) {
|
|
if (this->xLearning.size() < value) {
|
|
this->countRulesIn = this->xLearning.size();
|
|
} else {
|
|
this->countRulesIn = value;
|
|
}
|
|
|
|
} else if (paramName.compare("p") == 0) {
|
|
if (value <= 0) {
|
|
this->p = 1;
|
|
} else {
|
|
this->p = value;
|
|
}
|
|
} else if (paramName.compare("sizeLabels") == 0) {
|
|
this->sizeLabels = value;
|
|
}
|
|
|
|
if (paramName.compare("0") == 0) {
|
|
this->countFuzzyParts = value * 100;
|
|
} else if (paramName.compare("1") == 0) {
|
|
if (this->xLearning.size() < value * 5) {
|
|
this->countRulesIn = this->xLearning.size();
|
|
} else {
|
|
this->countRulesIn = value * 5;
|
|
}
|
|
} else if (paramName.compare("2") == 0) {
|
|
this->sizeLabels = value * 100;
|
|
}
|
|
}
|
|
|
|
|
|
// ìåòîä ïîëó÷åíèÿ îöåíêè ìîäåëè
|
|
double Dsa::calcEstimation(Aic *aic) {
|
|
return aic->getValue(3, this->xEstimation, this->forecast);
|
|
}
|
|
|
|
// ìåòîä ïîëó÷åíèÿ îïòèìèçèðîâàííîãî çíà÷åíèÿ îäíîãî ïàðàìåòðà
|
|
// TODO: ðåàëèçîâàòü
|
|
Param* Dsa::optimize(Estimation *est) {
|
|
Param *optimal = new Param();
|
|
double minSmape = 99999;
|
|
for (double cfp = 2; cfp < 50;cfp+= 1) {
|
|
cout << "DSA " << cfp << " èç 50" <<"\n";;
|
|
for (double cri = 1; cri < 5;cri+=1) {
|
|
for (double sizeLabels = 1; sizeLabels < 50; sizeLabels+= 1) {
|
|
this->setParam("countRulesIn", cri);
|
|
this->setParam("countFuzzyParts", cfp);
|
|
this->setParam("sizeLabels", sizeLabels);
|
|
double smapeValue = 0;
|
|
int maxShift = 5;
|
|
if (maxShift > this->countPointForecast) {
|
|
maxShift = this->countPointForecast-1;
|
|
}
|
|
this->countPointForecast -= maxShift;
|
|
for (int shift=0; shift <= maxShift; shift++) {
|
|
this->partition();
|
|
this->createModelForEstimation();
|
|
smapeValue += est->getValue(x, getForecast());
|
|
this->countPointForecast++;
|
|
}
|
|
this->countPointForecast--;
|
|
smapeValue = smapeValue / maxShift;
|
|
if (minSmape > smapeValue) {
|
|
minSmape = smapeValue;
|
|
optimal->countFuzzyParts = cfp;
|
|
optimal->countRulesIn = cri;
|
|
optimal->estim = smapeValue;
|
|
optimal->sizeLabels = sizeLabels;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return optimal;
|
|
}
|
|
|
|
int Dsa::getNamberParam() {
|
|
return 3;
|
|
}
|