/* * 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 = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5); private ExponentialMethodParamValue beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5); private ExponentialMethodParamValue gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5); private ExponentialMethodParamValue season = new ExponentialMethodParamValue<>(Season.getInstance(), 12); private final List sComponent = new ArrayList<>(); private final List tComponent = new ArrayList<>(); private final List iComponent = new ArrayList<>(); public AddTrendAddSeason createFor(TimeSeries timeSeries) { this.originalTimeSeries = timeSeries; return this; } public AddTrendAddSeason setAlpha(ExponentialMethodParamValue alpha) { this.alpha = alpha; return this; } public AddTrendAddSeason setBeta(ExponentialMethodParamValue beta) { this.beta = beta; return this; } public AddTrendAddSeason setGamma(ExponentialMethodParamValue gamma) { this.gamma = gamma; return this; } public AddTrendAddSeason setSeason(ExponentialMethodParamValue 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 getAvailableParameters() { return Arrays.asList(alpha.getParam(), beta.getParam(), gamma.getParam(), season.getParam()); } @Override public TimeSeriesMethod setAvailableParameters(List 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; } }