From 34db9f60183414ba0a35128763d34651ffaea329 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Wed, 19 Mar 2025 15:39:18 +0400 Subject: [PATCH] #14 -- Add forecast stub --- .../ru/ulstu/method/fuzzy/PlainFuzzy.java | 47 +++++++++++++------ .../ulstu/method/fuzzy/PlainFuzzyModel.java | 19 +------- .../java/ru/ulstu/method/fuzzy/Triangle.java | 23 +++++---- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzy.java b/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzy.java index f5f38dd..b5abddd 100644 --- a/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzy.java +++ b/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzy.java @@ -10,7 +10,7 @@ import ru.ulstu.method.MethodParamValue; import ru.ulstu.method.MethodParameter; import java.util.ArrayList; -import java.util.Comparator; +import java.util.DoubleSummaryStatistics; import java.util.List; @Component @@ -24,35 +24,54 @@ public class PlainFuzzy extends Method { protected Model getModelOfValidTimeSeries(TimeSeries timeSeries, List parameters) { PlainFuzzyModel model = new PlainFuzzyModel(timeSeries, parameters); List fuzzySets = generateFuzzySets(timeSeries, model.getNumberOfFuzzyTerms().getIntValue()); - return null; + for (TimeSeriesValue tsVal : timeSeries.getValues()) { + model.getTimeSeriesModel().addValue(new TimeSeriesValue( + tsVal.getDate(), + getMaxMembership(fuzzySets, tsVal).getTop())); + model.getFuzzyTimeSeries().add(getMaxMembership(fuzzySets, tsVal)); + } + return model; } private List generateFuzzySets(TimeSeries timeSeries, Integer numberOfFuzzyTerms) { - List fuzzySets = new ArrayList(); - double min = timeSeries.getValues() + // Universum + DoubleSummaryStatistics stat = timeSeries.getValues() .stream() - .min(Comparator.comparing(TimeSeriesValue::getValue)) - .map(TimeSeriesValue::getValue) - .orElseThrow(() -> new RuntimeException("Минимальное значение не найдено")); - double max = timeSeries.getValues() - .stream() - .max(Comparator.comparing(TimeSeriesValue::getValue)) - .map(TimeSeriesValue::getValue) - .orElseThrow(() -> new RuntimeException("Максимальное значение не найдено")); + .mapToDouble(TimeSeriesValue::getValue) + .summaryStatistics(); + double min = stat.getMin(); + double max = stat.getMax(); + // Generate fuzzy sets + List fuzzySets = new ArrayList<>(); double delta = ((max - min) / (numberOfFuzzyTerms - 1)); for (int i = 0; i < numberOfFuzzyTerms; i++) { fuzzySets.add(new Triangle(min + i * delta - delta, min + i * delta, - min + i * delta + delta)); + min + i * delta + delta, i)); } return fuzzySets; } + private Triangle getMaxMembership(List fuzzySets, TimeSeriesValue tsVal) { + Triangle maxTriangle = fuzzySets.get(0); + double membersip = 0; + for (Triangle triangle : fuzzySets) { + if (membersip < triangle.getValueAtPoint(tsVal.getValue())) { + maxTriangle = triangle; + membersip = triangle.getValueAtPoint(tsVal.getValue()); + } + } + return maxTriangle; + } + @Override protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) throws ModelingException { - return null; + for (TimeSeriesValue tsVal : forecast.getValues()) { + tsVal.setValue(0.0); + } + return forecast; } @Override diff --git a/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzyModel.java b/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzyModel.java index 686a6ca..a0e0553 100644 --- a/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzyModel.java +++ b/src/main/java/ru/ulstu/method/fuzzy/PlainFuzzyModel.java @@ -11,14 +11,11 @@ import java.util.Collections; import java.util.List; public class PlainFuzzyModel extends Model { - private final static String PREFIX_OF_FUZZY_LABEL = "X"; private final MethodParamValue numberOfFuzzyTerms = new MethodParamValue(NumberOfFuzzyTerms.getInstance(), 2); - private List fuzzyTimeSeries = new ArrayList<>(); - private TimeSeries defuzzyfiedTimeSeries; + private final List fuzzyTimeSeries = new ArrayList<>(); protected PlainFuzzyModel(TimeSeries ts, List parameters) { super(ts); - defuzzyfiedTimeSeries = new TimeSeries("Defuzzified time series of ", ts.getKey()); for (MethodParamValue parameter : parameters) { if (parameter.getParameter() instanceof NumberOfFuzzyTerms) { numberOfFuzzyTerms.setValue(parameter.getValue()); @@ -34,19 +31,7 @@ public class PlainFuzzyModel extends Model { return numberOfFuzzyTerms; } - public List getFuzzyTimeSeries() { + public List getFuzzyTimeSeries() { return fuzzyTimeSeries; } - - public void setFuzzyTimeSeries(List fuzzyTimeSeries) { - this.fuzzyTimeSeries = fuzzyTimeSeries; - } - - public TimeSeries getDefuzzyfiedTimeSeries() { - return defuzzyfiedTimeSeries; - } - - public void setDefuzzifiedTimeSeries(TimeSeries defuzzifiedTimeSeries) { - this.defuzzyfiedTimeSeries = defuzzifiedTimeSeries; - } } diff --git a/src/main/java/ru/ulstu/method/fuzzy/Triangle.java b/src/main/java/ru/ulstu/method/fuzzy/Triangle.java index 5bf0796..5ebf550 100644 --- a/src/main/java/ru/ulstu/method/fuzzy/Triangle.java +++ b/src/main/java/ru/ulstu/method/fuzzy/Triangle.java @@ -1,6 +1,8 @@ package ru.ulstu.method.fuzzy; public class Triangle { + private final static String FUZZY_LABEL_TEMPLATE = "X%s"; + private String label; private double start; // левая граница треугольника private double end; // правая граница треугольника private double top; // вершина треугольника @@ -9,10 +11,11 @@ public class Triangle { return start; } - public Triangle(double start, double top, double end) { + public Triangle(double start, double top, double end, int number) { this.start = start; this.top = top; this.end = end; + this.label = String.format(FUZZY_LABEL_TEMPLATE, number); } public void setStart(int start) { @@ -36,16 +39,20 @@ public class Triangle { this.top = top; } - public double getValueAtPoint(int pointIndex) { - if (pointIndex == this.getTop()) { + public double getValueAtPoint(double crispValue) { + if (crispValue == this.getTop()) { return 1; - } else if ((pointIndex >= this.getEnd()) || (pointIndex <= this.getStart())) { + } else if ((crispValue >= this.getEnd()) || (crispValue <= this.getStart())) { return 0; - } else if (pointIndex < this.getTop()) { - return (pointIndex - this.getStart()) / (this.getTop() - this.getStart()); - } else if (pointIndex > this.getTop()) { - return -(pointIndex - this.getEnd()) / (this.getEnd() - this.getTop()); + } else if (crispValue < this.getTop()) { + return (crispValue - this.getStart()) / (this.getTop() - this.getStart()); + } else if (crispValue > this.getTop()) { + return -(crispValue - this.getEnd()) / (this.getEnd() - this.getTop()); } return 0; } + + public String getLabel() { + return label; + } }