From 371dfe566591f928f6299b0866f0d4cf5d4db3aa Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Thu, 21 Apr 2022 11:54:55 +0400 Subject: [PATCH] #3 -- add fuzzy time series for forecasting --- .../ulstu/method/ftransform/AComponent.java | 29 ++++++++---- .../ulstu/method/ftransform/FTransform.java | 47 ++++++++++++++----- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/main/java/ru/ulstu/method/ftransform/AComponent.java b/src/main/java/ru/ulstu/method/ftransform/AComponent.java index 5ba4fe4..3292f37 100644 --- a/src/main/java/ru/ulstu/method/ftransform/AComponent.java +++ b/src/main/java/ru/ulstu/method/ftransform/AComponent.java @@ -1,21 +1,21 @@ package ru.ulstu.method.ftransform; /** - * Треугольная функция принадлежности + * Базисная функция */ public class AComponent { - private int start; // левая граница треугольника - private int end; // правая граница треугольника - private int top; // вершина треугольника + private double start; // левая граница треугольника + private double end; // правая граница треугольника + private double top; // вершина треугольника - public int getStart() { + public double getStart() { return start; } public AComponent() { } - public AComponent(int start, int top, int end) { + public AComponent(double start, double top, double end) { this.start = start; this.top = top; this.end = end; @@ -26,19 +26,23 @@ public class AComponent { } - public int getEnd() { + public double getEnd() { return end; } - public void setEnd(int end) { + public void setEnd(double end) { this.end = end; } - public int getTop() { + public double getTop() { return top; } - public void setTop(int top) { + public int getTopInt() { + return (int) Math.round(top); + } + + public void setTop(double top) { this.top = top; } @@ -54,4 +58,9 @@ public class AComponent { } return 0; } + + @Override + public String toString() { + return "start=" + start; + } } diff --git a/src/main/java/ru/ulstu/method/ftransform/FTransform.java b/src/main/java/ru/ulstu/method/ftransform/FTransform.java index e533c9c..eb266e1 100644 --- a/src/main/java/ru/ulstu/method/ftransform/FTransform.java +++ b/src/main/java/ru/ulstu/method/ftransform/FTransform.java @@ -3,14 +3,17 @@ package ru.ulstu.method.ftransform; import org.springframework.stereotype.Component; import ru.ulstu.datamodel.Model; import ru.ulstu.datamodel.ts.TimeSeries; +import ru.ulstu.datamodel.ts.TimeSeriesValue; import ru.ulstu.method.Method; import ru.ulstu.method.MethodParamValue; import ru.ulstu.method.MethodParameter; +import java.util.ArrayList; import java.util.List; @Component public class FTransform extends Method { + private final static int NUMBER_OF_FUZZY_VALUES = 3; @Override protected FTransformModel getModelOfValidTimeSeries(TimeSeries ts, @@ -29,8 +32,8 @@ public class FTransform extends Method { sum1 += membership * ts.getNumericValue(j); sum2 += membership; } - piecewiseLinearTrend.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2); - tsModel.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2); + piecewiseLinearTrend.addValue(ts.getValue(aComponent.getTopInt()), sum1 / sum2); + tsModel.addValue(ts.getValue(aComponent.getTopInt()), sum1 / sum2); } return model; } @@ -41,27 +44,27 @@ public class FTransform extends Method { 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); + : piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTopInt(); + AComponent aComponent = new AComponent(startPoint, currentPoint, (int) (currentPoint + Math.round(numberOfCoveredPoints / 2.0))); + if (aComponent.getStart() < 0) { + aComponent.setStart(0); } - if (bf.getEnd() > ts.getLength() - 1) { - bf.setEnd(ts.getLength() - 1); + if (aComponent.getEnd() > ts.getLength() - 1) { + aComponent.setEnd(ts.getLength() - 1); } - if (bf.getTop() > ts.getLength() - 1) { - bf.setTop(ts.getLength() - 1); + if (aComponent.getTop() > ts.getLength() - 1) { + aComponent.setTop(ts.getLength() - 1); } - piecewiseLinearTrend.add(bf); + piecewiseLinearTrend.add(aComponent); 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(), + AComponent aComponent = new AComponent(piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop(), piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd(), piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd()); - piecewiseLinearTrend.add(bf); + piecewiseLinearTrend.add(aComponent); } return piecewiseLinearTrend; } @@ -69,6 +72,24 @@ public class FTransform extends Method { @Override protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) { FTransformModel fTransformModel = (FTransformModel) model; + double minValue = fTransformModel.getPiecewiseLinearTrend().getValues().stream().map(TimeSeriesValue::getValue).min(Double::compareTo).orElse(0.0); + double maxValue = fTransformModel.getPiecewiseLinearTrend().getValues().stream().map(TimeSeriesValue::getValue).max(Double::compareTo).orElse(0.0); + List fuzzyValues = new ArrayList<>(); + double diff = (maxValue - minValue) / NUMBER_OF_FUZZY_VALUES; + for (int i = 0; i < NUMBER_OF_FUZZY_VALUES; i++) { + fuzzyValues.add(new AComponent(i * diff, i * diff + diff / 2, i * diff + diff)); + } + List fuzzyTimeSeries = new ArrayList<>(); + + for (int i = 0; i < model.getTimeSeriesModel().getLength(); i++) { + for (AComponent fuzzyValue : fuzzyValues) { + if (model.getTimeSeriesModel().getValue(i).getValue() >= fuzzyValue.getStart() + && model.getTimeSeriesModel().getValue(i).getValue() <= fuzzyValue.getEnd()) { + fuzzyTimeSeries.add(fuzzyValue); + } + } + } + for (int t = 1; t < forecast.getLength(); t++) { forecast.getValues().get(t).setValue(fTransformModel.getPiecewiseLinearTrend().getLastValue().getValue()); }