145 lines
6.3 KiB
Java
145 lines
6.3 KiB
Java
/*
|
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
*
|
|
*/
|
|
|
|
package ru.ulstu.tsMethods.exponential;
|
|
|
|
import org.springframework.stereotype.Component;
|
|
import ru.ulstu.models.TimeSeries;
|
|
import ru.ulstu.models.exceptions.ModelingException;
|
|
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
|
import ru.ulstu.tsMethods.MethodParameter;
|
|
import ru.ulstu.tsMethods.TimeSeriesMethod;
|
|
import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
|
|
import ru.ulstu.tsMethods.exponential.parameter.Alpha;
|
|
import ru.ulstu.tsMethods.exponential.parameter.Beta;
|
|
import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
|
|
import ru.ulstu.tsMethods.exponential.parameter.Gamma;
|
|
import ru.ulstu.tsMethods.exponential.parameter.Season;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
@Component
|
|
public class AddTrendAddSeason extends TimeSeriesMethod {
|
|
private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
|
private ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
|
private ExponentialMethodParamValue<Gamma> gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5);
|
|
private ExponentialMethodParamValue<Season> season = new ExponentialMethodParamValue<>(Season.getInstance(), 12);
|
|
private final List<Double> sComponent = new ArrayList<>();
|
|
private final List<Double> tComponent = new ArrayList<>();
|
|
private final List<Double> iComponent = new ArrayList<>();
|
|
|
|
public AddTrendAddSeason createFor(TimeSeries timeSeries) {
|
|
this.originalTimeSeries = timeSeries;
|
|
return this;
|
|
}
|
|
|
|
public AddTrendAddSeason setAlpha(ExponentialMethodParamValue<Alpha> alpha) {
|
|
this.alpha = alpha;
|
|
return this;
|
|
}
|
|
|
|
public AddTrendAddSeason setBeta(ExponentialMethodParamValue<Beta> beta) {
|
|
this.beta = beta;
|
|
return this;
|
|
}
|
|
|
|
public AddTrendAddSeason setGamma(ExponentialMethodParamValue<Gamma> gamma) {
|
|
this.gamma = gamma;
|
|
return this;
|
|
}
|
|
|
|
public AddTrendAddSeason setSeason(ExponentialMethodParamValue<Season> season) {
|
|
this.season = season;
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
protected TimeSeries getModelOfValidTimeSeries() throws ModelingException {
|
|
sComponent.clear();
|
|
tComponent.clear();
|
|
iComponent.clear();
|
|
iComponent.add(1.0);
|
|
sComponent.add(originalTimeSeries.getFirstValue().getValue());
|
|
tComponent.add(0.0);
|
|
TimeSeries model = new TimeSeries("Model of " + originalTimeSeries.getName());
|
|
model.addValue(originalTimeSeries.getFirstValue());
|
|
//выполняется проход модели по сглаживанию
|
|
for (int t = 1; t < season.getValue().intValue(); t++) {
|
|
sComponent.add(alpha.getDoubleValue() * originalTimeSeries.getNumericValue(t)
|
|
+ (1 - alpha.getDoubleValue())
|
|
* (sComponent.get(t - 1) + tComponent.get(t - 1)));
|
|
tComponent.add(beta.getDoubleValue()
|
|
* (sComponent.get(t) - sComponent.get(t - 1))
|
|
+ (1 - beta.getDoubleValue()) * tComponent.get(t - 1));
|
|
iComponent.add(gamma.getDoubleValue() * originalTimeSeries.getNumericValue(t) / sComponent.get(sComponent.size() - 1)
|
|
+ (1 - gamma.getDoubleValue()) * iComponent.get(0));
|
|
model.addValue(originalTimeSeries.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
|
}
|
|
for (int t = season.getIntValue();
|
|
t < originalTimeSeries.getValues().size(); t++) {
|
|
sComponent.add(alpha.getDoubleValue() * originalTimeSeries.getNumericValue(t)
|
|
/ iComponent.get(t - season.getIntValue())
|
|
+ (1 - alpha.getDoubleValue())
|
|
* (sComponent.get(t - 1) + tComponent.get(t - 1)));
|
|
|
|
tComponent.add(beta.getDoubleValue()
|
|
* (sComponent.get(t) - sComponent.get(t - 1))
|
|
+ (1 - beta.getDoubleValue()) * tComponent.get(t - 1));
|
|
|
|
iComponent.add(gamma.getDoubleValue() * originalTimeSeries.getNumericValue(t) / sComponent.get(sComponent.size() - 1)
|
|
+ (1 - gamma.getDoubleValue()) * iComponent.get(t - season.getIntValue()));
|
|
model.addValue(originalTimeSeries.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
|
}
|
|
return model;
|
|
}
|
|
|
|
@Override
|
|
protected void validateAdditionalParams() throws ModelingException {
|
|
if (originalTimeSeries.getLength() < season.getIntValue()) {
|
|
throw new TimeSeriesValidateException("Период больше чем длина ряда");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected TimeSeries makeForecast(TimeSeries forecast) throws ModelingException {
|
|
TimeSeries model = getModel();
|
|
for (int t = 1; t < forecast.getLength(); t++) {
|
|
iComponent.add(gamma.getDoubleValue() * forecast.getNumericValue(t - 1) / sComponent.get(sComponent.size() - 1)
|
|
+ (1 - gamma.getDoubleValue()) * iComponent.get(t + model.getLength() - season.getIntValue()));
|
|
|
|
forecast.getValues().get(t).setValue((sComponent.get(sComponent.size() - 1) + tComponent.get(tComponent.size() - 1) * t)
|
|
* iComponent.get(t + model.getLength() - season.getIntValue()));
|
|
}
|
|
return forecast;
|
|
}
|
|
|
|
@Override
|
|
public List<MethodParameter> getAvailableParameters() {
|
|
return Arrays.asList(alpha.getParam(), beta.getParam(), gamma.getParam(), season.getParam());
|
|
}
|
|
|
|
@Override
|
|
public TimeSeriesMethod setAvailableParameters(List<TimeSeriesMethodParamValue> parameters) {
|
|
for (TimeSeriesMethodParamValue parameter : parameters) {
|
|
if (parameter.getParameter() instanceof Alpha) {
|
|
alpha.setValue(parameter.getValue());
|
|
}
|
|
if (parameter.getParameter() instanceof Beta) {
|
|
beta.setValue(parameter.getValue());
|
|
}
|
|
if (parameter.getParameter() instanceof Gamma) {
|
|
gamma.setValue(parameter.getValue());
|
|
}
|
|
if (parameter.getParameter() instanceof Season) {
|
|
season.setValue(parameter.getValue());
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
}
|