Merge branch '8-modularity' into 'master'
Resolve "повысить модульность" Closes #8 See merge request romanov73/time-series-smoothing!5
This commit is contained in:
commit
090b339219
@ -1,6 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
package ru.ulstu;
|
||||||
|
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020. Anton Romanov
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.controllers;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -21,10 +12,10 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
|
|||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.client.HttpServerErrorException;
|
import org.springframework.web.client.HttpServerErrorException;
|
||||||
import ru.ulstu.models.exceptions.ForecastValidateException;
|
import ru.ulstu.datamodel.exception.ForecastValidateException;
|
||||||
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
import ru.ulstu.datamodel.exception.TimeSeriesValidateException;
|
||||||
import ru.ulstu.models.response.ErrorConstants;
|
import ru.ulstu.datamodel.response.ErrorConstants;
|
||||||
import ru.ulstu.models.response.ResponseExtended;
|
import ru.ulstu.datamodel.response.ResponseExtended;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.controllers;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -16,12 +14,12 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
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.datamodel.ForecastParams;
|
||||||
import ru.ulstu.models.ModelingResult;
|
import ru.ulstu.datamodel.ModelingResult;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.services.MethodParamBruteForce;
|
import ru.ulstu.service.MethodParamBruteForce;
|
||||||
import ru.ulstu.services.TimeSeriesService;
|
import ru.ulstu.service.TimeSeriesService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(ApiConfiguration.API_1_0)
|
@RequestMapping(ApiConfiguration.API_1_0)
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.controllers;
|
/*
|
||||||
|
* 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.controller;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -10,8 +16,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
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.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.services.UtilService;
|
import ru.ulstu.service.UtilService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(ApiConfiguration.API_1_0)
|
@RequestMapping(ApiConfiguration.API_1_0)
|
@ -1,4 +1,12 @@
|
|||||||
package ru.ulstu.models;
|
/*
|
||||||
|
* 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.datamodel;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
public class ForecastParams {
|
public class ForecastParams {
|
||||||
private TimeSeries originalTimeSeries;
|
private TimeSeries originalTimeSeries;
|
21
src/main/java/ru/ulstu/datamodel/Model.java
Normal file
21
src/main/java/ru/ulstu/datamodel/Model.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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.datamodel;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
|
public abstract class Model {
|
||||||
|
protected final TimeSeries timeSeriesModel;
|
||||||
|
|
||||||
|
protected Model(TimeSeries ts) {
|
||||||
|
timeSeriesModel = new TimeSeries("Model of", ts.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSeries getTimeSeriesModel() {
|
||||||
|
return timeSeriesModel;
|
||||||
|
}
|
||||||
|
}
|
46
src/main/java/ru/ulstu/datamodel/ModelingResult.java
Normal file
46
src/main/java/ru/ulstu/datamodel/ModelingResult.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.datamodel;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ModelingResult {
|
||||||
|
private final TimeSeries timeSeries;
|
||||||
|
private final List<MethodParamValue> paramValues;
|
||||||
|
private final Score score;
|
||||||
|
private final Method method;
|
||||||
|
|
||||||
|
public ModelingResult(TimeSeries timeSeries,
|
||||||
|
List<MethodParamValue> paramValues,
|
||||||
|
Score score,
|
||||||
|
Method method) {
|
||||||
|
this.timeSeries = timeSeries;
|
||||||
|
this.paramValues = paramValues;
|
||||||
|
this.score = score;
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSeries getTimeSeries() {
|
||||||
|
return timeSeries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MethodParamValue> getParamValues() {
|
||||||
|
return paramValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Score getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getTimeSeriesMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.models;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import ru.ulstu.score.ScoreMethod;
|
import ru.ulstu.score.ScoreMethod;
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.datamodel.exception;
|
||||||
|
|
||||||
|
public class ForecastValidateException extends ModelingException {
|
||||||
|
public ForecastValidateException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.datamodel.exception;
|
||||||
|
|
||||||
|
public class ModelingException extends Exception {
|
||||||
|
public ModelingException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.datamodel.exception;
|
||||||
|
|
||||||
|
public class TimeSeriesValidateException extends ModelingException {
|
||||||
|
public TimeSeriesValidateException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models.response;
|
/*
|
||||||
|
* 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.datamodel.response;
|
||||||
|
|
||||||
class ControllerResponse<D, E> {
|
class ControllerResponse<D, E> {
|
||||||
private final D data;
|
private final D data;
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models.response;
|
/*
|
||||||
|
* 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.datamodel.response;
|
||||||
|
|
||||||
class ControllerResponseError<D> {
|
class ControllerResponseError<D> {
|
||||||
private final ErrorConstants description;
|
private final ErrorConstants description;
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models.response;
|
/*
|
||||||
|
* 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.datamodel.response;
|
||||||
|
|
||||||
public enum ErrorConstants {
|
public enum ErrorConstants {
|
||||||
UNKNOWN(0, "Unknown error"),
|
UNKNOWN(0, "Unknown error"),
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models.response;
|
/*
|
||||||
|
* 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.datamodel.response;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models.response;
|
/*
|
||||||
|
* 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.datamodel.response;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models;
|
/*
|
||||||
|
* 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.datamodel.ts;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
@ -14,6 +20,10 @@ public class TimeSeries {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSeries(String prefix, String suffix) {
|
||||||
|
this.name = String.format("%s %s", prefix, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public TimeSeries(@JsonProperty(value = "values") List<TimeSeriesValue> values, @JsonProperty(value = "name") String name) {
|
public TimeSeries(@JsonProperty(value = "values") List<TimeSeriesValue> values, @JsonProperty(value = "name") String name) {
|
||||||
this.values = values;
|
this.values = values;
|
||||||
@ -78,6 +88,13 @@ public class TimeSeries {
|
|||||||
throw new RuntimeException("Индекс выходит за границы временного ряда");
|
throw new RuntimeException("Индекс выходит за границы временного ряда");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeSeriesValue getValue(int t) {
|
||||||
|
if ((values.size() > t) && (t >= 0)) {
|
||||||
|
return values.get(t);
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Индекс выходит за границы временного ряда");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TimeSeries{" +
|
return "TimeSeries{" +
|
@ -1,4 +1,10 @@
|
|||||||
package ru.ulstu.models;
|
/*
|
||||||
|
* 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.datamodel.ts;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,20 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import ru.ulstu.TimeSeriesUtils;
|
import ru.ulstu.TimeSeriesUtils;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.datamodel.exception.ForecastValidateException;
|
||||||
import ru.ulstu.models.exceptions.ForecastValidateException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.exception.TimeSeriesValidateException;
|
||||||
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
|
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -22,69 +21,51 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Наиболее общая логика моделировании и прогнозирования временных рядов
|
* Наиболее общая логика моделировании и прогнозирования временных рядов
|
||||||
*/
|
*/
|
||||||
public abstract class TimeSeriesMethod {
|
public abstract class Method {
|
||||||
@JsonIgnore
|
|
||||||
protected TimeSeries originalTimeSeries;
|
|
||||||
@JsonIgnore
|
|
||||||
private TimeSeries model;
|
|
||||||
|
|
||||||
public abstract TimeSeriesMethod createFor(TimeSeries originalTimeSeries);
|
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public abstract List<MethodParameter> getAvailableParameters();
|
public abstract List<MethodParameter> getAvailableParameters();
|
||||||
|
|
||||||
public abstract TimeSeriesMethod setAvailableParameters(List<TimeSeriesMethodParamValue> parameters);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает модельное представление временного ряда: для тех же точек времени что и в параметре timeSeries
|
|
||||||
* строится модель. Количество точек может быть изменено: сокращено при сжатии ряда, увеличено при интерполяции.
|
|
||||||
* Метод является шаблонным, выполняет операции валидации исходного ряда и потом его моделирование
|
|
||||||
*
|
|
||||||
* @throws ModelingException генерируется, если есть проблемы моделирования при задании параметров
|
|
||||||
*/
|
|
||||||
protected void makeModel() throws ModelingException {
|
|
||||||
validateTimeSeries();
|
|
||||||
model = getModelOfValidTimeSeries();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает модельное представление валидного временного ряда: для тех же точек времени что и в параметре timeSeries
|
* Возвращает модельное представление валидного временного ряда: для тех же точек времени что и в параметре timeSeries
|
||||||
* строится модель. Количество точек может быть изменено: сокращено при сжатии ряда, увеличено при интерполяции.
|
* строится модель. Количество точек может быть изменено: сокращено при сжатии ряда, увеличено при интерполяции.
|
||||||
*
|
*
|
||||||
* @return модельное представление временного ряда
|
* @return модель временного ряда
|
||||||
*/
|
*/
|
||||||
protected abstract TimeSeries getModelOfValidTimeSeries() throws ModelingException;
|
protected abstract Model getModelOfValidTimeSeries(TimeSeries timeSeries,
|
||||||
|
List<MethodParamValue> parameters) throws ModelingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает модельное представление временного ряда: для тех же точек времени что и в параметре timeSeries
|
||||||
|
* строится модель. Количество точек может быть изменено: сокращено при сжатии ряда, увеличено при интерполяции.
|
||||||
|
* Метод является шаблонным, выполняет операции валидации исходного ряда и потом его моделирование
|
||||||
|
* <p>
|
||||||
|
* return модельное представление временного ряда
|
||||||
|
*
|
||||||
|
* @throws ModelingException генерируется, если есть проблемы моделирования при задании параметров
|
||||||
|
*/
|
||||||
|
public Model getModel(TimeSeries timeSeries, List<MethodParamValue> parameters) throws ModelingException {
|
||||||
|
validateTimeSeries(timeSeries);
|
||||||
|
validateAdditionalParams(timeSeries, parameters);
|
||||||
|
return getModelOfValidTimeSeries(timeSeries, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Выполняет построение прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы по модельным точкам.
|
* Выполняет построение прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы по модельным точкам.
|
||||||
*
|
*
|
||||||
* @param countPoints количество точек для прогнозирования
|
* @param model модель временного ряда, включающая все нужные компоненты
|
||||||
|
* @param forecast заготовка временного ряда для прогноза с датами и нужным количеством точек для прогнозирования
|
||||||
* @return прогноз временного ряда
|
* @return прогноз временного ряда
|
||||||
*/
|
*/
|
||||||
public TimeSeries getForecastWithValidParams(int countPoints) throws ModelingException {
|
protected abstract TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) throws ModelingException;
|
||||||
TimeSeries forecast = generateEmptyForecastPoints(originalTimeSeries, countPoints);
|
|
||||||
getModel();
|
|
||||||
forecast.getFirstValue().setValue(originalTimeSeries.getLastValue().getValue());
|
|
||||||
forecast = makeForecast(forecast);
|
|
||||||
return forecast;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public boolean canMakeForecast(TimeSeries timeSeries, int countPoints) {
|
||||||
* Выполняет построение прогноза для уже сгенерированных будущих точек временного ряда.
|
try {
|
||||||
*
|
validateTimeSeries(timeSeries);
|
||||||
* @param forecast Заготовка прогноза временного ряда с пустыми значениями
|
validateForecastParams(countPoints);
|
||||||
* @return временной ряд прогноза
|
} catch (ModelingException ex) {
|
||||||
*/
|
return false;
|
||||||
protected abstract TimeSeries makeForecast(TimeSeries forecast) throws ModelingException;
|
|
||||||
|
|
||||||
protected TimeSeries generateEmptyForecastPoints(TimeSeries modelTimeSeries, int countPointForecast) {
|
|
||||||
long diffMilliseconds = TimeSeriesUtils.getTimeDifferenceInMilliseconds(originalTimeSeries);
|
|
||||||
TimeSeries forecast = new TimeSeries("Forecast of " + originalTimeSeries.getName());
|
|
||||||
forecast.addValue(new TimeSeriesValue(modelTimeSeries.getLastValue().getDate()));
|
|
||||||
for (int i = 1; i < countPointForecast + 1; i++) {
|
|
||||||
forecast.addValue(new TimeSeriesValue(forecast.getValues().get(i - 1).getDate().plus(diffMilliseconds, ChronoUnit.MILLIS)));
|
|
||||||
}
|
}
|
||||||
return forecast;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,9 +75,24 @@ public abstract class TimeSeriesMethod {
|
|||||||
* @param countPoints количество точек для прогнозирования
|
* @param countPoints количество точек для прогнозирования
|
||||||
* @return прогноз временного ряда
|
* @return прогноз временного ряда
|
||||||
*/
|
*/
|
||||||
public TimeSeries getForecast(int countPoints) throws ModelingException {
|
public TimeSeries getForecast(TimeSeries timeSeries,
|
||||||
|
List<MethodParamValue> parameters,
|
||||||
|
int countPoints) throws ModelingException {
|
||||||
validateForecastParams(countPoints);
|
validateForecastParams(countPoints);
|
||||||
return getForecastWithValidParams(countPoints);
|
Model model = getModel(timeSeries, parameters);
|
||||||
|
TimeSeries forecast = generateEmptyForecastPoints(model.getTimeSeriesModel(), countPoints);
|
||||||
|
forecast.getFirstValue().setValue(model.getTimeSeriesModel().getLastValue().getValue());
|
||||||
|
return getForecastWithValidParams(model, forecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TimeSeries generateEmptyForecastPoints(TimeSeries model, int countPointForecast) {
|
||||||
|
long diffMilliseconds = TimeSeriesUtils.getTimeDifferenceInMilliseconds(model);
|
||||||
|
TimeSeries forecast = new TimeSeries("Forecast of " + model.getName());
|
||||||
|
forecast.addValue(new TimeSeriesValue(model.getLastValue().getDate()));
|
||||||
|
for (int i = 1; i < countPointForecast + 1; i++) {
|
||||||
|
forecast.addValue(new TimeSeriesValue(forecast.getValues().get(i - 1).getDate().plus(diffMilliseconds, ChronoUnit.MILLIS)));
|
||||||
|
}
|
||||||
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateForecastParams(int countPoints) throws ForecastValidateException {
|
private void validateForecastParams(int countPoints) throws ForecastValidateException {
|
||||||
@ -105,41 +101,22 @@ public abstract class TimeSeriesMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void validateTimeSeries() throws ModelingException {
|
protected void validateTimeSeries(TimeSeries timeSeries) throws ModelingException {
|
||||||
if (originalTimeSeries == null || originalTimeSeries.isEmpty()) {
|
if (timeSeries == null || timeSeries.isEmpty()) {
|
||||||
throw new TimeSeriesValidateException("Временной ряд должен быть не пустым");
|
throw new TimeSeriesValidateException("Временной ряд должен быть не пустым");
|
||||||
}
|
}
|
||||||
if (originalTimeSeries.getLength() < 2) {
|
if (timeSeries.getLength() < 2) {
|
||||||
throw new TimeSeriesValidateException("Временной ряд должен содержать хотя бы 2 точки");
|
throw new TimeSeriesValidateException("Временной ряд должен содержать хотя бы 2 точки");
|
||||||
}
|
}
|
||||||
if (originalTimeSeries.getValues().stream().anyMatch(val -> val == null || val.getValue() == null)) {
|
if (timeSeries.getValues().stream().anyMatch(val -> val == null || val.getValue() == null)) {
|
||||||
throw new TimeSeriesValidateException("Временной ряд содержит пустые значения");
|
throw new TimeSeriesValidateException("Временной ряд содержит пустые значения");
|
||||||
}
|
}
|
||||||
if (originalTimeSeries.getValues().stream().anyMatch(val -> val.getDate() == null)) {
|
if (timeSeries.getValues().stream().anyMatch(val -> val.getDate() == null)) {
|
||||||
throw new TimeSeriesValidateException("Временной ряд должен иметь отметки времени");
|
throw new TimeSeriesValidateException("Временной ряд должен иметь отметки времени");
|
||||||
}
|
}
|
||||||
validateAdditionalParams();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void validateAdditionalParams() throws ModelingException {
|
protected void validateAdditionalParams(TimeSeries timeSeries, List<MethodParamValue> parameters) throws ModelingException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSeries getModel() throws ModelingException {
|
|
||||||
//TODO: what if always run?
|
|
||||||
//if (model == null) {
|
|
||||||
makeModel();
|
|
||||||
//}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canMakeForecast(int countPoints) {
|
|
||||||
try {
|
|
||||||
validateTimeSeries();
|
|
||||||
validateForecastParams(countPoints);
|
|
||||||
} catch (ModelingException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
25
src/main/java/ru/ulstu/method/MethodParamValue.java
Normal file
25
src/main/java/ru/ulstu/method/MethodParamValue.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.method;
|
||||||
|
|
||||||
|
public class MethodParamValue {
|
||||||
|
protected MethodParameter parameter;
|
||||||
|
protected Number value;
|
||||||
|
|
||||||
|
public MethodParamValue(MethodParameter parameter, Number value) {
|
||||||
|
this.parameter = parameter;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodParameter getParameter() {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.addtrendaddseason;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
|
import ru.ulstu.datamodel.exception.TimeSeriesValidateException;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Season;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AddTrendAddSeason extends Method {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Model getModelOfValidTimeSeries(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
AddTrendAddSeasonModel model = new AddTrendAddSeasonModel(ts, parameters);
|
||||||
|
List<Double> sComponent = model.getSmoothedComponent();
|
||||||
|
List<Double> tComponent = model.getTrendComponent();
|
||||||
|
List<Double> iComponent = model.getSeasonComponent();
|
||||||
|
sComponent.add(ts.getFirstValue().getValue());
|
||||||
|
TimeSeries tsModel = model.getTimeSeriesModel();
|
||||||
|
|
||||||
|
iComponent.add(1.0);
|
||||||
|
tComponent.add(0.0);
|
||||||
|
tsModel.addValue(ts.getFirstValue());
|
||||||
|
//выполняется проход модели по сглаживанию
|
||||||
|
for (int t = 1; t < model.getSeason().getValue().intValue(); t++) {
|
||||||
|
sComponent.add(model.getAlpha().getDoubleValue() * ts.getNumericValue(t)
|
||||||
|
+ (1 - model.getAlpha().getDoubleValue())
|
||||||
|
* (sComponent.get(t - 1) + tComponent.get(t - 1)));
|
||||||
|
tComponent.add(model.getBeta().getDoubleValue()
|
||||||
|
* (sComponent.get(t) - sComponent.get(t - 1))
|
||||||
|
+ (1 - model.getBeta().getDoubleValue()) * tComponent.get(t - 1));
|
||||||
|
iComponent.add(model.getGamma().getDoubleValue() * ts.getNumericValue(t) / sComponent.get(sComponent.size() - 1)
|
||||||
|
+ (1 - model.getGamma().getDoubleValue()) * iComponent.get(0));
|
||||||
|
tsModel.addValue(ts.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
||||||
|
}
|
||||||
|
for (int t = model.getSeason().getIntValue(); t < ts.getValues().size(); t++) {
|
||||||
|
sComponent.add(model.getAlpha().getDoubleValue() * ts.getNumericValue(t)
|
||||||
|
/ iComponent.get(t - model.getSeason().getIntValue())
|
||||||
|
+ (1 - model.getAlpha().getDoubleValue())
|
||||||
|
* (sComponent.get(t - 1) + tComponent.get(t - 1)));
|
||||||
|
|
||||||
|
tComponent.add(model.getBeta().getDoubleValue()
|
||||||
|
* (sComponent.get(t) - sComponent.get(t - 1))
|
||||||
|
+ (1 - model.getBeta().getDoubleValue()) * tComponent.get(t - 1));
|
||||||
|
|
||||||
|
iComponent.add(model.getGamma().getDoubleValue() * ts.getNumericValue(t) / sComponent.get(sComponent.size() - 1)
|
||||||
|
+ (1 - model.getGamma().getDoubleValue()) * iComponent.get(t - model.getSeason().getIntValue()));
|
||||||
|
tsModel.addValue(ts.getValue(t), sComponent.get(sComponent.size() - 1));
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAdditionalParams(TimeSeries ts, List<MethodParamValue> parameters) throws ModelingException {
|
||||||
|
for (MethodParamValue parameter : parameters) {
|
||||||
|
if (parameter.getParameter() instanceof Season) {
|
||||||
|
if (ts.getLength() < parameter.getValue().intValue()) {
|
||||||
|
throw new TimeSeriesValidateException("Период больше чем длина ряда");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) {
|
||||||
|
AddTrendAddSeasonModel currentModel = (AddTrendAddSeasonModel) model;
|
||||||
|
List<Double> sComponent = currentModel.getSmoothedComponent();
|
||||||
|
List<Double> tComponent = currentModel.getTrendComponent();
|
||||||
|
List<Double> iComponent = currentModel.getSeasonComponent();
|
||||||
|
for (int t = 1; t < forecast.getLength(); t++) {
|
||||||
|
iComponent.add(currentModel.getGamma().getDoubleValue() * forecast.getNumericValue(t - 1) / sComponent.get(sComponent.size() - 1)
|
||||||
|
+ (1 - currentModel.getGamma().getDoubleValue()) * iComponent.get(t + model.getTimeSeriesModel().getLength() - currentModel.getSeason().getIntValue()));
|
||||||
|
|
||||||
|
forecast.getValues().get(t).setValue((sComponent.get(sComponent.size() - 1) + tComponent.get(tComponent.size() - 1) * t)
|
||||||
|
* iComponent.get(t + model.getTimeSeriesModel().getLength() - currentModel.getSeason().getIntValue()));
|
||||||
|
}
|
||||||
|
return forecast;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
|
return AddTrendAddSeasonModel.getAvailableParameters();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.addtrendaddseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Alpha;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Beta;
|
||||||
|
import ru.ulstu.method.exponential.parameter.ExponentialMethodParamValue;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Gamma;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Season;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AddTrendAddSeasonModel extends ru.ulstu.datamodel.Model {
|
||||||
|
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
||||||
|
private final ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
||||||
|
private final ExponentialMethodParamValue<Gamma> gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5);
|
||||||
|
private final ExponentialMethodParamValue<Season> season = new ExponentialMethodParamValue<>(Season.getInstance(), 12);
|
||||||
|
private final List<Double> smoothedComponent = new ArrayList<>();
|
||||||
|
private final List<Double> trendComponent = new ArrayList<>();
|
||||||
|
private final List<Double> seasonComponent = new ArrayList<>();
|
||||||
|
|
||||||
|
public AddTrendAddSeasonModel(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
super(ts);
|
||||||
|
for (MethodParamValue 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getSmoothedComponent() {
|
||||||
|
return smoothedComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getTrendComponent() {
|
||||||
|
return trendComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getSeasonComponent() {
|
||||||
|
return seasonComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Alpha> getAlpha() {
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Beta> getBeta() {
|
||||||
|
return beta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Gamma> getGamma() {
|
||||||
|
return gamma;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Season> getSeason() {
|
||||||
|
return season;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MethodParameter> getAvailableParameters() {
|
||||||
|
return Arrays.asList(Alpha.getInstance(), Beta.getInstance(), Gamma.getInstance(), Season.getInstance());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.addtrendnoseason;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AddTrendNoSeason extends Method {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Model getModelOfValidTimeSeries(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
AddTrendNoSeasonModel model = new AddTrendNoSeasonModel(ts, parameters);
|
||||||
|
List<Double> sComponent = model.getSmoothedComponent();
|
||||||
|
List<Double> tComponent = model.getTrendComponent();
|
||||||
|
sComponent.add(ts.getFirstValue().getValue());
|
||||||
|
TimeSeries tsModel = model.getTimeSeriesModel();
|
||||||
|
|
||||||
|
sComponent.add(ts.getFirstValue().getValue());
|
||||||
|
tComponent.add(ts.getValue(1).getValue() - ts.getValue(0).getValue());
|
||||||
|
tsModel.addValue(ts.getFirstValue());
|
||||||
|
//выполняется проход модели по сглаживанию
|
||||||
|
for (int t = 1; t < ts.getValues().size(); t++) {
|
||||||
|
sComponent.add(model.getAlpha().getDoubleValue() * ts.getNumericValue(t)
|
||||||
|
+ (1 - model.getAlpha().getDoubleValue())
|
||||||
|
* (sComponent.get(t - 1) - tComponent.get(t - 1)));
|
||||||
|
|
||||||
|
tComponent.add(model.getBeta().getDoubleValue()
|
||||||
|
* (sComponent.get(t) - sComponent.get(t - 1))
|
||||||
|
+ (1 - model.getBeta().getDoubleValue()) * tComponent.get(t - 1));
|
||||||
|
tsModel.addValue(ts.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) {
|
||||||
|
AddTrendNoSeasonModel currentModel = (AddTrendNoSeasonModel) model;
|
||||||
|
List<Double> sComponent = currentModel.getSmoothedComponent();
|
||||||
|
List<Double> tComponent = currentModel.getTrendComponent();
|
||||||
|
for (int t = 1; t < forecast.getLength(); t++) {
|
||||||
|
forecast.getValues().get(t).setValue(sComponent.get(sComponent.size() - 1) + tComponent.get(tComponent.size() - 1) * t);
|
||||||
|
}
|
||||||
|
return forecast;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
|
return AddTrendNoSeasonModel.getAvailableParameters();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.addtrendnoseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Alpha;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Beta;
|
||||||
|
import ru.ulstu.method.exponential.parameter.ExponentialMethodParamValue;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AddTrendNoSeasonModel extends ru.ulstu.datamodel.Model {
|
||||||
|
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
||||||
|
private final ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
||||||
|
private final List<Double> smoothedComponent = new ArrayList<>();
|
||||||
|
private final List<Double> trendComponent = new ArrayList<>();
|
||||||
|
|
||||||
|
public AddTrendNoSeasonModel(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
super(ts);
|
||||||
|
for (MethodParamValue parameter : parameters) {
|
||||||
|
if (parameter.getParameter() instanceof Alpha) {
|
||||||
|
alpha.setValue(parameter.getValue());
|
||||||
|
}
|
||||||
|
if (parameter.getParameter() instanceof Beta) {
|
||||||
|
beta.setValue(parameter.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getSmoothedComponent() {
|
||||||
|
return smoothedComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getTrendComponent() {
|
||||||
|
return trendComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Alpha> getAlpha() {
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Beta> getBeta() {
|
||||||
|
return beta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MethodParameter> getAvailableParameters() {
|
||||||
|
return Arrays.asList(Alpha.getInstance(), Beta.getInstance());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.notrendnoseason;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NoTrendNoSeason extends Method {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NoTrendNoSeasonModel getModelOfValidTimeSeries(TimeSeries ts,
|
||||||
|
List<MethodParamValue> parameters) {
|
||||||
|
NoTrendNoSeasonModel model = new NoTrendNoSeasonModel(ts, parameters);
|
||||||
|
List<Double> sComponent = model.getSmoothedComponent();
|
||||||
|
sComponent.add(ts.getFirstValue().getValue());
|
||||||
|
TimeSeries tsModel = model.getTimeSeriesModel();
|
||||||
|
tsModel.addValue(ts.getFirstValue());
|
||||||
|
//выполняется проход модели по сглаживанию
|
||||||
|
for (int t = 1; t < ts.getValues().size(); t++) {
|
||||||
|
sComponent.add(sComponent.get(t - 1)
|
||||||
|
+ model.getAlpha().getDoubleValue()
|
||||||
|
* (ts.getNumericValue(t) - sComponent.get(t - 1)));
|
||||||
|
tsModel.addValue(ts.getValue(t), sComponent.get(sComponent.size() - 1));
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) {
|
||||||
|
for (int t = 1; t < forecast.getLength(); t++) {
|
||||||
|
forecast.getValues().get(t).setValue(forecast.getValues().get(t - 1).getValue());
|
||||||
|
}
|
||||||
|
return forecast;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
|
return NoTrendNoSeasonModel.getAvailableParameters();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.method.exponential.notrendnoseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
import ru.ulstu.method.exponential.parameter.Alpha;
|
||||||
|
import ru.ulstu.method.exponential.parameter.ExponentialMethodParamValue;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NoTrendNoSeasonModel extends ru.ulstu.datamodel.Model {
|
||||||
|
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
||||||
|
private final List<Double> smoothedComponent = new ArrayList<>();
|
||||||
|
|
||||||
|
public NoTrendNoSeasonModel(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
super(ts);
|
||||||
|
for (MethodParamValue parameter : parameters) {
|
||||||
|
if (parameter.getParameter() instanceof Alpha) {
|
||||||
|
alpha.setValue(parameter.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getSmoothedComponent() {
|
||||||
|
return smoothedComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExponentialMethodParamValue<Alpha> getAlpha() {
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MethodParameter> getAvailableParameters() {
|
||||||
|
return Collections.singletonList(Alpha.getInstance());
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Alpha extends ExponentialMethodParameter {
|
public class Alpha extends ExponentialMethodParameter {
|
||||||
public Alpha() {
|
public Alpha() {
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Beta extends ExponentialMethodParameter {
|
public class Beta extends ExponentialMethodParameter {
|
||||||
public Beta() {
|
public Beta() {
|
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class ExponentialMethodParamValue<T extends ExponentialMethodParameter> {
|
public class ExponentialMethodParamValue<T extends ExponentialMethodParameter> {
|
||||||
private final T param;
|
private final T param;
|
@ -4,10 +4,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import ru.ulstu.tsMethods.MethodParameter;
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Gamma extends ExponentialMethodParameter {
|
public class Gamma extends ExponentialMethodParameter {
|
||||||
public Gamma() {
|
public Gamma() {
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.tsMethods.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Season extends ExponentialMethodParameter {
|
public class Season extends ExponentialMethodParameter {
|
||||||
private final static int DEFAULT_SEASON_OPTIMIZATION_STEP = 1;
|
private final static int DEFAULT_SEASON_OPTIMIZATION_STEP = 1;
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * 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;
|
|
||||||
|
|
||||||
import ru.ulstu.tsMethods.TimeSeriesMethod;
|
|
||||||
import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ModelingResult {
|
|
||||||
private final TimeSeries timeSeries;
|
|
||||||
private final List<TimeSeriesMethodParamValue> paramValues;
|
|
||||||
private final Score score;
|
|
||||||
private final TimeSeriesMethod timeSeriesMethod;
|
|
||||||
|
|
||||||
public ModelingResult(TimeSeries timeSeries,
|
|
||||||
List<TimeSeriesMethodParamValue> paramValues,
|
|
||||||
Score score,
|
|
||||||
TimeSeriesMethod timeSeriesMethod) {
|
|
||||||
this.timeSeries = timeSeries;
|
|
||||||
this.paramValues = paramValues;
|
|
||||||
this.score = score;
|
|
||||||
this.timeSeriesMethod = timeSeriesMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSeries getTimeSeries() {
|
|
||||||
return timeSeries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TimeSeriesMethodParamValue> getParamValues() {
|
|
||||||
return paramValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Score getScore() {
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSeriesMethod getTimeSeriesMethod() {
|
|
||||||
return timeSeriesMethod;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package ru.ulstu.models.exceptions;
|
|
||||||
|
|
||||||
public class ForecastValidateException extends ModelingException {
|
|
||||||
public ForecastValidateException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package ru.ulstu.models.exceptions;
|
|
||||||
|
|
||||||
public class ModelingException extends Exception {
|
|
||||||
public ModelingException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package ru.ulstu.models.exceptions;
|
|
||||||
|
|
||||||
public class TimeSeriesValidateException extends ModelingException {
|
|
||||||
public TimeSeriesValidateException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.pages;
|
package ru.ulstu.page;
|
||||||
|
|
||||||
import org.primefaces.model.chart.AxisType;
|
import org.primefaces.model.chart.AxisType;
|
||||||
import org.primefaces.model.chart.DateAxis;
|
import org.primefaces.model.chart.DateAxis;
|
||||||
@ -14,11 +14,11 @@ import org.primefaces.model.chart.LineChartSeries;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
import ru.ulstu.services.TimeSeriesService;
|
import ru.ulstu.service.TimeSeriesService;
|
||||||
import ru.ulstu.services.UtilService;
|
import ru.ulstu.service.UtilService;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.faces.view.ViewScoped;
|
import javax.faces.view.ViewScoped;
|
@ -1,17 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * 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.datamodel.Score;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
|
|
||||||
public abstract class ScoreMethod {
|
public abstract class ScoreMethod {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
*
|
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||||
* * Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||||
* * 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.TimeSeries;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
|
|
||||||
import static java.lang.Math.abs;
|
import static java.lang.Math.abs;
|
||||||
|
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.services;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.ulstu.models.ModelingResult;
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.ModelingResult;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
import ru.ulstu.score.ScoreMethod;
|
import ru.ulstu.score.ScoreMethod;
|
||||||
import ru.ulstu.score.Smape;
|
import ru.ulstu.score.Smape;
|
||||||
import ru.ulstu.tsMethods.MethodParameter;
|
|
||||||
import ru.ulstu.tsMethods.TimeSeriesMethod;
|
|
||||||
import ru.ulstu.tsMethods.TimeSeriesMethodParamValue;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -29,11 +30,11 @@ import java.util.concurrent.Future;
|
|||||||
@Service
|
@Service
|
||||||
public class MethodParamBruteForce {
|
public class MethodParamBruteForce {
|
||||||
private final int DEFAULT_THREAD_COUNT = 50;
|
private final int DEFAULT_THREAD_COUNT = 50;
|
||||||
private final List<TimeSeriesMethod> methods;
|
private final List<Method> methods;
|
||||||
private final ScoreMethod scoreMethod = new Smape();
|
private final ScoreMethod scoreMethod = new Smape();
|
||||||
private final ExecutorService executors = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);
|
private final ExecutorService executors = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);
|
||||||
|
|
||||||
public MethodParamBruteForce(List<TimeSeriesMethod> methods) {
|
public MethodParamBruteForce(List<Method> methods) {
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +50,21 @@ public class MethodParamBruteForce {
|
|||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
||||||
try {
|
try {
|
||||||
for (TimeSeriesMethod method : methods) {
|
for (Method method : methods) {
|
||||||
List<List<TimeSeriesMethodParamValue>> availableParametersValues = getAvailableParametersValues(method.getAvailableParameters());
|
List<List<MethodParamValue>> availableParametersValues = getAvailableParametersValues(method.getAvailableParameters());
|
||||||
for (List<TimeSeriesMethodParamValue> parametersValues : availableParametersValues) {
|
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
||||||
results.add(executors.submit(() -> {
|
results.add(executors.submit(() -> {
|
||||||
TimeSeriesMethod methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||||
TimeSeries model = methodInstance.createFor(timeSeries)
|
try {
|
||||||
.setAvailableParameters(parametersValues)
|
Model model = methodInstance.getModel(timeSeries, parametersValues);
|
||||||
.getModel();
|
return new ModelingResult(model.getTimeSeriesModel(),
|
||||||
return new ModelingResult(model, parametersValues, scoreMethod.getScore(timeSeries, model), methodInstance);
|
parametersValues,
|
||||||
|
scoreMethod.getScore(timeSeries, model.getTimeSeriesModel()),
|
||||||
|
methodInstance);
|
||||||
|
} catch (ModelingException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,8 +86,8 @@ public class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<TimeSeriesMethodParamValue>> getAvailableParametersValues(List<MethodParameter> availableParameters) {
|
private List<List<MethodParamValue>> getAvailableParametersValues(List<MethodParameter> availableParameters) {
|
||||||
List<List<TimeSeriesMethodParamValue>> result = new ArrayList<>();
|
List<List<MethodParamValue>> result = new ArrayList<>();
|
||||||
Map<MethodParameter, Integer> parameterOffset = new TreeMap<>();
|
Map<MethodParameter, Integer> parameterOffset = new TreeMap<>();
|
||||||
Map<MethodParameter, List<Number>> parameterValues = new TreeMap<>();
|
Map<MethodParameter, List<Number>> parameterValues = new TreeMap<>();
|
||||||
for (MethodParameter methodParameter : availableParameters) {
|
for (MethodParameter methodParameter : availableParameters) {
|
||||||
@ -88,9 +95,9 @@ public class MethodParamBruteForce {
|
|||||||
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
||||||
}
|
}
|
||||||
while (!isAllValuesUsed(parameterOffset, parameterValues)) {
|
while (!isAllValuesUsed(parameterOffset, parameterValues)) {
|
||||||
List<TimeSeriesMethodParamValue> resultRow = new ArrayList<>();
|
List<MethodParamValue> resultRow = new ArrayList<>();
|
||||||
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
||||||
resultRow.add(new TimeSeriesMethodParamValue(methodParameter,
|
resultRow.add(new MethodParamValue(methodParameter,
|
||||||
parameterValues.get(methodParameter).get(parameterOffset.get(methodParameter))));
|
parameterValues.get(methodParameter).get(parameterOffset.get(methodParameter))));
|
||||||
}
|
}
|
||||||
incrementOffset(parameterOffset, parameterValues);
|
incrementOffset(parameterOffset, parameterValues);
|
@ -4,18 +4,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.ulstu.services;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.models.exceptions.ModelingException;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.tsMethods.TimeSeriesMethod;
|
import ru.ulstu.method.Method;
|
||||||
import ru.ulstu.tsMethods.exponential.AddTrendAddSeason;
|
import ru.ulstu.method.exponential.addtrendaddseason.AddTrendAddSeason;
|
||||||
import ru.ulstu.tsMethods.exponential.NoTrendNoSeason;
|
|
||||||
import ru.ulstu.tsMethods.exponential.parameter.Alpha;
|
import java.util.Collections;
|
||||||
import ru.ulstu.tsMethods.exponential.parameter.ExponentialMethodParamValue;
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -28,10 +27,9 @@ public class TimeSeriesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TimeSeries getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
|
public TimeSeries getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
|
||||||
TimeSeriesMethod method;
|
Method method;
|
||||||
method = new NoTrendNoSeason().createFor(timeSeries).setAlpha(new ExponentialMethodParamValue<>(new Alpha(), 0.8));
|
method = new AddTrendAddSeason();
|
||||||
method = new AddTrendAddSeason().createFor(timeSeries);
|
return method.getForecast(timeSeries, Collections.emptyList(), countPoints);
|
||||||
return method.getForecast(countPoints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSeries smoothTimeSeries(TimeSeries timeSeries) throws ModelingException {
|
public TimeSeries smoothTimeSeries(TimeSeries timeSeries) throws ModelingException {
|
@ -1,11 +1,17 @@
|
|||||||
package ru.ulstu.services;
|
/*
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.ulstu.TimeSeriesUtils;
|
import ru.ulstu.TimeSeriesUtils;
|
||||||
import ru.ulstu.models.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.models.TimeSeriesValue;
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* * 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.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 java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class AddTrendNoSeason extends TimeSeriesMethod {
|
|
||||||
private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
|
||||||
private ExponentialMethodParamValue<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
|
||||||
private final List<Double> sComponent = new ArrayList<>();
|
|
||||||
private final List<Double> tComponent = new ArrayList<>();
|
|
||||||
|
|
||||||
public AddTrendNoSeason createFor(TimeSeries timeSeries) {
|
|
||||||
this.originalTimeSeries = timeSeries;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddTrendNoSeason setAlpha(ExponentialMethodParamValue<Alpha> alpha) {
|
|
||||||
this.alpha = alpha;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddTrendNoSeason setBeta(ExponentialMethodParamValue<Beta> beta) {
|
|
||||||
this.beta = beta;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TimeSeries getModelOfValidTimeSeries() {
|
|
||||||
sComponent.clear();
|
|
||||||
tComponent.clear();
|
|
||||||
sComponent.add(originalTimeSeries.getFirstValue().getValue());
|
|
||||||
tComponent.add(originalTimeSeries.getValues().get(1).getValue() - originalTimeSeries.getValues().get(0).getValue());
|
|
||||||
TimeSeries model = new TimeSeries("Model of " + originalTimeSeries.getName());
|
|
||||||
model.addValue(originalTimeSeries.getFirstValue());
|
|
||||||
//выполняется проход модели по сглаживанию
|
|
||||||
for (int t = 1; t < originalTimeSeries.getValues().size(); 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));
|
|
||||||
model.addValue(originalTimeSeries.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TimeSeries makeForecast(TimeSeries forecast) {
|
|
||||||
for (int t = 1; t < forecast.getLength(); t++) {
|
|
||||||
forecast.getValues().get(t).setValue(sComponent.get(sComponent.size() - 1) + tComponent.get(tComponent.size() - 1) * t);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.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.ExponentialMethodParamValue;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class NoTrendNoSeason extends TimeSeriesMethod {
|
|
||||||
private ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
|
||||||
private final List<Double> sComponent = new ArrayList<>();
|
|
||||||
|
|
||||||
public NoTrendNoSeason createFor(TimeSeries timeSeries) {
|
|
||||||
this.originalTimeSeries = timeSeries;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NoTrendNoSeason setAlpha(ExponentialMethodParamValue<Alpha> alpha) {
|
|
||||||
this.alpha = alpha;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TimeSeries getModelOfValidTimeSeries() {
|
|
||||||
sComponent.clear();
|
|
||||||
sComponent.add(originalTimeSeries.getFirstValue().getValue());
|
|
||||||
TimeSeries model = new TimeSeries("Model of " + originalTimeSeries.getName());
|
|
||||||
model.addValue(originalTimeSeries.getFirstValue());
|
|
||||||
//выполняется проход модели по сглаживанию
|
|
||||||
for (int t = 1; t < originalTimeSeries.getValues().size(); t++) {
|
|
||||||
sComponent.add(sComponent.get(t - 1)
|
|
||||||
+ alpha.getDoubleValue()
|
|
||||||
* (originalTimeSeries.getNumericValue(t) - sComponent.get(t - 1)));
|
|
||||||
model.addValue(originalTimeSeries.getValues().get(t), sComponent.get(sComponent.size() - 1));
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TimeSeries makeForecast(TimeSeries forecast) {
|
|
||||||
for (int t = 1; t < forecast.getLength(); t++) {
|
|
||||||
forecast.getValues().get(t).setValue(forecast.getValues().get(t - 1).getValue());
|
|
||||||
}
|
|
||||||
return forecast;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MethodParameter> getAvailableParameters() {
|
|
||||||
return Collections.singletonList(alpha.getParam());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TimeSeriesMethod setAvailableParameters(List<TimeSeriesMethodParamValue> parameters) {
|
|
||||||
for (TimeSeriesMethodParamValue parameter : parameters) {
|
|
||||||
if (parameter.getParameter() instanceof Alpha) {
|
|
||||||
alpha.setValue(parameter.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user