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

559 lines
11 KiB
C++

#include "stdafx.h"
#include "Transformation.h"
#include "Median.h"
#include <math.h>
#include <vector>
#include <iostream>
#include <limits>
Transformation::Transformation(vector <double> ts)
{
setTimeSeries(ts);
INFINITY = std::numeric_limits<double>::infinity();
}
Transformation::~Transformation()
{
}
void Transformation::setTimeSeries(vector<double> ts){
TimeSeries = ts;
tsSizeValue = ts.size();
tsShiftValue = 0;
GeometricAverage = 1;
valueMean = 0;
double min = 0;
for (int i = 0; i < tsSizeValue; i++)
{
if ((TimeSeries[i] < 0) && (TimeSeries[i] < min))
{
min = TimeSeries[i];
}
GeometricAverage = GeometricAverage * TimeSeries[i];
valueMean += TimeSeries[i];
}
if (min != 0)
{
tsShiftValue = abs(min) + 1;
}
if (tsSizeValue != 0)
{
GeometricAverage = pow(GeometricAverage, 1 / tsSizeValue);
valueMean /= tsSizeValue;
}
}
int Transformation::sign(double value)
{
if (value >= 0)
return 1;
else
return -1;
}
double Transformation::lambdaEstimationGuerrero(double param){
double result;
int begin; // iterator
int end; // iterator
double sumRow; // sum row matrix
double sumSd; // sum for estimation standard deviation
double meanRat;
int lengthPeriod = 2;
if (seasonalPeriod > lengthPeriod)
{
lengthPeriod = seasonalPeriod;
}
int amtlengthPeriod = floor((double)tsSizeValue / lengthPeriod);
int shift = tsSizeValue - floor((double)amtlengthPeriod * lengthPeriod);
vector <double> mean(amtlengthPeriod); // mean row matrix
vector <double> sd(amtlengthPeriod); // standard deviation
vector <double> rat(amtlengthPeriod);
for (int i = 0; i < amtlengthPeriod; i++)
{
begin = shift + i * lengthPeriod;
end = begin + lengthPeriod;
sumRow = 0;
for (int row = begin; row < end; row++)
{
sumRow += TimeSeries[row];
}
mean[i] = sumRow / lengthPeriod;
sumSd = 0;
for (int row = begin; row < end; row++)
{
sumSd += pow(TimeSeries[row] - mean[i], 2);
}
sd[i] = sqrt(sumSd / (lengthPeriod - 1));
}
for (int i = 0; i < amtlengthPeriod; i++)
{
rat[i] = sd[i] / (pow(mean[i], 1 - param));
}
meanRat = 0;
for (int i = 0; i < amtlengthPeriod; i++)
{
meanRat += rat[i];
}
meanRat /= amtlengthPeriod;
sumSd = 0;
for (int i = 0; i < amtlengthPeriod; i++)
{
sumSd += pow(rat[i] - meanRat, 2);
}
result = sqrt(sumSd / (amtlengthPeriod - 1)) / meanRat;
return result;
}
void Transformation::lambdaEstimation(){
double cv = INFINITY; //cv - coefficient of variation
for (double i = -1; i <= 2; i += 0.01)
{
//double i = 0.7;
double result = lambdaEstimationGuerrero(i);
if (result < cv)
{
cv = result;
lambda = i;
}
}
}
vector<double> Transformation::BoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = log(TimeSeries[i] + tsShiftValue);
}
}
else
{
for (int i = 0; i < TimeSeries.size(); i++)
{
tsTransformation[i] = (pow(TimeSeries[i] + tsShiftValue, lambda) - 1) / lambda;
}
}
return tsTransformation;
}
vector<double> Transformation::invBoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = exp(TimeSeries[i]) - tsShiftValue;
}
}
else
{
for (int i = 0; i < TimeSeries.size(); i++)
{
tsTransformation[i] = pow((lambda * TimeSeries[i] + 1), 1 / lambda) - tsShiftValue;
}
}
return tsTransformation;
}
vector<double> Transformation::ExponentialTransformation(){
vector <double> tsTransformation(tsSizeValue);
if (lambda != 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = (exp(TimeSeries[i] * lambda) - 1) / lambda;
}
}
return tsTransformation;
}
vector<double> Transformation::invExponentialTransformation(){
vector <double> tsTransformation(tsSizeValue);
if (lambda != 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = log(1 + TimeSeries[i] * lambda) / lambda;
}
}
return tsTransformation;
}
vector<double> Transformation::ModulusTransformation(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = sign(TimeSeries[i]) * log(abs(TimeSeries[i]) + 1);
}
}
else
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = sign(TimeSeries[i]) * (pow(abs(TimeSeries[i]) + 1, lambda) - 1) / lambda;
}
}
return tsTransformation;
}
vector<double> Transformation::invModulusTransformation(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = sign(TimeSeries[i]) * (exp(abs(TimeSeries[i])) - 1);
}
}
else
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = pow(TimeSeries[i] * lambda / sign(TimeSeries[i]) + 1, 1 / lambda) - 1;
}
}
return tsTransformation;
}
vector<double> Transformation::AsymptoticBoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda > 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = (sign(TimeSeries[i]) * pow(abs(TimeSeries[i]), lambda) - 1) / lambda;
}
}
return tsTransformation;
}
vector<double> Transformation::invAsymptoticBoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda > 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = pow((TimeSeries[i] * lambda - 1) / sign(TimeSeries[i]), 1 / lambda);
}
}
return tsTransformation;
}
vector<double> Transformation::ModifiedBoxCox(){
vector <double> tsTransformation(tsSizeValue);
for (int i = 0; i < tsSizeValue; i++)
{
if ((TimeSeries[i] >= 0) && (lambda != 0))
{
tsTransformation[i] = (pow(TimeSeries[i] + 1, lambda) - 1) / lambda;
}
else if ((TimeSeries[i] >= 0) && (lambda == 0))
{
tsTransformation[i] = log(TimeSeries[i] + 1);
}
else if ((TimeSeries[i] < 0) && (lambda != 0))
{
tsTransformation[i] = -(pow(-TimeSeries[i] + 1, 2 - lambda) - 1) / (2 - lambda);
}
else if ((TimeSeries[i] < 0) && (lambda == 0))
{
tsTransformation[i] = -log(-TimeSeries[i] + 1);
}
}
return tsTransformation;
}
vector<double> Transformation::invModifiedBoxCox(){
vector <double> tsTransformation(tsSizeValue);
for (int i = 0; i < tsSizeValue; i++)
{
if ((TimeSeries[i] >= 0) && (lambda != 0))
{
tsTransformation[i] = pow(TimeSeries[i] * lambda + 1, 1 / lambda) - 1;
}
else if ((TimeSeries[i] >= 0) && (lambda == 0))
{
tsTransformation[i] = exp(TimeSeries[i]) - 1;
}
else if ((TimeSeries[i] < 0) && (lambda != 2))
{
tsTransformation[i] = -(pow(-(TimeSeries[i] * (2 - lambda) - 1), 1 / (2 - lambda)) - 1);
}
else if ((TimeSeries[i] < 0) && (lambda == 2))
{
tsTransformation[i] = -exp(-TimeSeries[i]) + 1;
}
}
return tsTransformation;
}
vector<double> Transformation::NormalizedBoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = GeometricAverage * log(TimeSeries[i]);
}
}
else
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = (pow(TimeSeries[i], lambda) - 1) / (lambda * pow(GeometricAverage, lambda - 1));
}
}
return tsTransformation;
}
vector<double> Transformation::invNormalizedBoxCox(){
vector <double> tsTransformation(tsSizeValue);
if (lambda == 0)
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = exp(TimeSeries[i] / GeometricAverage);
}
}
else
{
for (int i = 0; i < tsSizeValue; i++)
{
tsTransformation[i] = pow(TimeSeries[i] * lambda * pow(GeometricAverage, lambda - 1) + 1, 1 / lambda);
}
}
return tsTransformation;
}
vector<double> Transformation::Deseasonalization(int seasonalPeriod){
vector <double> tsDeseasonalization(tsSizeValue);
SeasonalIndex.resize(seasonalPeriod - 1);
int tsShift = 0;
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
if (tsSizeValue % seasonalPeriod != 0)
{
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod;
}
// считаем средние сезоанальные индексы
Median *est = new Median();
SeasonalIndex = est->getValue(TimeSeries, seasonalPeriod);
// получаем итог
for (int i = 0; i < amtSeasonalPeriod; i++)
{
int begin = tsShift + i * seasonalPeriod;
int end = begin + seasonalPeriod;
for (int ii = begin; ii < end; ii++)
{
tsDeseasonalization[ii] = TimeSeries[ii] / SeasonalIndex[i];
}
}
return tsDeseasonalization;
}
vector<double> Transformation::invDeseasonalization(){
vector <double> tsDeseasonalization(tsSizeValue);
int tsShift = 0;
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
if (tsSizeValue % seasonalPeriod != 0)
{
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod - 1;
}
for (int i = 0; i < amtSeasonalPeriod; i++)
{
int begin = tsShift + i * seasonalPeriod;
int end = begin + seasonalPeriod;
for (int ii = begin; ii < end; ii++)
{
tsDeseasonalization[ii] = TimeSeries[ii] * SeasonalIndex[i];
}
}
return tsDeseasonalization;
}
vector<double> Transformation::getSeasonalIndex(){
return SeasonalIndex;
}
vector <double> Transformation::Aggregation(int seasonalPeriod){
int tsShift = 0;
int amtSeasonalPeriod = tsSizeValue / seasonalPeriod;
vector <double> tsAggregation(amtSeasonalPeriod);
if (tsSizeValue % seasonalPeriod != 0)
{
tsShift = tsSizeValue - amtSeasonalPeriod * seasonalPeriod;
}
// получаем итог
for (int i = 0; i < amtSeasonalPeriod; i++)
{
int begin = tsShift + i * seasonalPeriod;
int end = begin + seasonalPeriod;
for (int ii = begin; ii < end; ii++)
{
tsAggregation[i] += TimeSeries[ii];
}
}
return tsAggregation;
}
vector <double> Transformation::invAggregation(){
int sumSeasonalPeriod = tsSizeValue * seasonalPeriod;
vector <double> tsDeaggregation(sumSeasonalPeriod);
// получаем итог
for (int i = 0; i < tsSizeValue; i++)
{
int begin = i * seasonalPeriod;
int end = begin + seasonalPeriod;
for (int ii = begin; ii < end; ii++)
{
tsDeaggregation[ii] = TimeSeries[i] / seasonalPeriod;
}
}
return tsDeaggregation;
}
vector<double> Transformation::Normalization(){
vector <double> tsNormalization(tsSizeValue);
valueSd = 0;
for (int i = 0; i < tsSizeValue; i++)
{
valueSd += pow(TimeSeries[i] - valueMean, 2);
}
valueSd = sqrt(valueSd / (tsSizeValue - 1));
for (int i = 0; i < tsSizeValue; i++)
{
tsNormalization[i] = (TimeSeries[i] - valueMean) / valueSd;
}
return tsNormalization;
}
vector <double> Transformation::invNormalization()
{
vector <double> tsNormalization(tsSizeValue);
for (int i = 0; i < tsSizeValue; i++)
{
tsNormalization[i] = TimeSeries[i] * valueSd + valueMean;
}
return tsNormalization;
}