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

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;
}