Merge pull request '3-add-f-transform' (#4) from 3-f-transform into master
Reviewed-on: #4
This commit is contained in:
commit
02555481e0
@ -55,45 +55,33 @@ public class IndexController {
|
|||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/method")
|
|
||||||
public String method(Model model) throws IOException {
|
|
||||||
model.addAttribute("sets", dbService.getSets());
|
|
||||||
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
|
||||||
model.addAttribute("chartForm", new ChartForm());
|
|
||||||
return "method";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("chartMethod")
|
|
||||||
public String chartMethod(@ModelAttribute ChartForm chartForm, Model model) throws IOException, ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
|
||||||
model.addAttribute("sets", dbService.getSets());
|
|
||||||
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
|
||||||
if (chartForm.getSet() != null && !chartForm.getSet().getKey().equals("")) {
|
|
||||||
model.addAttribute("listTimeSeries", dbService.getTimeSeriesMeta(chartForm.getSet()));
|
|
||||||
}
|
|
||||||
if (chartForm.getTimeSeriesMeta() != null
|
|
||||||
&& chartForm.getTimeSeriesMeta().getKey() != null
|
|
||||||
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
|
||||||
&& chartForm.getMethodClassName() != null
|
|
||||||
&& !chartForm.getMethodClassName().equals("")) {
|
|
||||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), chartForm.getMethodClassName(), model);
|
|
||||||
}
|
|
||||||
return "method";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addChartToModel(TimeSeries timeSeries, String method, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
private void addChartToModel(TimeSeries timeSeries, String method, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
||||||
TimeSeries timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
TimeSeries timeSeriesModel;
|
||||||
ModelingResult modelingResult;
|
ModelingResult modelingResult;
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
|
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
||||||
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
||||||
} else {
|
} else {
|
||||||
|
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries, method).getTimeSeries();
|
||||||
modelingResult = timeSeriesService.getForecast(timeSeries, method, countForecastPoints);
|
modelingResult = timeSeriesService.getForecast(timeSeries, method, countForecastPoints);
|
||||||
}
|
}
|
||||||
TimeSeries forecast = modelingResult.getTimeSeries();
|
TimeSeries forecast = modelingResult.getTimeSeries();
|
||||||
TimeSeries testForecast = modelingResult.getTestForecast();
|
TimeSeries testForecast = modelingResult.getTestForecast();
|
||||||
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
||||||
model.addAttribute("timeSeries", timeSeries.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
model.addAttribute("timeSeries", timeSeries.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
||||||
model.addAttribute("model", timeSeriesModel.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
// если временной ряд был сжат моделью, то для графика нужно вставить пустые значения
|
||||||
|
TimeSeries modelWithSkips = new TimeSeries(timeSeriesModel.getKey());
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < timeSeries.getLength(); i++) {
|
||||||
|
if (timeSeries.getValue(i).getDate().equals(timeSeriesModel.getValue(j).getDate())) {
|
||||||
|
modelWithSkips.addValue(timeSeriesModel.getValue(j));
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
modelWithSkips.addValue(new TimeSeriesValue((Double) null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.addAttribute("model", modelWithSkips.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
||||||
timeSeries.getValues().remove(timeSeries.getValues().size() - 1);
|
timeSeries.getValues().remove(timeSeries.getValues().size() - 1);
|
||||||
|
|
||||||
List<Double> forecastValues = timeSeries.getValues().stream().map(v -> (Double) null).collect(Collectors.toList());
|
List<Double> forecastValues = timeSeries.getValues().stream().map(v -> (Double) null).collect(Collectors.toList());
|
||||||
@ -119,4 +107,29 @@ public class IndexController {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/method")
|
||||||
|
public String method(Model model) throws IOException {
|
||||||
|
model.addAttribute("sets", dbService.getSets());
|
||||||
|
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
||||||
|
model.addAttribute("chartForm", new ChartForm());
|
||||||
|
return "method";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("chartMethod")
|
||||||
|
public String chartMethod(@ModelAttribute ChartForm chartForm, Model model) throws IOException, ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||||
|
model.addAttribute("sets", dbService.getSets());
|
||||||
|
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
||||||
|
if (chartForm.getSet() != null && !chartForm.getSet().getKey().equals("")) {
|
||||||
|
model.addAttribute("listTimeSeries", dbService.getTimeSeriesMeta(chartForm.getSet()));
|
||||||
|
}
|
||||||
|
if (chartForm.getTimeSeriesMeta() != null
|
||||||
|
&& chartForm.getTimeSeriesMeta().getKey() != null
|
||||||
|
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
||||||
|
&& chartForm.getMethodClassName() != null
|
||||||
|
&& !chartForm.getMethodClassName().equals("")) {
|
||||||
|
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), chartForm.getMethodClassName(), model);
|
||||||
|
}
|
||||||
|
return "method";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ public class DbFileService implements DbService {
|
|||||||
createDbIfNotExists();
|
createDbIfNotExists();
|
||||||
return Arrays.stream(Objects.requireNonNull(new File(timeSeriesDbPath).listFiles(File::isDirectory)))
|
return Arrays.stream(Objects.requireNonNull(new File(timeSeriesDbPath).listFiles(File::isDirectory)))
|
||||||
.map(TimeSeriesSet::new)
|
.map(TimeSeriesSet::new)
|
||||||
|
.sorted()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ public class DbFileService implements DbService {
|
|||||||
.readValue(Paths.get(getSetPath(timeSeriesSet).getAbsolutePath(), file.getName())
|
.readValue(Paths.get(getSetPath(timeSeriesSet).getAbsolutePath(), file.getName())
|
||||||
.toFile(), TimeSeriesMeta.class));
|
.toFile(), TimeSeriesMeta.class));
|
||||||
}
|
}
|
||||||
return list;
|
return list.stream().sorted().collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,7 +2,7 @@ package ru.ulstu.db.model;
|
|||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
public class TimeSeriesMeta {
|
public class TimeSeriesMeta implements Comparable<TimeSeriesMeta> {
|
||||||
private String key;
|
private String key;
|
||||||
private int size;
|
private int size;
|
||||||
private boolean hasDateTime;
|
private boolean hasDateTime;
|
||||||
@ -31,4 +31,9 @@ public class TimeSeriesMeta {
|
|||||||
public boolean isHasDateTime() {
|
public boolean isHasDateTime() {
|
||||||
return hasDateTime;
|
return hasDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TimeSeriesMeta o) {
|
||||||
|
return o != null ? key.compareTo(o.getKey()) : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package ru.ulstu.db.model;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class TimeSeriesSet {
|
public class TimeSeriesSet implements Comparable<TimeSeriesSet> {
|
||||||
private final String key;
|
private final String key;
|
||||||
|
|
||||||
public TimeSeriesSet(File dir) {
|
public TimeSeriesSet(File dir) {
|
||||||
@ -16,4 +16,9 @@ public class TimeSeriesSet {
|
|||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TimeSeriesSet o) {
|
||||||
|
return o != null ? key.compareTo(o.getKey()) : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,4 +16,12 @@ public class MethodParamValue {
|
|||||||
public Number getValue() {
|
public Number getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getIntValue() {
|
||||||
|
return value.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Number value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package ru.ulstu.method;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class MethodParameter implements Comparable {
|
public abstract class MethodParameter implements Comparable<MethodParameter> {
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
public MethodParameter(String name) {
|
public MethodParameter(String name) {
|
||||||
@ -13,10 +15,10 @@ public abstract class MethodParameter implements Comparable {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract List<Number> getAvailableValues();
|
public abstract List<Number> getAvailableValues(TimeSeries timeSeries);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Object o) {
|
public int compareTo(MethodParameter o) {
|
||||||
return this.name.compareTo(((MethodParameter) o).getName());
|
return this.name.compareTo(o.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.ulstu.method.exponential.addtrendaddseason;
|
package ru.ulstu.method.exponential.addtrendaddseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.method.MethodParamValue;
|
import ru.ulstu.method.MethodParamValue;
|
||||||
import ru.ulstu.method.MethodParameter;
|
import ru.ulstu.method.MethodParameter;
|
||||||
@ -13,7 +14,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AddTrendAddSeasonModel extends ru.ulstu.datamodel.Model {
|
public class AddTrendAddSeasonModel extends Model {
|
||||||
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
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<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
||||||
private final ExponentialMethodParamValue<Gamma> gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5);
|
private final ExponentialMethodParamValue<Gamma> gamma = new ExponentialMethodParamValue<>(Gamma.getInstance(), 0.5);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.ulstu.method.exponential.addtrendnoseason;
|
package ru.ulstu.method.exponential.addtrendnoseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.method.MethodParamValue;
|
import ru.ulstu.method.MethodParamValue;
|
||||||
import ru.ulstu.method.MethodParameter;
|
import ru.ulstu.method.MethodParameter;
|
||||||
@ -11,7 +12,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AddTrendNoSeasonModel extends ru.ulstu.datamodel.Model {
|
public class AddTrendNoSeasonModel extends Model {
|
||||||
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
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<Beta> beta = new ExponentialMethodParamValue<>(Beta.getInstance(), 0.5);
|
||||||
private final List<Double> smoothedComponent = new ArrayList<>();
|
private final List<Double> smoothedComponent = new ArrayList<>();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.ulstu.method.exponential.notrendnoseason;
|
package ru.ulstu.method.exponential.notrendnoseason;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.method.MethodParamValue;
|
import ru.ulstu.method.MethodParamValue;
|
||||||
import ru.ulstu.method.MethodParameter;
|
import ru.ulstu.method.MethodParameter;
|
||||||
@ -10,7 +11,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NoTrendNoSeasonModel extends ru.ulstu.datamodel.Model {
|
public class NoTrendNoSeasonModel extends Model {
|
||||||
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
private final ExponentialMethodParamValue<Alpha> alpha = new ExponentialMethodParamValue<>(Alpha.getInstance(), 0.5);
|
||||||
private final List<Double> smoothedComponent = new ArrayList<>();
|
private final List<Double> smoothedComponent = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.ulstu.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.method.MethodParameter;
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -35,7 +36,7 @@ public abstract class ExponentialMethodParameter extends MethodParameter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public List<Number> getAvailableValues() {
|
public List<Number> getAvailableValues(TimeSeries timeSeries) {
|
||||||
List<Number> values = new ArrayList<>();
|
List<Number> values = new ArrayList<>();
|
||||||
for (double i = minValue.doubleValue(); i <= maxValue.doubleValue(); i += optimizationStep.doubleValue()) {
|
for (double i = minValue.doubleValue(); i <= maxValue.doubleValue(); i += optimizationStep.doubleValue()) {
|
||||||
values.add(i);
|
values.add(i);
|
||||||
|
57
src/main/java/ru/ulstu/method/ftransform/AComponent.java
Normal file
57
src/main/java/ru/ulstu/method/ftransform/AComponent.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package ru.ulstu.method.ftransform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Треугольная функция принадлежности
|
||||||
|
*/
|
||||||
|
public class AComponent {
|
||||||
|
private int start; // левая граница треугольника
|
||||||
|
private int end; // правая граница треугольника
|
||||||
|
private int top; // вершина треугольника
|
||||||
|
|
||||||
|
public int getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AComponent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AComponent(int start, int top, int end) {
|
||||||
|
this.start = start;
|
||||||
|
this.top = top;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart(int start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getEnd() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnd(int end) {
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTop() {
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTop(int top) {
|
||||||
|
this.top = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValueAtPoint(int pointIndex) {
|
||||||
|
if (pointIndex == this.getTop()) {
|
||||||
|
return 1;
|
||||||
|
} else if ((pointIndex >= this.getEnd()) || (pointIndex <= this.getStart())) {
|
||||||
|
return 0;
|
||||||
|
} else if (pointIndex < this.getTop()) {
|
||||||
|
return (double) (pointIndex - this.getStart()) / (this.getTop() - this.getStart());
|
||||||
|
} else if (pointIndex > this.getTop()) {
|
||||||
|
return (double) -(pointIndex - this.getEnd()) / (this.getEnd() - this.getTop());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
87
src/main/java/ru/ulstu/method/ftransform/FTransform.java
Normal file
87
src/main/java/ru/ulstu/method/ftransform/FTransform.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package ru.ulstu.method.ftransform;
|
||||||
|
|
||||||
|
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 FTransform extends Method {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FTransformModel getModelOfValidTimeSeries(TimeSeries ts,
|
||||||
|
List<MethodParamValue> parameters) {
|
||||||
|
FTransformModel model = new FTransformModel(ts, parameters);
|
||||||
|
List<AComponent> aComponents = generateAComponents(ts, model.getNumberOfCoveredPoints().getIntValue(), model.getAComponents());
|
||||||
|
|
||||||
|
TimeSeries piecewiseLinearTrend = model.getPiecewiseLinearTrend();
|
||||||
|
TimeSeries tsModel = model.getTimeSeriesModel();
|
||||||
|
|
||||||
|
for (AComponent aComponent : aComponents) {
|
||||||
|
double sum1 = 0;
|
||||||
|
double sum2 = 0;
|
||||||
|
for (int j = 0; j < ts.getLength(); j++) {
|
||||||
|
double membership = aComponent.getValueAtPoint(j);
|
||||||
|
sum1 += membership * ts.getNumericValue(j);
|
||||||
|
sum2 += membership;
|
||||||
|
}
|
||||||
|
piecewiseLinearTrend.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2);
|
||||||
|
tsModel.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2);
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AComponent> generateAComponents(TimeSeries ts, int numberOfCoveredPoints, List<AComponent> piecewiseLinearTrend) {
|
||||||
|
long deltaForTriangle = Math.round(numberOfCoveredPoints / 2.0);
|
||||||
|
int currentPoint = 0;
|
||||||
|
while (currentPoint < ts.getLength()) {
|
||||||
|
int startPoint = (currentPoint == 0)
|
||||||
|
? 0
|
||||||
|
: piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop();
|
||||||
|
AComponent bf = new AComponent(startPoint, currentPoint, (int) (currentPoint + Math.round(numberOfCoveredPoints / 2.0)));
|
||||||
|
if (bf.getStart() < 0) {
|
||||||
|
bf.setStart(0);
|
||||||
|
}
|
||||||
|
if (bf.getEnd() > ts.getLength() - 1) {
|
||||||
|
bf.setEnd(ts.getLength() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bf.getTop() > ts.getLength() - 1) {
|
||||||
|
bf.setTop(ts.getLength() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
piecewiseLinearTrend.add(bf);
|
||||||
|
currentPoint += deltaForTriangle;
|
||||||
|
}
|
||||||
|
if (piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd() != piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop()) {
|
||||||
|
AComponent bf = new AComponent(piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop(),
|
||||||
|
piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd(),
|
||||||
|
piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd());
|
||||||
|
piecewiseLinearTrend.add(bf);
|
||||||
|
}
|
||||||
|
return piecewiseLinearTrend;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) {
|
||||||
|
FTransformModel fTransformModel = (FTransformModel) model;
|
||||||
|
for (int t = 1; t < forecast.getLength(); t++) {
|
||||||
|
forecast.getValues().get(t).setValue(fTransformModel.getPiecewiseLinearTrend().getLastValue().getValue());
|
||||||
|
}
|
||||||
|
return forecast;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
|
return FTransformModel.getAvailableParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "F - преобразование";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package ru.ulstu.method.ftransform;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.Model;
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.MethodParamValue;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
import ru.ulstu.method.ftransform.parameter.NumberOfCoveredPoints;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FTransformModel extends Model {
|
||||||
|
private final MethodParamValue numberOfCoveredPoints = new MethodParamValue(NumberOfCoveredPoints.getInstance(), 3);
|
||||||
|
private final List<AComponent> aComponents = new ArrayList<>();
|
||||||
|
private final TimeSeries piecewiseLinearTrend;
|
||||||
|
|
||||||
|
public FTransformModel(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||||
|
super(ts);
|
||||||
|
piecewiseLinearTrend = new TimeSeries("Piecewise linear trend of ", ts.getKey());
|
||||||
|
for (MethodParamValue parameter : parameters) {
|
||||||
|
if (parameter.getParameter() instanceof NumberOfCoveredPoints) {
|
||||||
|
numberOfCoveredPoints.setValue(parameter.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSeries getPiecewiseLinearTrend() {
|
||||||
|
return piecewiseLinearTrend;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AComponent> getAComponents() {
|
||||||
|
return aComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodParamValue getNumberOfCoveredPoints() {
|
||||||
|
return numberOfCoveredPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MethodParameter> getAvailableParameters() {
|
||||||
|
return Collections.singletonList(NumberOfCoveredPoints.getInstance());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package ru.ulstu.method.ftransform.parameter;
|
||||||
|
|
||||||
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.MethodParameter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NumberOfCoveredPoints extends MethodParameter {
|
||||||
|
private final static int MIN_NUMBER_OF_COVERED_POINTS = 3;
|
||||||
|
private final static int MIN_INCREASING_STEP_OF_NUMBER_OF_COVERED_POINTS = 2;
|
||||||
|
|
||||||
|
public NumberOfCoveredPoints() {
|
||||||
|
super("Number of covered points");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NumberOfCoveredPoints getInstance() {
|
||||||
|
return new NumberOfCoveredPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Number> getAvailableValues(TimeSeries timeSeries) {
|
||||||
|
List<Number> values = new ArrayList<>();
|
||||||
|
for (double i = MIN_NUMBER_OF_COVERED_POINTS; i <= (timeSeries.getLength() < 10 ? 7 : timeSeries.getLength() / 3.0); i += MIN_INCREASING_STEP_OF_NUMBER_OF_COVERED_POINTS) {
|
||||||
|
values.add(i);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ class MethodParamBruteForce {
|
|||||||
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue));
|
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue));
|
||||||
|
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
List<List<MethodParamValue>> availableParametersValues = getAvailableParametersValues(method.getAvailableParameters());
|
List<List<MethodParamValue>> availableParametersValues = getAvailableParametersValues(timeSeries, method.getAvailableParameters());
|
||||||
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)) {
|
||||||
@ -119,7 +119,7 @@ class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries, List<Method> methods) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ class MethodParamBruteForce {
|
|||||||
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue));
|
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue));
|
||||||
|
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
List<List<MethodParamValue>> availableParametersValues = getAvailableParametersValues(method.getAvailableParameters());
|
List<List<MethodParamValue>> availableParametersValues = getAvailableParametersValues(timeSeries, method.getAvailableParameters());
|
||||||
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
||||||
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||||
if (methodInstance.canMakeModel(timeSeries, parametersValues)) {
|
if (methodInstance.canMakeModel(timeSeries, parametersValues)) {
|
||||||
@ -150,13 +150,25 @@ class MethodParamBruteForce {
|
|||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<MethodParamValue>> getAvailableParametersValues(List<MethodParameter> availableParameters) {
|
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries, String methodClassName) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
Method method = methods.stream()
|
||||||
|
.filter(m -> m.getClass().getSimpleName().equals(methodClassName))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(() -> new ModelingException("Неизвестный метод прогнозирования"));
|
||||||
|
return getSmoothedTimeSeries(timeSeries, List.of(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
|
return getSmoothedTimeSeries(timeSeries, methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<List<MethodParamValue>> getAvailableParametersValues(TimeSeries timeSeries, List<MethodParameter> availableParameters) {
|
||||||
List<List<MethodParamValue>> 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) {
|
||||||
parameterOffset.put(methodParameter, 0);
|
parameterOffset.put(methodParameter, 0);
|
||||||
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
parameterValues.put(methodParameter, methodParameter.getAvailableValues(timeSeries));
|
||||||
}
|
}
|
||||||
while (isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
while (isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
||||||
List<MethodParamValue> resultRow = new ArrayList<>();
|
List<MethodParamValue> resultRow = new ArrayList<>();
|
||||||
|
@ -35,6 +35,10 @@ public class TimeSeriesService {
|
|||||||
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries);
|
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModelingResult smoothTimeSeries(TimeSeries timeSeries, String methodClassName) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries, methodClassName);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Method> getAvailableMethods() {
|
public List<Method> getAvailableMethods() {
|
||||||
return methodParamBruteForce.getAvailableMethods();
|
return methodParamBruteForce.getAvailableMethods();
|
||||||
}
|
}
|
||||||
|
@ -63,21 +63,25 @@
|
|||||||
{
|
{
|
||||||
name: [[#{messages.time_series}]],
|
name: [[#{messages.time_series}]],
|
||||||
color: 'rgba(119,152,191,0.5)',
|
color: 'rgba(119,152,191,0.5)',
|
||||||
|
connectNulls: true,
|
||||||
data: [[${timeSeries}]]
|
data: [[${timeSeries}]]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: [[#{messages.time_series_model}]],
|
name: [[#{messages.time_series_model}]],
|
||||||
color: 'rgba(255,200,0,0.5)',
|
color: 'rgba(255,200,0,0.5)',
|
||||||
|
connectNulls: true,
|
||||||
data: [[${model}]]
|
data: [[${model}]]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: [[#{messages.time_series_test_forecast}]],
|
name: [[#{messages.time_series_test_forecast}]],
|
||||||
color: 'rgba(255,0,0,0.5)',
|
color: 'rgba(255,0,0,0.5)',
|
||||||
|
connectNulls: true,
|
||||||
data: [[${testForecast}]]
|
data: [[${testForecast}]]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: [[#{messages.time_series_forecast_short}]],
|
name: [[#{messages.time_series_forecast_short}]],
|
||||||
color: 'rgba(255,0,0,0.5)',
|
color: 'rgba(255,0,0,0.5)',
|
||||||
|
connectNulls: true,
|
||||||
data: [[${forecast}]]
|
data: [[${forecast}]]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user