#2 -- fix forecasting
This commit is contained in:
parent
be9a761f0f
commit
85c4b3cad8
35
src/main/java/ru/ulstu/TimeSeriesUtils.java
Normal file
35
src/main/java/ru/ulstu/TimeSeriesUtils.java
Normal file
@ -0,0 +1,35 @@
|
||||
package ru.ulstu;
|
||||
|
||||
import ru.ulstu.models.TimeSeries;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
public class TimeSeriesUtils {
|
||||
/**
|
||||
* Вычисляет среднее значение между датами временного ряда
|
||||
*
|
||||
* @param timeSeries объект, содержащий временной ряд
|
||||
* @return средняя разница между датами исходного временного ряда в миллисекундах
|
||||
*/
|
||||
public static long getTimeDifferenceInMilliseconds(TimeSeries timeSeries) {
|
||||
long diffMilliseconds = 0;
|
||||
for (int i = 1; i < timeSeries.getLength(); i++) {
|
||||
diffMilliseconds += timeSeries.getValues().get(i - 1).getDate()
|
||||
.until(timeSeries.getValues().get(i).getDate(), ChronoUnit.MILLIS);
|
||||
}
|
||||
return diffMilliseconds / (timeSeries.getLength() - 1);
|
||||
}
|
||||
|
||||
public static TimeSeries fillDates(TimeSeries timeSeries, long milliseconds) {
|
||||
timeSeries.getLastValue().setDate(LocalDateTime.now());
|
||||
for (int i = timeSeries.getLength() - 2; i >= 0; i--) {
|
||||
timeSeries.getValues().get(i).setDate(timeSeries.getValues().get(i + 1).getDate().minus(milliseconds, ChronoUnit.MILLIS));
|
||||
}
|
||||
return timeSeries;
|
||||
}
|
||||
|
||||
public static TimeSeries fillDates(TimeSeries timeSeries) {
|
||||
return fillDates(timeSeries, 1000 * 60 * 60 * 24);
|
||||
}
|
||||
}
|
@ -38,6 +38,18 @@ public class TimeSeriesController {
|
||||
return new ResponseEntity<>(timeSeriesService.getRandomTimeSeries(length), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("getFromString")
|
||||
@ApiOperation("Преобразовать строку с разделителями во временной ряд")
|
||||
public ResponseEntity<TimeSeries> getTimeSeriesFromString(@RequestParam("tsString") String tsString) {
|
||||
return new ResponseEntity<>(timeSeriesService.getTimeSeriesFromString(tsString), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("timeSeriesToString")
|
||||
@ApiOperation("Преобразовать временной ряд в строку с разделителями")
|
||||
public ResponseEntity<String> getTimeSeriesToString(@RequestBody TimeSeries timeSeries) {
|
||||
return new ResponseEntity<>(timeSeriesService.getTimeSeriesToString(timeSeries), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("getForecast")
|
||||
@ApiOperation("Получить прогноз временного ряда")
|
||||
public ResponseEntity<Forecast> getForecastTimeSeries(@RequestBody ForecastParams forecastParams) throws ModelingException {
|
||||
|
@ -24,6 +24,10 @@ public class TimeSeries {
|
||||
|
||||
}
|
||||
|
||||
public TimeSeries(List<TimeSeriesValue> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public List<TimeSeriesValue> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
@ -20,6 +20,10 @@ public class TimeSeriesValue {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public TimeSeriesValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public LocalDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package ru.ulstu.services;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.TimeSeriesUtils;
|
||||
import ru.ulstu.models.Forecast;
|
||||
import ru.ulstu.models.TimeSeries;
|
||||
import ru.ulstu.models.TimeSeriesValue;
|
||||
@ -10,6 +11,9 @@ import ru.ulstu.models.exceptions.ModelingException;
|
||||
import ru.ulstu.tsMethods.exponential.NoTrendNoSeason;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Service
|
||||
@ -27,7 +31,34 @@ public class TimeSeriesService {
|
||||
}
|
||||
|
||||
public Forecast getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException {
|
||||
NoTrendNoSeason nn = new NoTrendNoSeason(0.1);
|
||||
NoTrendNoSeason nn = new NoTrendNoSeason(0.8);
|
||||
return nn.getForecast(timeSeries, countPoints);
|
||||
}
|
||||
|
||||
public TimeSeries getTimeSeriesFromString(String tsString) {
|
||||
List<TimeSeriesValue> tsValues = Arrays.stream(tsString.split("\n"))
|
||||
.flatMap(v -> Arrays.stream(v.split(";")))
|
||||
.flatMap(v -> Arrays.stream(v.split(",")))
|
||||
.flatMap(v -> Arrays.stream(v.split("<br>")))
|
||||
.filter(v -> {
|
||||
try {
|
||||
Double.parseDouble(v);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.map(Double::parseDouble)
|
||||
.map(TimeSeriesValue::new)
|
||||
.collect(Collectors.toList());
|
||||
return TimeSeriesUtils.fillDates(new TimeSeries(tsValues));
|
||||
}
|
||||
|
||||
public String getTimeSeriesToString(TimeSeries timeSeries) {
|
||||
return timeSeries
|
||||
.getValues()
|
||||
.stream()
|
||||
.map(v -> v.getValue().toString().replaceAll("\\.", ","))
|
||||
.collect(Collectors.joining(";"));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.ulstu.tsMethods;
|
||||
|
||||
import ru.ulstu.TimeSeriesUtils;
|
||||
import ru.ulstu.models.Forecast;
|
||||
import ru.ulstu.models.Model;
|
||||
import ru.ulstu.models.TimeSeries;
|
||||
@ -8,8 +9,6 @@ import ru.ulstu.models.exceptions.ForecastValidateException;
|
||||
import ru.ulstu.models.exceptions.ModelingException;
|
||||
import ru.ulstu.models.exceptions.TimeSeriesValidateException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
@ -58,7 +57,7 @@ public abstract class TimeSeriesMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет построение прогноза ждя уже сгенерированных будущих точек временного ряда.
|
||||
* Выполняет построение прогноза для уже сгенерированных будущих точек временного ряда.
|
||||
*
|
||||
* @param forecast Заготовка прогноза временного ряда с пустыми значениями
|
||||
* @return
|
||||
@ -66,14 +65,7 @@ public abstract class TimeSeriesMethod {
|
||||
protected abstract Forecast makeForecast(Forecast forecast);
|
||||
|
||||
protected Forecast generateEmptyForecastPoints(Forecast forecast, int countPointForecast) {
|
||||
long diffMilliseconds = getTimeDifferenceInMilliseconds(forecast);
|
||||
LocalDateTime lastTimeSeriesDateTime = forecast
|
||||
.getModel()
|
||||
.getOriginalTimeSeries()
|
||||
.getLastValue()
|
||||
.getDate()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDateTime();
|
||||
long diffMilliseconds = TimeSeriesUtils.getTimeDifferenceInMilliseconds(forecast.getModel().getOriginalTimeSeries());
|
||||
forecast.getForecastTimeSeries()
|
||||
.addValue(new TimeSeriesValue(forecast.getModel().getModelTimeSeries().getLastValue().getDate()));
|
||||
for (int i = 1; i < countPointForecast + 1; i++) {
|
||||
@ -83,21 +75,6 @@ public abstract class TimeSeriesMethod {
|
||||
return forecast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисляет среднее значение между датами исходного временного ряда
|
||||
*
|
||||
* @param forecast объект, содержащий результат прогнозирования
|
||||
* @return средняя разница между датами исходного временного ряда в миллисекундах
|
||||
*/
|
||||
protected long getTimeDifferenceInMilliseconds(Forecast forecast) {
|
||||
long diffMilliseconds = 0;
|
||||
for (int i = 1; i < forecast.getModel().getOriginalTimeSeries().getLength(); i++) {
|
||||
diffMilliseconds += forecast.getModel().getOriginalTimeSeries().getValues().get(i - 1).getDate()
|
||||
.until(forecast.getModel().getOriginalTimeSeries().getValues().get(i).getDate(), ChronoUnit.MILLIS);
|
||||
}
|
||||
return diffMilliseconds / (forecast.getModel().getOriginalTimeSeries().getLength() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет построение модели и прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы
|
||||
* по модельным точкам.
|
||||
|
@ -34,7 +34,7 @@ public class NoTrendNoSeason extends TimeSeriesMethod {
|
||||
forecast.getForecastTimeSeries()
|
||||
.getValues()
|
||||
.get(t)
|
||||
.setValue(alpha * forecast.getForecastTimeSeries().getValues().get(t - 1).getValue());
|
||||
.setValue(forecast.getForecastTimeSeries().getValues().get(t - 1).getValue());
|
||||
}
|
||||
return forecast;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user