From 4216356c35fc8e750917fc889dc6542b9431591b Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Mon, 6 Feb 2023 13:54:12 +0400 Subject: [PATCH 1/2] #86 -- divide bl --- .../controller/AssessmentController.java | 10 +-- .../rule/service/FuzzyInferenceService.java | 67 +--------------- .../service/assessment/AssessmentService.java | 78 +++++++++++++++++++ .../java/ru/ulstu/FuzzyInferenceTest.java | 15 ++++ .../java/ru/ulstu/TimeSeriesMapperTest.java | 28 +++---- 5 files changed, 115 insertions(+), 83 deletions(-) create mode 100644 src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java create mode 100644 src/test/java/ru/ulstu/FuzzyInferenceTest.java diff --git a/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java b/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java index 3e3d3cc..b960b4d 100644 --- a/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java +++ b/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java @@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import ru.ulstu.extractor.assessment.model.FilterBranchForm; import ru.ulstu.extractor.branch.service.BranchService; -import ru.ulstu.extractor.rule.service.FuzzyInferenceService; +import ru.ulstu.extractor.service.assessment.AssessmentService; import springfox.documentation.annotations.ApiIgnore; import java.util.Optional; @@ -16,12 +16,12 @@ import static ru.ulstu.extractor.core.Route.ASSESSMENTS; @Controller @ApiIgnore public class AssessmentController { - private final FuzzyInferenceService fuzzyInferenceService; + private final AssessmentService assessmentService; private final BranchService branchService; - public AssessmentController(FuzzyInferenceService fuzzyInferenceService, + public AssessmentController(AssessmentService assessmentService, BranchService branchService) { - this.fuzzyInferenceService = fuzzyInferenceService; + this.assessmentService = assessmentService; this.branchService = branchService; } @@ -29,7 +29,7 @@ public class AssessmentController { public String getAssessments(Model model, @RequestParam Optional branchId) { model.addAttribute("branches", branchService.findAll()); if (branchId.isPresent()) { - model.addAttribute("assessments", fuzzyInferenceService.getAssessmentsByForecastTendencies(branchId.get())); + model.addAttribute("assessments", assessmentService.getAssessmentsByForecastTendencies(branchId.get())); model.addAttribute("filterBranchForm", new FilterBranchForm(branchId.get())); } else { model.addAttribute("filterBranchForm", new FilterBranchForm()); diff --git a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java index 9d8bc86..38a6a58 100644 --- a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java +++ b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java @@ -13,15 +13,10 @@ import com.fuzzylite.variable.InputVariable; import com.fuzzylite.variable.OutputVariable; import org.springframework.stereotype.Service; import ru.ulstu.extractor.assessment.model.Assessment; -import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.rule.model.AntecedentValue; -import ru.ulstu.extractor.rule.model.AssessmentException; import ru.ulstu.extractor.rule.model.DbRule; -import ru.ulstu.extractor.ts.model.TimeSeries; -import ru.ulstu.extractor.ts.service.TimeSeriesService; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -34,22 +29,8 @@ public class FuzzyInferenceService { + OUTPUT_VARIABLE_NAME + " is %s"; private final static String NO_RESULT = "Нет результата"; - private final DbRuleService ruleService; - private final AntecedentValueService antecedentValueService; - private final GitRepositoryService gitRepositoryService; - private final TimeSeriesService timeSeriesService; - public FuzzyInferenceService(DbRuleService ruleService, - AntecedentValueService antecedentValueService, - GitRepositoryService gitRepositoryService, - TimeSeriesService timeSeriesService) { - this.ruleService = ruleService; - this.antecedentValueService = antecedentValueService; - this.gitRepositoryService = gitRepositoryService; - this.timeSeriesService = timeSeriesService; - } - - public List getRulesFromDb(List dbRules, Map variableValues) { + private List getRulesFromDb(List dbRules, Map variableValues) { validateVariables(variableValues, dbRules); return dbRules.stream().map(this::getFuzzyRule).collect(Collectors.toList()); } @@ -114,23 +95,8 @@ public class FuzzyInferenceService { return engine; } - public List getAssessmentsByForecastTendencies(Integer branchId) { - List timeSeries = timeSeriesService.getByBranch(branchId); - List dbRules = ruleService.getList(); - try { - return getAssessmentsByTimeSeriesTendencies(dbRules, timeSeries); - } catch (AssessmentException ex) { - return new ArrayList<>(); - } - } - public List getAssessmentsByLastValues(Integer branchId) { - List timeSeries = timeSeriesService.getByBranch(branchId); - List dbRules = ruleService.getList(); - return getAssessmentsByLastValues(dbRules, timeSeries); - } - - private List getFuzzyInference(List dbRules, Map variableValues) { + public List getFuzzyInference(List dbRules, Map variableValues) { Engine engine = getFuzzyEngine(); List antecedentValues = Stream.concat(dbRules.stream().map(DbRule::getFirstAntecedentValue), dbRules.stream().map(DbRule::getSecondAntecedentValue)).distinct().collect(Collectors.toList()); @@ -147,35 +113,6 @@ public class FuzzyInferenceService { .collect(Collectors.toList()); } - private List getSingleAssessmentByTimeSeriesTendencies(List dbRules, List timeSeries) throws AssessmentException { - Map variableValues = new HashMap<>(); - timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), - timeSeriesService.getLastTimeSeriesTendency(ts) - .orElseThrow(() -> new AssessmentException("")))); - return getFuzzyInference(dbRules, variableValues); - } - - private List getAssessmentsByTimeSeriesTendencies(List dbRules, List timeSeries) { - return dbRules - .stream() - .flatMap(dbRule -> { - Map variableValues = new HashMap<>(); - timeSeries - .stream() - .filter(ts -> ts.getTimeSeriesType() == dbRule.getFirstAntecedent() - || ts.getTimeSeriesType() == dbRule.getSecondAntecedent()) - .forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService - .getLastTimeSeriesTendency(ts) - .orElseThrow(() -> new AssessmentException("")))); - return getFuzzyInference(List.of(dbRule), variableValues).stream(); - }).collect(Collectors.toList()); - } - - private List getAssessmentsByLastValues(List dbRules, List timeSeries) { - Map variableValues = new HashMap<>(); - timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), ts.getValues().get(ts.getValues().size() - 1).getValue())); - return getFuzzyInference(dbRules, variableValues); - } private void validateVariables(Map variableValues, List dbDbRules) { for (DbRule dbRule : dbDbRules) { diff --git a/src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java b/src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java new file mode 100644 index 0000000..5edd2ec --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java @@ -0,0 +1,78 @@ +package ru.ulstu.extractor.service.assessment; + +import org.springframework.stereotype.Service; +import ru.ulstu.extractor.assessment.model.Assessment; +import ru.ulstu.extractor.rule.model.AssessmentException; +import ru.ulstu.extractor.rule.model.DbRule; +import ru.ulstu.extractor.rule.service.DbRuleService; +import ru.ulstu.extractor.rule.service.FuzzyInferenceService; +import ru.ulstu.extractor.ts.model.TimeSeries; +import ru.ulstu.extractor.ts.service.TimeSeriesService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class AssessmentService { + private final DbRuleService ruleService; + private final TimeSeriesService timeSeriesService; + private final FuzzyInferenceService fuzzyInferenceService; + + public AssessmentService(DbRuleService ruleService, + TimeSeriesService timeSeriesService, + FuzzyInferenceService fuzzyInferenceService) { + this.ruleService = ruleService; + this.timeSeriesService = timeSeriesService; + this.fuzzyInferenceService = fuzzyInferenceService; + } + + public List getAssessmentsByForecastTendencies(Integer branchId) { + List timeSeries = timeSeriesService.getByBranch(branchId); + List dbRules = ruleService.getList(); + try { + return getAssessmentsByTimeSeriesTendencies(dbRules, timeSeries); + } catch (AssessmentException ex) { + return new ArrayList<>(); + } + } + + public List getAssessmentsByLastValues(Integer branchId) { + List timeSeries = timeSeriesService.getByBranch(branchId); + List dbRules = ruleService.getList(); + return getAssessmentsByLastValues(dbRules, timeSeries); + } + + private List getSingleAssessmentByTimeSeriesTendencies(List dbRules, List timeSeries) throws AssessmentException { + Map variableValues = new HashMap<>(); + timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), + timeSeriesService.getLastTimeSeriesTendency(ts) + .orElseThrow(() -> new AssessmentException("")))); + return fuzzyInferenceService.getFuzzyInference(dbRules, variableValues); + } + + private List getAssessmentsByTimeSeriesTendencies(List dbRules, List timeSeries) { + return dbRules + .stream() + .flatMap(dbRule -> { + Map variableValues = new HashMap<>(); + timeSeries + .stream() + .filter(ts -> ts.getTimeSeriesType() == dbRule.getFirstAntecedent() + || ts.getTimeSeriesType() == dbRule.getSecondAntecedent()) + .forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService + .getLastTimeSeriesTendency(ts) + .orElseThrow(() -> new AssessmentException("")))); + return fuzzyInferenceService.getFuzzyInference(List.of(dbRule), variableValues).stream(); + }).collect(Collectors.toList()); + } + + private List getAssessmentsByLastValues(List dbRules, List timeSeries) { + Map variableValues = new HashMap<>(); + timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), ts.getValues().get(ts.getValues().size() - 1).getValue())); + return fuzzyInferenceService.getFuzzyInference(dbRules, variableValues); + } + +} diff --git a/src/test/java/ru/ulstu/FuzzyInferenceTest.java b/src/test/java/ru/ulstu/FuzzyInferenceTest.java new file mode 100644 index 0000000..99d69ef --- /dev/null +++ b/src/test/java/ru/ulstu/FuzzyInferenceTest.java @@ -0,0 +1,15 @@ +package ru.ulstu; + +import org.junit.Assert; +import org.junit.Test; +import ru.ulstu.extractor.rule.service.FuzzyInferenceService; + +public class FuzzyInferenceTest { + + private final FuzzyInferenceService fuzzyInferenceService = new FuzzyInferenceService(); + + @Test + public void test() { + Assert.assertNotNull(fuzzyInferenceService); + } +} diff --git a/src/test/java/ru/ulstu/TimeSeriesMapperTest.java b/src/test/java/ru/ulstu/TimeSeriesMapperTest.java index d799a2b..9beb443 100644 --- a/src/test/java/ru/ulstu/TimeSeriesMapperTest.java +++ b/src/test/java/ru/ulstu/TimeSeriesMapperTest.java @@ -2,7 +2,9 @@ package ru.ulstu; import org.junit.Assert; import org.junit.Test; +import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.ts.model.TimeSeries; +import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.util.TimeSeriesDateMapper; @@ -17,13 +19,13 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2020, 5, 2, 2, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); - timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); + timeSeries = TimeSeriesDateMapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); Assert.assertEquals(1, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue()); } @Test @@ -32,13 +34,13 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2020, 5, 2, 1, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); Assert.assertEquals(1, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue()); } @Test @@ -47,13 +49,13 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2020, 5, 2, 1, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); Assert.assertEquals(1, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue()); } @Test @@ -62,13 +64,13 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2020, 6, 2, 1, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); Assert.assertEquals(2, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(10), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(10), timeSeries.getValues().get(0).getValue()); } @Test @@ -77,13 +79,13 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2020, 5, 2, 1, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries); Assert.assertEquals(1, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue()); } @Test @@ -92,12 +94,12 @@ public class TimeSeriesMapperTest { c1.set(2020, 5, 1, 1, 1, 1); Calendar c2 = GregorianCalendar.getInstance(); c2.set(2021, 5, 2, 1, 1, 1); - TimeSeries timeSeries = new TimeSeries("Тестовый", + TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS, Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), new TimeSeriesValue(c2.getTime(), 10.0))); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries); Assert.assertEquals(2, timeSeries.getValues().size()); - Assert.assertEquals(Integer.valueOf(10), timeSeries.getValues().get(0).getValue()); + Assert.assertEquals(Double.valueOf(10), timeSeries.getValues().get(0).getValue()); } } From 4143fcfb20638651f2a5564d96c1491487150ae6 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Tue, 7 Feb 2023 16:36:32 +0400 Subject: [PATCH 2/2] #86 -- fix fuzzy inference --- .../controller/AssessmentController.java | 2 +- .../assessment/model/Assessment.java | 8 +- .../service}/AssessmentService.java | 68 +++++++++++++++-- .../service/GitRepositoryService.java | 1 - .../extractor/rule/model/AntecedentValue.java | 3 +- .../rule/service/FuzzyInferenceService.java | 75 ++++++++++++------- src/main/resources/templates/assessments.html | 1 + .../java/ru/ulstu/FuzzyInferenceTest.java | 15 ---- 8 files changed, 120 insertions(+), 53 deletions(-) rename src/main/java/ru/ulstu/extractor/{service/assessment => assessment/service}/AssessmentService.java (55%) delete mode 100644 src/test/java/ru/ulstu/FuzzyInferenceTest.java diff --git a/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java b/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java index b960b4d..3434377 100644 --- a/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java +++ b/src/main/java/ru/ulstu/extractor/assessment/controller/AssessmentController.java @@ -5,8 +5,8 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import ru.ulstu.extractor.assessment.model.FilterBranchForm; +import ru.ulstu.extractor.assessment.service.AssessmentService; import ru.ulstu.extractor.branch.service.BranchService; -import ru.ulstu.extractor.service.assessment.AssessmentService; import springfox.documentation.annotations.ApiIgnore; import java.util.Optional; diff --git a/src/main/java/ru/ulstu/extractor/assessment/model/Assessment.java b/src/main/java/ru/ulstu/extractor/assessment/model/Assessment.java index f6609b4..db5e048 100644 --- a/src/main/java/ru/ulstu/extractor/assessment/model/Assessment.java +++ b/src/main/java/ru/ulstu/extractor/assessment/model/Assessment.java @@ -9,13 +9,15 @@ public class Assessment { private final String firstAntecedentTendency; private final TimeSeriesType secondAntecedent; private final String secondAntecedentTendency; + private final Double degree; - public Assessment(DbRule dbRule) { + public Assessment(DbRule dbRule, Double degree) { this.consequent = dbRule.getConsequent(); this.firstAntecedent = dbRule.getFirstAntecedent(); this.firstAntecedentTendency = dbRule.getFirstAntecedentValue().getAntecedentValue(); this.secondAntecedent = dbRule.getSecondAntecedent(); this.secondAntecedentTendency = dbRule.getSecondAntecedentValue().getAntecedentValue(); + this.degree = degree; } public String getConsequent() { @@ -37,4 +39,8 @@ public class Assessment { public String getSecondAntecedentTendency() { return secondAntecedentTendency; } + + public Double getDegree() { + return degree; + } } diff --git a/src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java b/src/main/java/ru/ulstu/extractor/assessment/service/AssessmentService.java similarity index 55% rename from src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java rename to src/main/java/ru/ulstu/extractor/assessment/service/AssessmentService.java index 5edd2ec..d221806 100644 --- a/src/main/java/ru/ulstu/extractor/service/assessment/AssessmentService.java +++ b/src/main/java/ru/ulstu/extractor/assessment/service/AssessmentService.java @@ -1,15 +1,18 @@ -package ru.ulstu.extractor.service.assessment; +package ru.ulstu.extractor.assessment.service; import org.springframework.stereotype.Service; import ru.ulstu.extractor.assessment.model.Assessment; import ru.ulstu.extractor.rule.model.AssessmentException; import ru.ulstu.extractor.rule.model.DbRule; +import ru.ulstu.extractor.rule.service.AntecedentValueService; import ru.ulstu.extractor.rule.service.DbRuleService; import ru.ulstu.extractor.rule.service.FuzzyInferenceService; import ru.ulstu.extractor.ts.model.TimeSeries; +import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.service.TimeSeriesService; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,13 +21,16 @@ import java.util.stream.Collectors; @Service public class AssessmentService { private final DbRuleService ruleService; + private final AntecedentValueService antecedentValueService; private final TimeSeriesService timeSeriesService; private final FuzzyInferenceService fuzzyInferenceService; public AssessmentService(DbRuleService ruleService, + AntecedentValueService antecedentValueService, TimeSeriesService timeSeriesService, FuzzyInferenceService fuzzyInferenceService) { this.ruleService = ruleService; + this.antecedentValueService = antecedentValueService; this.timeSeriesService = timeSeriesService; this.fuzzyInferenceService = fuzzyInferenceService; } @@ -35,6 +41,7 @@ public class AssessmentService { try { return getAssessmentsByTimeSeriesTendencies(dbRules, timeSeries); } catch (AssessmentException ex) { + ex.printStackTrace(); return new ArrayList<>(); } } @@ -50,7 +57,11 @@ public class AssessmentService { timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService.getLastTimeSeriesTendency(ts) .orElseThrow(() -> new AssessmentException("")))); - return fuzzyInferenceService.getFuzzyInference(dbRules, variableValues); + return fuzzyInferenceService.getFuzzyInference(dbRules, + antecedentValueService.getList(), + variableValues, + getTSsMin(timeSeries), + getTSsMax(timeSeries)); } private List getAssessmentsByTimeSeriesTendencies(List dbRules, List timeSeries) { @@ -64,15 +75,60 @@ public class AssessmentService { || ts.getTimeSeriesType() == dbRule.getSecondAntecedent()) .forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService .getLastTimeSeriesTendency(ts) - .orElseThrow(() -> new AssessmentException("")))); - return fuzzyInferenceService.getFuzzyInference(List.of(dbRule), variableValues).stream(); - }).collect(Collectors.toList()); + .orElse(ts.getValues().get(ts.getValues().size() - 1).getValue()))); + return fuzzyInferenceService.getFuzzyInference(List.of(dbRule), + antecedentValueService.getList(), + variableValues, + getTSsMin(timeSeries), + getTSsMax(timeSeries)).stream(); + }) + .sorted(Comparator.comparing(Assessment::getDegree)) + .collect(Collectors.toList()); } private List getAssessmentsByLastValues(List dbRules, List timeSeries) { Map variableValues = new HashMap<>(); timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), ts.getValues().get(ts.getValues().size() - 1).getValue())); - return fuzzyInferenceService.getFuzzyInference(dbRules, variableValues); + return fuzzyInferenceService.getFuzzyInference(dbRules, + antecedentValueService.getList(), + variableValues, + getTSsMin(timeSeries), + getTSsMax(timeSeries)); } + private Double getMin(List values) { + return values.stream().mapToDouble(v -> v).min().getAsDouble(); + } + + private Map.Entry getTSMin(TimeSeries ts) { + return Map.entry(ts.getTimeSeriesType().name(), + getMin(ts.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()))); + } + + private Map getTSsMin(List tss) { + Map res = new HashMap<>(); + tss.forEach(ts -> { + Map.Entry entry = getTSMin(ts); + res.put(entry.getKey(), entry.getValue()); + }); + return res; + } + + private Double getMax(List values) { + return values.stream().mapToDouble(v -> v).max().getAsDouble(); + } + + private Map.Entry getTSMax(TimeSeries ts) { + return Map.entry(ts.getTimeSeriesType().name(), + getMax(ts.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()))); + } + + private Map getTSsMax(List tss) { + Map res = new HashMap<>(); + tss.forEach(ts -> { + Map.Entry entry = getTSMax(ts); + res.put(entry.getKey(), entry.getValue()); + }); + return res; + } } diff --git a/src/main/java/ru/ulstu/extractor/gitrepository/service/GitRepositoryService.java b/src/main/java/ru/ulstu/extractor/gitrepository/service/GitRepositoryService.java index 2802edf..2d451e1 100644 --- a/src/main/java/ru/ulstu/extractor/gitrepository/service/GitRepositoryService.java +++ b/src/main/java/ru/ulstu/extractor/gitrepository/service/GitRepositoryService.java @@ -283,7 +283,6 @@ public class GitRepositoryService { List changes = new ArrayList<>(); String[] strings = output.split("\n"); Map> filesContent = getFilesContent(strings); - System.out.println(filesContent); for(Map.Entry> fileSterings: filesContent.entrySet()) { FileChange fileChange = new FileChange(); fileChange.setFile(fileSterings.getKey()); diff --git a/src/main/java/ru/ulstu/extractor/rule/model/AntecedentValue.java b/src/main/java/ru/ulstu/extractor/rule/model/AntecedentValue.java index 39b5eb6..3583e6a 100644 --- a/src/main/java/ru/ulstu/extractor/rule/model/AntecedentValue.java +++ b/src/main/java/ru/ulstu/extractor/rule/model/AntecedentValue.java @@ -11,7 +11,8 @@ public class AntecedentValue extends BaseEntity { public AntecedentValue() { } - public AntecedentValue(String antecedentValue) { + public AntecedentValue(Integer id, String antecedentValue) { + this.setId(id); this.antecedentValue = antecedentValue; } diff --git a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java index 38a6a58..6768c87 100644 --- a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java +++ b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java @@ -1,16 +1,18 @@ package ru.ulstu.extractor.rule.service; import com.fuzzylite.Engine; -import com.fuzzylite.activation.Highest; +import com.fuzzylite.activation.General; import com.fuzzylite.defuzzifier.Centroid; -import com.fuzzylite.norm.s.BoundedSum; import com.fuzzylite.norm.s.Maximum; import com.fuzzylite.norm.t.AlgebraicProduct; +import com.fuzzylite.norm.t.Minimum; import com.fuzzylite.rule.Rule; import com.fuzzylite.rule.RuleBlock; import com.fuzzylite.term.Triangle; import com.fuzzylite.variable.InputVariable; import com.fuzzylite.variable.OutputVariable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import ru.ulstu.extractor.assessment.model.Assessment; import ru.ulstu.extractor.rule.model.AntecedentValue; @@ -20,10 +22,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import java.util.stream.Stream; + +import static java.lang.String.format; @Service public class FuzzyInferenceService { + private final static Logger LOG = LoggerFactory.getLogger(FuzzyInferenceService.class); private final static String OUTPUT_VARIABLE_NAME = "state"; private final static String RULE_TEMPLATE = "if %s is %s and %s is %s then " + OUTPUT_VARIABLE_NAME @@ -36,7 +40,7 @@ public class FuzzyInferenceService { } private String getFuzzyRule(DbRule dbRule) { - return String.format(RULE_TEMPLATE, + return format(RULE_TEMPLATE, dbRule.getFirstAntecedent().name(), dbRule.getFirstAntecedentValue().getAntecedentValue(), dbRule.getSecondAntecedent().name(), @@ -47,6 +51,8 @@ public class FuzzyInferenceService { private RuleBlock getRuleBlock(Engine engine, List dbRules, Map variableValues, + Map min, + Map max, List antecedentValues, List consequentValues) { variableValues.forEach((key, value) -> { @@ -54,10 +60,19 @@ public class FuzzyInferenceService { input.setName(key); input.setDescription(""); input.setEnabled(true); - input.setRange(-0.1, antecedentValues.size() + 1.1); + double delta = antecedentValues.size() > 1 + ? (max.get(key) - min.get(key)) / (antecedentValues.size() - 1) + : (max.get(key) - min.get(key)); + input.setRange(min.get(key), max.get(key)); input.setLockValueInRange(false); for (int i = 0; i < antecedentValues.size(); i++) { - input.addTerm(new Triangle(antecedentValues.get(i).getAntecedentValue(), i - 0.1, i + 2.1)); + input.addTerm( + new Triangle( + antecedentValues.get(i).getAntecedentValue(), + min.get(key) + i * delta - 0.5 * delta, + min.get(key) + i * delta + delta + 0.5 * delta + ) + ); } engine.addInputVariable(input); }); @@ -66,13 +81,13 @@ public class FuzzyInferenceService { output.setName(OUTPUT_VARIABLE_NAME); output.setDescription(""); output.setEnabled(true); - output.setRange(-0.1, consequentValues.size() + 0.1); + output.setRange(0, consequentValues.size() + 0.1); output.setAggregation(new Maximum()); - output.setDefuzzifier(new Centroid(100)); + output.setDefuzzifier(new Centroid(10)); output.setDefaultValue(Double.NaN); output.setLockValueInRange(false); for (int i = 0; i < consequentValues.size(); i++) { - output.addTerm(new Triangle(consequentValues.get(i).toString(), i - 0.1, i + 2.1)); + output.addTerm(new Triangle(consequentValues.get(i).toString(), i, i + 2.1)); } engine.addOutputVariable(output); @@ -80,11 +95,14 @@ public class FuzzyInferenceService { mamdani.setName("mamdani"); mamdani.setDescription(""); mamdani.setEnabled(true); - mamdani.setConjunction(new AlgebraicProduct()); - mamdani.setDisjunction(new BoundedSum()); + mamdani.setConjunction(new Minimum()); + //mamdani.setDisjunction(null); mamdani.setImplication(new AlgebraicProduct()); - mamdani.setActivation(new Highest()); - getRulesFromDb(dbRules, variableValues).forEach(r -> mamdani.addRule(Rule.parse(r, engine))); + mamdani.setActivation(new General()); + getRulesFromDb(dbRules, variableValues).forEach(r -> { + LOG.info(r); + mamdani.addRule(Rule.parse(r, engine)); + }); return mamdani; } @@ -95,21 +113,22 @@ public class FuzzyInferenceService { return engine; } - - public List getFuzzyInference(List dbRules, Map variableValues) { + public List getFuzzyInference(List dbRules, + List antecedentValues, + Map variableValues, + Map min, + Map max) { Engine engine = getFuzzyEngine(); - List antecedentValues = Stream.concat(dbRules.stream().map(DbRule::getFirstAntecedentValue), - dbRules.stream().map(DbRule::getSecondAntecedentValue)).distinct().collect(Collectors.toList()); List consequentValues = dbRules.stream().map(DbRule::getId).collect(Collectors.toList()); - engine.addRuleBlock(getRuleBlock(engine, dbRules, variableValues, antecedentValues, consequentValues)); - String consequent = getConsequent(engine, variableValues); - if (consequent.equals(NO_RESULT)) { + engine.addRuleBlock(getRuleBlock(engine, dbRules, variableValues, min, max, antecedentValues, consequentValues)); + Map.Entry consequent = getConsequent(engine, variableValues); + if (consequent.getKey().equals(NO_RESULT)) { return new ArrayList<>(); } return dbRules .stream() - .filter(r -> r.getId().equals(Integer.valueOf(consequent))) - .map(Assessment::new) + .filter(r -> r.getId().equals(Integer.valueOf(consequent.getKey()))) + .map(r -> new Assessment(r, consequent.getValue())) .collect(Collectors.toList()); } @@ -117,17 +136,17 @@ public class FuzzyInferenceService { private void validateVariables(Map variableValues, List dbDbRules) { for (DbRule dbRule : dbDbRules) { if (!variableValues.containsKey(dbRule.getFirstAntecedent().name())) { - throw new RuntimeException(String.format("Переменной в правиле не задано значение (нет временного ряда): %s ", + throw new RuntimeException(format("Переменной в правиле не задано значение (нет временного ряда): %s ", dbRule.getFirstAntecedent().name())); } if (!variableValues.containsKey(dbRule.getSecondAntecedent().name())) { - throw new RuntimeException(String.format("Переменной в правиле не задано значение (нет временного ряда): %s ", + throw new RuntimeException(format("Переменной в правиле не задано значение (нет временного ряда): %s ", dbRule.getSecondAntecedent().name())); } } } - private String getConsequent(Engine engine, Map variableValues) { + private Map.Entry getConsequent(Engine engine, Map variableValues) { OutputVariable outputVariable = engine.getOutputVariable(OUTPUT_VARIABLE_NAME); for (Map.Entry variableValue : variableValues.entrySet()) { InputVariable inputVariable = engine.getInputVariable(variableValue.getKey()); @@ -135,10 +154,10 @@ public class FuzzyInferenceService { } engine.process(); if (outputVariable != null) { - outputVariable.defuzzify(); + LOG.info("Output: {}", outputVariable.getValue()); } return (outputVariable == null || Double.isNaN(outputVariable.getValue())) - ? NO_RESULT - : outputVariable.highestMembership(outputVariable.getValue()).getSecond().getName(); + ? Map.entry(NO_RESULT, 0.0) + : Map.entry(outputVariable.highestMembershipTerm(outputVariable.getValue()).getName(), outputVariable.getValue()); } } diff --git a/src/main/resources/templates/assessments.html b/src/main/resources/templates/assessments.html index 516628a..a303e2d 100644 --- a/src/main/resources/templates/assessments.html +++ b/src/main/resources/templates/assessments.html @@ -42,6 +42,7 @@ th:text="${assessment.firstAntecedent.description}">' и тенденции '' показателя ''; +
diff --git a/src/test/java/ru/ulstu/FuzzyInferenceTest.java b/src/test/java/ru/ulstu/FuzzyInferenceTest.java deleted file mode 100644 index 99d69ef..0000000 --- a/src/test/java/ru/ulstu/FuzzyInferenceTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.ulstu; - -import org.junit.Assert; -import org.junit.Test; -import ru.ulstu.extractor.rule.service.FuzzyInferenceService; - -public class FuzzyInferenceTest { - - private final FuzzyInferenceService fuzzyInferenceService = new FuzzyInferenceService(); - - @Test - public void test() { - Assert.assertNotNull(fuzzyInferenceService); - } -}