create full brutforce over parameters

This commit is contained in:
Anton Romanov 2021-05-28 12:22:14 +04:00
parent ce8fd32642
commit 65fa782b10
19 changed files with 458 additions and 111 deletions

View File

@ -1,3 +1,11 @@
/*
*
* * 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.controllers; package ru.ulstu.controllers;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -9,8 +17,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.configuration.ApiConfiguration; import ru.ulstu.configuration.ApiConfiguration;
import ru.ulstu.models.ForecastParams; import ru.ulstu.models.ForecastParams;
import ru.ulstu.models.ModelingResult;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.models.exceptions.ModelingException;
import ru.ulstu.services.MethodParamBruteForce;
import ru.ulstu.services.TimeSeriesService; import ru.ulstu.services.TimeSeriesService;
@RestController @RestController
@ -18,9 +28,12 @@ import ru.ulstu.services.TimeSeriesService;
public class TimeSeriesController { public class TimeSeriesController {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final MethodParamBruteForce methodParamBruteForce;
public TimeSeriesController(TimeSeriesService timeSeriesService) { public TimeSeriesController(TimeSeriesService timeSeriesService,
MethodParamBruteForce methodParamBruteForce) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.methodParamBruteForce = methodParamBruteForce;
} }
@PostMapping("getForecast") @PostMapping("getForecast")
@ -29,4 +42,10 @@ public class TimeSeriesController {
return new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(), return new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
forecastParams.getCountForecast()), HttpStatus.OK); forecastParams.getCountForecast()), HttpStatus.OK);
} }
@PostMapping("getSmoothed")
@ApiOperation("Получить сглаженный временной ряд")
public ResponseEntity<ModelingResult> getSmoothedTimeSeries(@RequestBody TimeSeries timeSeries) throws ModelingException {
return new ResponseEntity<>(methodParamBruteForce.getSmoothedTimeSeries(timeSeries), HttpStatus.OK);
}
} }

View File

@ -1,6 +1,15 @@
/*
*
* * 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.models; package ru.ulstu.models;
import ru.ulstu.tsMethods.exponential.param.TimeSeriesMethodParamValue; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
import java.util.List; import java.util.List;
@ -8,11 +17,16 @@ public class ModelingResult {
private final TimeSeries timeSeries; private final TimeSeries timeSeries;
private final List<TimeSeriesMethodParamValue> paramValues; private final List<TimeSeriesMethodParamValue> paramValues;
private final Score score; private final Score score;
private final TimeSeriesMethod timeSeriesMethod;
public ModelingResult(TimeSeries timeSeries, List<TimeSeriesMethodParamValue> paramValues, Score score) { public ModelingResult(TimeSeries timeSeries,
List<TimeSeriesMethodParamValue> paramValues,
Score score,
TimeSeriesMethod timeSeriesMethod) {
this.timeSeries = timeSeries; this.timeSeries = timeSeries;
this.paramValues = paramValues; this.paramValues = paramValues;
this.score = score; this.score = score;
this.timeSeriesMethod = timeSeriesMethod;
} }
public TimeSeries getTimeSeries() { public TimeSeries getTimeSeries() {
@ -26,4 +40,8 @@ public class ModelingResult {
public Score getScore() { public Score getScore() {
return score; return score;
} }
public TimeSeriesMethod getTimeSeriesMethod() {
return timeSeriesMethod;
}
} }

View File

@ -1,5 +1,14 @@
/*
*
* * 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.models; package ru.ulstu.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import ru.ulstu.score.ScoreMethod; import ru.ulstu.score.ScoreMethod;
public class Score { public class Score {
@ -18,4 +27,9 @@ public class Score {
public Number getValue() { public Number getValue() {
return value; return value;
} }
@JsonIgnore
public Double getDoubleValue() {
return value.doubleValue();
}
} }

View File

@ -1,7 +1,40 @@
/*
*
* * 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.score; package ru.ulstu.score;
import ru.ulstu.models.Score;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.TimeSeriesValue;
import ru.ulstu.models.exceptions.ModelingException;
public abstract class ScoreMethod { public abstract class ScoreMethod {
public abstract Number evaluate(TimeSeries originalTimeSeries, TimeSeries modelTimeSeries); private final String name;
public ScoreMethod(String name) {
this.name = name;
}
public Score getScore(TimeSeries original, TimeSeries model) throws ModelingException {
return new Score(this, evaluate(original, model));
}
public abstract Number evaluate(TimeSeries original, TimeSeries model) throws ModelingException;
public String getName() {
return name;
}
protected TimeSeriesValue getValueOnSameDate(TimeSeriesValue timeSeriesValueToFind, TimeSeries timeSeries) throws ModelingException {
return timeSeries.getValues()
.stream()
.filter(v -> v.getDate().equals(timeSeriesValueToFind.getDate()))
.findAny()
.orElseThrow(() -> new ModelingException("Значение модельного ряда не найдено в оригинальном ряде: " + timeSeriesValueToFind.getDate()));
}
} }

View File

@ -0,0 +1,33 @@
/*
*
* * 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.score;
import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.TimeSeriesValue;
import ru.ulstu.models.exceptions.ModelingException;
import static java.lang.Math.abs;
public class Smape extends ScoreMethod {
public Smape() {
super("Smape");
}
@Override
public Number evaluate(TimeSeries original, TimeSeries model) throws ModelingException {
double sum = 0;
for (TimeSeriesValue modelValue : model.getValues()) {
double actualValue = getValueOnSameDate(modelValue, original).getValue();
sum += abs(modelValue.getValue() - actualValue)
/ ((abs(actualValue) + abs(modelValue.getValue())) / 2);
}
sum = Math.round(sum * 100) / 100;
return sum * 100 / model.getLength();
}
}

View File

@ -1,60 +1,138 @@
/*
*
* * 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.services; package ru.ulstu.services;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.models.ModelingResult; import ru.ulstu.models.ModelingResult;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.exceptions.ModelingException;
import ru.ulstu.score.ScoreMethod;
import ru.ulstu.score.Smape;
import ru.ulstu.tsMethods.MethodParameter;
import ru.ulstu.tsMethods.TimeSeriesMethod; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.exponential.param.TimeSeriesMethodParam; import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.TimeSeriesMethodParamValue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service @Service
public class MethodParamBruteForce { public class MethodParamBruteForce {
private final int DEFAULT_THREAD_COUNT = 10;
private final List<TimeSeriesMethod> methods; private final List<TimeSeriesMethod> methods;
private ExecutorService executors = Executors.newFixedThreadPool(10); private final ScoreMethod scoreMethod = new Smape();
private final ExecutorService executors = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);
public MethodParamBruteForce(List<TimeSeriesMethod> methods) { public MethodParamBruteForce(List<TimeSeriesMethod> methods) {
this.methods = methods; this.methods = methods;
} }
public TimeSeries getForecast(TimeSeries timeSeries) { public TimeSeries getForecast(TimeSeries timeSeries) {
throw new RuntimeException("Not implemented");
} }
public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) { public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) {
throw new RuntimeException("Not implemented");
} }
public TimeSeries getSmoothedTimeSeries(TimeSeries timeSeries) { public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ModelingException {
List<Future<ModelingResult>> results = new ArrayList<>(); //List<Future<ModelingResult>> results = new ArrayList<>();
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
for (TimeSeriesMethod method : methods) { for (TimeSeriesMethod method : methods) {
List<TimeSeriesMethodParam> availableParams = method.getAvailableParams(); List<List<TimeSeriesMethodParamValue>> availableParametersValues = getAvailableParametersValues(method.getAvailableParameters());
Map<TimeSeriesMethodParam, List<Number>> paramsAvailableValues = new HashMap<>(); for (List<TimeSeriesMethodParamValue> parametersValues : availableParametersValues) {
for (TimeSeriesMethodParam param : availableParams) { /*results.add(executors.submit(() -> {
paramsAvailableValues.put(param, param.getAvailableValues()); TimeSeries model = method.createFor(timeSeries)
.setAvailableParameters(parametersValues)
.getModel();
return new ModelingResult(model, parametersValues, scoreMethod.getScore(timeSeries, model));
}));*/
TimeSeries model = method.createFor(timeSeries)
.setAvailableParameters(parametersValues)
.getModel();
results2.add(new ModelingResult(model,
parametersValues,
scoreMethod.getScore(timeSeries, model),
method));
} }
List<TimeSeriesMethodParamValue> paramValues = new ArrayList<>();
results.add(executors.submit(() -> {
return new ModelingResult(method.getModel(),
method.createFor(timeSeries)
.setAvailableParams(paramValues)
.getModel());
}));
} }
TimeSeries result = null;
try { try {
result = results.get(0).get(); /*results.forEach(modelingResultFuture -> {
try {
modelingResultFuture.get();
} catch (Exception e) {
e.printStackTrace();
}
});
for (Future<ModelingResult> futureModelingResult: results) {
results2.add(futureModelingResult.get());
}*/
return results2.stream()
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
.orElse(null);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return null;
}
private List<List<TimeSeriesMethodParamValue>> getAvailableParametersValues(List<MethodParameter> availableParameters) {
List<List<TimeSeriesMethodParamValue>> result = new ArrayList<>();
Map<MethodParameter, Integer> parameterOffset = new TreeMap<>();
Map<MethodParameter, List<Number>> parameterValues = new TreeMap<>();
for (MethodParameter methodParameter : availableParameters) {
parameterOffset.put(methodParameter, 0);
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
}
while (!isAllValuesUsed(parameterOffset, parameterValues)) {
List<TimeSeriesMethodParamValue> resultRow = new ArrayList<>();
for (MethodParameter methodParameter : parameterOffset.keySet()) {
resultRow.add(new TimeSeriesMethodParamValue(methodParameter,
parameterValues.get(methodParameter).get(parameterOffset.get(methodParameter))));
}
incrementOffset(parameterOffset, parameterValues);
result.add(resultRow);
}
return result; return result;
} }
private void incrementOffset(Map<MethodParameter, Integer> parameterOffset,
Map<MethodParameter, List<Number>> parameterValues) {
List<MethodParameter> parameters = new ArrayList<>(parameterOffset.keySet());
int i = 0;
while (i < parameters.size() && !isAllValuesUsed(parameterOffset, parameterValues)) {
if (parameterOffset.get(parameters.get(i)) == parameterValues.get(parameters.get(i)).size() - 1) {
parameterOffset.put(parameters.get(i), 0);
i++;
//continue;
}
if (parameterOffset.get(parameters.get(i)) < parameterValues.get(parameters.get(i)).size()) {
parameterOffset.put(parameters.get(i), parameterOffset.get(parameters.get(i)) + 1);
return;
}
i++;
}
}
private boolean isAllValuesUsed(Map<MethodParameter, Integer> parameterOffset,
Map<MethodParameter, List<Number>> parameterValues) {
for (MethodParameter methodParameter : parameterOffset.keySet()) {
if (parameterOffset.get(methodParameter) != parameterValues.get(methodParameter).size() - 1) {
return false;
}
}
return true;
}
} }

View File

@ -16,11 +16,8 @@ import ru.ulstu.models.exceptions.ModelingException;
import ru.ulstu.tsMethods.TimeSeriesMethod; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.exponential.AddTrendAddSeason; import ru.ulstu.tsMethods.exponential.AddTrendAddSeason;
import ru.ulstu.tsMethods.exponential.NoTrendNoSeason; import ru.ulstu.tsMethods.exponential.NoTrendNoSeason;
import ru.ulstu.tsMethods.exponential.param.Alpha; import ru.ulstu.tsMethods.exponential.parameter.Alpha;
import ru.ulstu.tsMethods.exponential.param.Beta; import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.ExponentialMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.Gamma;
import ru.ulstu.tsMethods.exponential.param.Season;
@Service @Service
@ -29,24 +26,16 @@ public class TimeSeriesService {
public TimeSeries getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException { public TimeSeries getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
TimeSeriesMethod method; TimeSeriesMethod method;
method = new NoTrendNoSeason(timeSeries, new ExponentialMethodParamValue<>(new Alpha(), 0.8)); method = new NoTrendNoSeason().createFor(timeSeries).setAlpha(new ExponentialMethodParamValue<>(new Alpha(), 0.8));
method = new AddTrendAddSeason(timeSeries, method = new AddTrendAddSeason().createFor(timeSeries);
new ExponentialMethodParamValue<>(new Alpha(), 0.5),
new ExponentialMethodParamValue<>(new Beta(), 0.5),
new ExponentialMethodParamValue<>(new Gamma(), 0.5),
new ExponentialMethodParamValue<>(new Season(), 17));
return method.getForecast(countPoints); return method.getForecast(countPoints);
} }
public TimeSeries smoothTimeSeries(TimeSeries timeSeries) throws ModelingException { public TimeSeries smoothTimeSeries(TimeSeries timeSeries) throws ModelingException {
//NoTrendNoSeason nn = new NoTrendNoSeason(timeSeries, ExponentialMethodParams.of(ExponentialParamName.ALPHA, 0.8)); //NoTrendNoSeason nn = new NoTrendNoSeason(timeSeries, ExponentialMethodParams.of(ExponentialParamName.ALPHA, 0.8));
TimeSeriesMethod method; TimeSeriesMethod method;
method = new NoTrendNoSeason(timeSeries, new ExponentialMethodParamValue<>(new Alpha(), 0.8)); method = new NoTrendNoSeason().createFor(timeSeries);
method = new AddTrendAddSeason(timeSeries, method = new AddTrendAddSeason().createFor(timeSeries);
new ExponentialMethodParamValue<>(new Alpha(), 0.5),
new ExponentialMethodParamValue<>(new Beta(), 0.5),
new ExponentialMethodParamValue<>(new Gamma(), 0.5),
new ExponentialMethodParamValue<>(new Season(), 17));
return method.getModel(); return method.getModel();
} }
} }

View File

@ -0,0 +1,30 @@
/*
*
* * 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;
import java.util.List;
public abstract class MethodParameter implements Comparable {
protected String name;
public MethodParameter(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract List<Number> getAvailableValues();
@Override
public int compareTo(Object o) {
return this.name.compareTo(((MethodParameter) o).getName());
}
}

View File

@ -1,22 +1,31 @@
/*
*
* * 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; package ru.ulstu.tsMethods;
import com.fasterxml.jackson.annotation.JsonIgnore;
import ru.ulstu.TimeSeriesUtils; import ru.ulstu.TimeSeriesUtils;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.TimeSeriesValue; import ru.ulstu.models.TimeSeriesValue;
import ru.ulstu.models.exceptions.ForecastValidateException; import ru.ulstu.models.exceptions.ForecastValidateException;
import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.models.exceptions.ModelingException;
import ru.ulstu.models.exceptions.TimeSeriesValidateException; import ru.ulstu.models.exceptions.TimeSeriesValidateException;
import ru.ulstu.tsMethods.exponential.param.TimeSeriesMethodParam;
import ru.ulstu.tsMethods.exponential.param.TimeSeriesMethodParamValue;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.List; import java.util.List;
/** /**
* Наиболее общая логика моделировани и прогнозирования временных рядов * Наиболее общая логика моделировании и прогнозирования временных рядов
*/ */
public abstract class TimeSeriesMethod { public abstract class TimeSeriesMethod {
@JsonIgnore
protected TimeSeries originalTimeSeries; protected TimeSeries originalTimeSeries;
@JsonIgnore
private TimeSeries model; private TimeSeries model;
public abstract TimeSeriesMethod createFor(TimeSeries originalTimeSeries); public abstract TimeSeriesMethod createFor(TimeSeries originalTimeSeries);
@ -113,13 +122,15 @@ public abstract class TimeSeriesMethod {
} }
public TimeSeries getModel() throws ModelingException { public TimeSeries getModel() throws ModelingException {
if (model == null) { //TODO: what if always run?
makeModel(); //if (model == null) {
} makeModel();
//}
return model; return model;
} }
public abstract List<TimeSeriesMethodParam> getAvailableParams(); @JsonIgnore
public abstract List<MethodParameter> getAvailableParameters();
public abstract TimeSeriesMethod setAvailableParams(List<TimeSeriesMethodParamValue> params); public abstract TimeSeriesMethod setAvailableParameters(List<TimeSeriesMethodParamValue> parameters);
} }

View File

@ -0,0 +1,27 @@
/*
*
* * 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;
public class TimeSeriesMethodParamValue {
protected MethodParameter parameter;
protected Number value;
public TimeSeriesMethodParamValue(MethodParameter parameter, Number value) {
this.parameter = parameter;
this.value = value;
}
public MethodParameter getParameter() {
return parameter;
}
public Number getValue() {
return value;
}
}

View File

@ -11,35 +11,51 @@ package ru.ulstu.tsMethods.exponential;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.models.exceptions.ModelingException;
import ru.ulstu.models.exceptions.TimeSeriesValidateException; import ru.ulstu.models.exceptions.TimeSeriesValidateException;
import ru.ulstu.tsMethods.MethodParameter;
import ru.ulstu.tsMethods.TimeSeriesMethod; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.exponential.param.Alpha; import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.Beta; import ru.ulstu.tsMethods.exponential.parameter.Alpha;
import ru.ulstu.tsMethods.exponential.param.ExponentialMethodParamValue; import ru.ulstu.tsMethods.exponential.parameter.Beta;
import ru.ulstu.tsMethods.exponential.param.Gamma; import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.Season; import ru.ulstu.tsMethods.exponential.parameter.Gamma;
import ru.ulstu.tsMethods.exponential.parameter.Season;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
public class AddTrendAddSeason extends TimeSeriesMethod { public class AddTrendAddSeason extends TimeSeriesMethod {
private final ExponentialMethodParamValue<Alpha> alpha; private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
private final ExponentialMethodParamValue<Beta> beta; private ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
private final ExponentialMethodParamValue<Gamma> gamma; private ExponentialMethodParamValue<Gamma> gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5);
private final ExponentialMethodParamValue<Season> season; private ExponentialMethodParamValue<Season> season = new ExponentialMethodParamValue<>(Season.getInstance(), 12);
private final List<Double> sComponent = new ArrayList<>(); private final List<Double> sComponent = new ArrayList<>();
private final List<Double> tComponent = new ArrayList<>(); private final List<Double> tComponent = new ArrayList<>();
private final List<Double> iComponent = new ArrayList<>(); private final List<Double> iComponent = new ArrayList<>();
public AddTrendAddSeason(TimeSeries timeSeries, public AddTrendAddSeason createFor(TimeSeries timeSeries) {
ExponentialMethodParamValue<Alpha> alpha, this.originalTimeSeries = timeSeries;
ExponentialMethodParamValue<Beta> beta, return this;
ExponentialMethodParamValue<Gamma> gamma, }
ExponentialMethodParamValue<Season> season) throws ModelingException {
super(timeSeries); public AddTrendAddSeason setAlpha(ExponentialMethodParamValue<Alpha> alpha) {
this.alpha = alpha; this.alpha = alpha;
return this;
}
public AddTrendAddSeason setBeta(ExponentialMethodParamValue<Beta> beta) {
this.beta = beta; this.beta = beta;
return this;
}
public AddTrendAddSeason setGamma(ExponentialMethodParamValue<Gamma> gamma) {
this.gamma = gamma; this.gamma = gamma;
return this;
}
public AddTrendAddSeason setSeason(ExponentialMethodParamValue<Season> season) {
this.season = season; this.season = season;
return this;
} }
@Override @Override
@ -100,4 +116,28 @@ public class AddTrendAddSeason extends TimeSeriesMethod {
} }
return forecast; 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;
}
} }

View File

@ -8,32 +8,43 @@
package ru.ulstu.tsMethods.exponential; package ru.ulstu.tsMethods.exponential;
import org.springframework.stereotype.Component;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.tsMethods.MethodParameter;
import ru.ulstu.tsMethods.TimeSeriesMethod; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.exponential.param.Alpha; import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.Beta; import ru.ulstu.tsMethods.exponential.parameter.Alpha;
import ru.ulstu.tsMethods.exponential.param.ExponentialMethodParamValue; import ru.ulstu.tsMethods.exponential.parameter.Beta;
import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
@Component
public class AddTrendNoSeason extends TimeSeriesMethod { public class AddTrendNoSeason extends TimeSeriesMethod {
private final ExponentialMethodParamValue<Alpha> alpha; private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
private final ExponentialMethodParamValue<Beta> beta; private ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
private final List<Double> sComponent = new ArrayList<>(); private final List<Double> sComponent = new ArrayList<>();
private final List<Double> tComponent = new ArrayList<>(); private final List<Double> tComponent = new ArrayList<>();
public AddTrendNoSeason(TimeSeries timeSeries, public AddTrendNoSeason createFor(TimeSeries timeSeries) {
ExponentialMethodParamValue<Alpha> alpha, this.originalTimeSeries = timeSeries;
ExponentialMethodParamValue<Beta> beta) throws ModelingException { return this;
super(timeSeries); }
public AddTrendNoSeason setAlpha(ExponentialMethodParamValue<Alpha> alpha) {
this.alpha = alpha; this.alpha = alpha;
return this;
}
public AddTrendNoSeason setBeta(ExponentialMethodParamValue<Beta> beta) {
this.beta = beta; this.beta = beta;
return this;
} }
@Override @Override
protected TimeSeries getModelOfValidTimeSeries() throws ModelingException { protected TimeSeries getModelOfValidTimeSeries() {
sComponent.clear(); sComponent.clear();
tComponent.clear(); tComponent.clear();
sComponent.add(originalTimeSeries.getFirstValue().getValue()); sComponent.add(originalTimeSeries.getFirstValue().getValue());
@ -61,4 +72,22 @@ public class AddTrendNoSeason extends TimeSeriesMethod {
} }
return forecast; return forecast;
} }
@Override
public List<MethodParameter> getAvailableParameters() {
return Arrays.asList(alpha.getParam(), beta.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());
}
}
return this;
}
} }

View File

@ -8,21 +8,20 @@
package ru.ulstu.tsMethods.exponential; package ru.ulstu.tsMethods.exponential;
import org.springframework.stereotype.Component;
import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeries;
import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.tsMethods.MethodParameter;
import ru.ulstu.tsMethods.TimeSeriesMethod; import ru.ulstu.tsMethods.TimeSeriesMethod;
import ru.ulstu.tsMethods.exponential.param.Alpha; import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
import ru.ulstu.tsMethods.exponential.param.ExponentialMethodParam; import ru.ulstu.tsMethods.exponential.parameter.Alpha;
import ru.ulstu.tsMethods.exponential.param.ExponentialMethodParamValue; import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@Component
public class NoTrendNoSeason extends TimeSeriesMethod { public class NoTrendNoSeason extends TimeSeriesMethod {
private ExponentialMethodParamValue<Alpha> alpha; private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
private final List<Double> sComponent = new ArrayList<>(); private final List<Double> sComponent = new ArrayList<>();
public NoTrendNoSeason createFor(TimeSeries timeSeries) { public NoTrendNoSeason createFor(TimeSeries timeSeries) {
@ -36,7 +35,7 @@ public class NoTrendNoSeason extends TimeSeriesMethod {
} }
@Override @Override
protected TimeSeries getModelOfValidTimeSeries() throws ModelingException { protected TimeSeries getModelOfValidTimeSeries() {
sComponent.clear(); sComponent.clear();
sComponent.add(originalTimeSeries.getFirstValue().getValue()); sComponent.add(originalTimeSeries.getFirstValue().getValue());
TimeSeries model = new TimeSeries("Model of " + originalTimeSeries.getName()); TimeSeries model = new TimeSeries("Model of " + originalTimeSeries.getName());
@ -60,15 +59,15 @@ public class NoTrendNoSeason extends TimeSeriesMethod {
} }
@Override @Override
public List<ExponentialMethodParam> getAvailableParams() { public List<MethodParameter> getAvailableParameters() {
return Collections.singletonList(alpha.getParam()); return Collections.singletonList(alpha.getParam());
} }
@Override @Override
public TimeSeriesMethod setAvailableParams(List<ExponentialMethodParamValue> params) { public TimeSeriesMethod setAvailableParameters(List<TimeSeriesMethodParamValue> parameters) {
for (ExponentialMethodParamValue param : params) { for (TimeSeriesMethodParamValue parameter : parameters) {
if (param.getParam() instanceof Alpha) { if (parameter.getParameter() instanceof Alpha) {
alpha.setValue(param.getValue()); alpha.setValue(parameter.getValue());
} }
} }
return this; return this;

View File

@ -6,10 +6,14 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public class Alpha extends ExponentialMethodParam { public class Alpha extends ExponentialMethodParameter {
public Alpha() { public Alpha() {
super("ALPHA", 0, 1, DEFAULT_OPTIMIZATION_STEP); super("ALPHA", 0, 1, DEFAULT_OPTIMIZATION_STEP);
} }
public static Alpha getInstance() {
return new Alpha();
}
} }

View File

@ -6,10 +6,14 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public class Beta extends ExponentialMethodParam { public class Beta extends ExponentialMethodParameter {
public Beta() { public Beta() {
super("BETA", 0, 1, DEFAULT_OPTIMIZATION_STEP); super("BETA", 0, 1, DEFAULT_OPTIMIZATION_STEP);
} }
public static Beta getInstance() {
return new Beta();
}
} }

View File

@ -6,9 +6,9 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public class ExponentialMethodParamValue<T extends ExponentialMethodParam> { public class ExponentialMethodParamValue<T extends ExponentialMethodParameter> {
private final T param; private final T param;
private Number value; private Number value;

View File

@ -6,26 +6,27 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public abstract class ExponentialMethodParam { import com.fasterxml.jackson.annotation.JsonIgnore;
public static final Float DEFAULT_OPTIMIZATION_STEP = 0.01f; import ru.ulstu.tsMethods.MethodParameter;
private final String key;
import java.util.ArrayList;
import java.util.List;
public abstract class ExponentialMethodParameter extends MethodParameter {
public static final Float DEFAULT_OPTIMIZATION_STEP = 0.1f;
private final Number minValue; private final Number minValue;
private final Number maxValue; private final Number maxValue;
private final Number optimizationStep; private final Number optimizationStep;
public ExponentialMethodParam(String key, Number minValue, Number maxValue, Number optimizationStep) { public ExponentialMethodParameter(String name, Number minValue, Number maxValue, Number optimizationStep) {
this.key = key; super(name);
this.minValue = minValue; this.minValue = minValue;
this.maxValue = maxValue; this.maxValue = maxValue;
this.optimizationStep = optimizationStep; this.optimizationStep = optimizationStep;
} }
public String getKey() {
return key;
}
public Number getMinValue() { public Number getMinValue() {
return minValue; return minValue;
} }
@ -38,10 +39,20 @@ public abstract class ExponentialMethodParam {
return optimizationStep; return optimizationStep;
} }
@Override
@JsonIgnore
public List<Number> getAvailableValues() {
List<Number> values = new ArrayList<>();
for (double i = minValue.doubleValue(); i <= maxValue.doubleValue(); i += optimizationStep.doubleValue()) {
values.add(i);
}
return values;
}
@Override @Override
public String toString() { public String toString() {
return "TimeSeriesMethodParam{" + return "TimeSeriesMethodParam{" +
"key='" + key + '\'' + "name='" + name + '\'' +
", minValue=" + minValue + ", minValue=" + minValue +
", maxValue=" + maxValue + ", maxValue=" + maxValue +
", delta=" + optimizationStep + ", delta=" + optimizationStep +

View File

@ -6,10 +6,14 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public class Gamma extends ExponentialMethodParam { public class Gamma extends ExponentialMethodParameter {
public Gamma() { public Gamma() {
super("Gamma", 0, 1, DEFAULT_OPTIMIZATION_STEP); super("Gamma", 0, 1, DEFAULT_OPTIMIZATION_STEP);
} }
public static Gamma getInstance() {
return new Gamma();
}
} }

View File

@ -6,12 +6,16 @@
* *
*/ */
package ru.ulstu.tsMethods.exponential.param; package ru.ulstu.tsMethods.exponential.parameter;
public class Season extends ExponentialMethodParam { public class Season extends ExponentialMethodParameter {
private final static int DEFAULT_SEASON_OPTIMIZATION_STEP = 1; private final static int DEFAULT_SEASON_OPTIMIZATION_STEP = 1;
public Season() { public Season() {
super("Сезонность", 0, 12, DEFAULT_SEASON_OPTIMIZATION_STEP); super("Сезонность", 0, 12, DEFAULT_SEASON_OPTIMIZATION_STEP);
} }
public static Season getInstance() {
return new Season();
}
} }