#1 -- add choosing method in api
This commit is contained in:
parent
e13ba082d8
commit
d5c99caeb3
@ -20,6 +20,7 @@ import ru.ulstu.method.Method;
|
|||||||
import ru.ulstu.service.TimeSeriesService;
|
import ru.ulstu.service.TimeSeriesService;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.validation.Valid;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -37,7 +38,7 @@ public class TimeSeriesController {
|
|||||||
|
|
||||||
@PostMapping("getForecast")
|
@PostMapping("getForecast")
|
||||||
@Operation(description = "Получить прогноз временного ряда любым методом")
|
@Operation(description = "Получить прогноз временного ряда любым методом")
|
||||||
public ResponseEntity<ModelingResult> getForecastTimeSeries(@RequestBody ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
public ResponseEntity<ModelingResult> getForecastTimeSeries(@RequestBody @Valid ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
||||||
LOGGER.info("Forecast: " + forecastParams);
|
LOGGER.info("Forecast: " + forecastParams);
|
||||||
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
||||||
@ -58,10 +59,11 @@ public class TimeSeriesController {
|
|||||||
|
|
||||||
@PostMapping("getSpecificMethodForecast")
|
@PostMapping("getSpecificMethodForecast")
|
||||||
@Operation(description = "Получить прогноз временного ряда указанным методом")
|
@Operation(description = "Получить прогноз временного ряда указанным методом")
|
||||||
public ResponseEntity<ModelingResult> getForecastTimeSeriesSpecificMethod(@RequestBody ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
public ResponseEntity<ModelingResult> getForecastTimeSeriesSpecificMethod(@RequestBody @Valid ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
||||||
LOGGER.info("Forecast: " + forecastParams);
|
LOGGER.info("Forecast: " + forecastParams);
|
||||||
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
||||||
|
forecastParams.getMethodClassName(),
|
||||||
forecastParams.getCountForecast()), HttpStatus.OK);
|
forecastParams.getCountForecast()), HttpStatus.OK);
|
||||||
LOGGER.info("Forecast result complete");
|
LOGGER.info("Forecast result complete");
|
||||||
return result;
|
return result;
|
||||||
|
@ -2,9 +2,14 @@ package ru.ulstu.datamodel;
|
|||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class ForecastParams {
|
public class ForecastParams {
|
||||||
|
@NotNull
|
||||||
private TimeSeries originalTimeSeries;
|
private TimeSeries originalTimeSeries;
|
||||||
|
@NotNull
|
||||||
private int countForecast;
|
private int countForecast;
|
||||||
|
private String methodClassName;
|
||||||
|
|
||||||
public TimeSeries getOriginalTimeSeries() {
|
public TimeSeries getOriginalTimeSeries() {
|
||||||
return originalTimeSeries;
|
return originalTimeSeries;
|
||||||
@ -22,6 +27,14 @@ public class ForecastParams {
|
|||||||
this.countForecast = countForecast;
|
this.countForecast = countForecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMethodClassName() {
|
||||||
|
return methodClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethodClassName(String methodClassName) {
|
||||||
|
this.methodClassName = methodClassName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ForecastParams{" +
|
return "ForecastParams{" +
|
||||||
|
@ -3,7 +3,7 @@ package ru.ulstu.db.model;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class TimeSeriesSet {
|
public class TimeSeriesSet {
|
||||||
private String key;
|
private final String key;
|
||||||
|
|
||||||
public TimeSeriesSet(File dir) {
|
public TimeSeriesSet(File dir) {
|
||||||
this.key = dir.getName();
|
this.key = dir.getName();
|
||||||
|
@ -86,7 +86,9 @@ public abstract class Method {
|
|||||||
Model model = getModel(timeSeries, parameters);
|
Model model = getModel(timeSeries, parameters);
|
||||||
TimeSeries forecast = generateEmptyForecastPoints(model.getTimeSeriesModel(), countPoints);
|
TimeSeries forecast = generateEmptyForecastPoints(model.getTimeSeriesModel(), countPoints);
|
||||||
forecast.getFirstValue().setValue(model.getTimeSeriesModel().getLastValue().getValue());
|
forecast.getFirstValue().setValue(model.getTimeSeriesModel().getLastValue().getValue());
|
||||||
return getForecastWithValidParams(model, forecast);
|
forecast = getForecastWithValidParams(model, forecast);
|
||||||
|
forecast.getFirstValue().setValue(timeSeries.getLastValue().getValue());
|
||||||
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TimeSeries generateEmptyForecastPoints(TimeSeries model, int countPointForecast) {
|
protected TimeSeries generateEmptyForecastPoints(TimeSeries model, int countPointForecast) {
|
||||||
|
@ -37,9 +37,9 @@ class MethodParamBruteForce {
|
|||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelingResult getForecast(TimeSeries timeSeries, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
private ModelingResult getForecastByMethods(TimeSeries timeSeries, List<Method> methods, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> futureModelingResults = new ArrayList<>();
|
||||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
List<ModelingResult> modelingResults = new CopyOnWriteArrayList<>();
|
||||||
final int countPoints = (countPointsForecast > timeSeries.getLength()) ? timeSeries.getLength() / 3 : countPointsForecast;
|
final int countPoints = (countPointsForecast > timeSeries.getLength()) ? timeSeries.getLength() / 3 : countPointsForecast;
|
||||||
TimeSeries reducedTimeSeries = new TimeSeries(timeSeries.getValues().stream().limit(timeSeries.getLength() - countPoints).collect(Collectors.toList()),
|
TimeSeries reducedTimeSeries = new TimeSeries(timeSeries.getValues().stream().limit(timeSeries.getLength() - countPoints).collect(Collectors.toList()),
|
||||||
"test part of " + timeSeries.getKey());
|
"test part of " + timeSeries.getKey());
|
||||||
@ -52,7 +52,7 @@ class MethodParamBruteForce {
|
|||||||
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
||||||
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||||
if (methodInstance.canMakeForecast(reducedTimeSeries, parametersValues, countPoints)) {
|
if (methodInstance.canMakeForecast(reducedTimeSeries, parametersValues, countPoints)) {
|
||||||
results.add(executors.submit(() -> {
|
futureModelingResults.add(executors.submit(() -> {
|
||||||
TimeSeries forecast = syncDates(methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints), timeSeries);
|
TimeSeries forecast = syncDates(methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints), timeSeries);
|
||||||
return new ModelingResult(forecast, null,
|
return new ModelingResult(forecast, null,
|
||||||
parametersValues,
|
parametersValues,
|
||||||
@ -62,17 +62,39 @@ class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Future<ModelingResult> futureModelingResult : results) {
|
for (Future<ModelingResult> futureModelingResult : futureModelingResults) {
|
||||||
results2.add(futureModelingResult.get());
|
modelingResults.add(futureModelingResult.get());
|
||||||
}
|
}
|
||||||
ModelingResult bestResult = results2.stream()
|
|
||||||
|
return getBestResultForecast(modelingResults, timeSeries, countPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, String methodClassName, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
Method method = methods.stream()
|
||||||
|
.filter(m -> m.getClass().getSimpleName().equals(methodClassName))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(() -> new ModelingException("Неизвестный метод прогнозирования"));
|
||||||
|
return getForecastByMethods(timeSeries, List.of(method), countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, Method method, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return getForecastByMethods(timeSeries, List.of(method), countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return getForecastByMethods(timeSeries, methods, countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelingResult getBestResultForecast(List<ModelingResult> modelingResults,
|
||||||
|
TimeSeries timeSeries,
|
||||||
|
int countPoints) throws ModelingException {
|
||||||
|
ModelingResult bestResult = modelingResults.stream()
|
||||||
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
||||||
.orElseThrow(() -> new ModelingException("Лучший метод не найден"));
|
.orElseThrow(() -> new ModelingException("Лучший метод не найден"));
|
||||||
|
|
||||||
TimeSeries forecast = bestResult.getTimeSeriesMethod().getForecast(timeSeries,
|
TimeSeries forecast = bestResult.getTimeSeriesMethod().getForecast(timeSeries,
|
||||||
bestResult.getParamValues(),
|
bestResult.getParamValues(),
|
||||||
countPoints);
|
countPoints);
|
||||||
forecast.getValue(0).setValue(timeSeries.getNumericValue(timeSeries.getLength() - 1));
|
|
||||||
|
|
||||||
return new ModelingResult(forecast,
|
return new ModelingResult(forecast,
|
||||||
bestResult.getTimeSeries(),
|
bestResult.getTimeSeries(),
|
||||||
@ -90,9 +112,12 @@ class MethodParamBruteForce {
|
|||||||
return forecast;
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) {
|
public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) {
|
||||||
throw new RuntimeException("Not implemented");
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||||
@ -133,7 +158,7 @@ class MethodParamBruteForce {
|
|||||||
parameterOffset.put(methodParameter, 0);
|
parameterOffset.put(methodParameter, 0);
|
||||||
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
||||||
}
|
}
|
||||||
while (!isAllValuesUsed(parameterOffset, parameterValues)) {
|
while (isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
||||||
List<MethodParamValue> resultRow = new ArrayList<>();
|
List<MethodParamValue> resultRow = new ArrayList<>();
|
||||||
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
||||||
resultRow.add(new MethodParamValue(methodParameter,
|
resultRow.add(new MethodParamValue(methodParameter,
|
||||||
@ -149,7 +174,7 @@ class MethodParamBruteForce {
|
|||||||
Map<MethodParameter, List<Number>> parameterValues) {
|
Map<MethodParameter, List<Number>> parameterValues) {
|
||||||
List<MethodParameter> parameters = new ArrayList<>(parameterOffset.keySet());
|
List<MethodParameter> parameters = new ArrayList<>(parameterOffset.keySet());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < parameters.size() && !isAllValuesUsed(parameterOffset, parameterValues)) {
|
while (i < parameters.size() && isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
||||||
if (parameterOffset.get(parameters.get(i)) == parameterValues.get(parameters.get(i)).size() - 1) {
|
if (parameterOffset.get(parameters.get(i)) == parameterValues.get(parameters.get(i)).size() - 1) {
|
||||||
parameterOffset.put(parameters.get(i), 0);
|
parameterOffset.put(parameters.get(i), 0);
|
||||||
i++;
|
i++;
|
||||||
@ -163,15 +188,15 @@ class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAllValuesUsed(Map<MethodParameter, Integer> parameterOffset,
|
private boolean isNotAllParameterValuesUsed(Map<MethodParameter, Integer> parameterOffset,
|
||||||
Map<MethodParameter, List<Number>> parameterValues) {
|
Map<MethodParameter, List<Number>> parameterValues) {
|
||||||
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
||||||
if (parameterOffset.get(methodParameter) != parameterValues.get(methodParameter).size() - 1) {
|
if (parameterOffset.get(methodParameter) != parameterValues.get(methodParameter).size() - 1) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Method> getAvailableMethods() {
|
public List<Method> getAvailableMethods() {
|
||||||
return methods;
|
return methods;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.ulstu.service;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.ulstu.datamodel.ModelingResult;
|
import ru.ulstu.datamodel.ModelingResult;
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
@ -14,15 +15,22 @@ import java.util.concurrent.ExecutionException;
|
|||||||
@Service
|
@Service
|
||||||
public class TimeSeriesService {
|
public class TimeSeriesService {
|
||||||
private final MethodParamBruteForce methodParamBruteForce;
|
private final MethodParamBruteForce methodParamBruteForce;
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
public TimeSeriesService(MethodParamBruteForce methodParamBruteForce) {
|
public TimeSeriesService(MethodParamBruteForce methodParamBruteForce,
|
||||||
|
ApplicationContext applicationContext) {
|
||||||
this.methodParamBruteForce = methodParamBruteForce;
|
this.methodParamBruteForce = methodParamBruteForce;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelingResult getForecast(TimeSeries timeSeries, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
public ModelingResult getForecast(TimeSeries timeSeries, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
return methodParamBruteForce.getForecast(timeSeries, countPoints);
|
return methodParamBruteForce.getForecast(timeSeries, countPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, String methodClassName, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return methodParamBruteForce.getForecast(timeSeries, methodClassName, countPoints);
|
||||||
|
}
|
||||||
|
|
||||||
public ModelingResult smoothTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
public ModelingResult smoothTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||||
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries);
|
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user