From 5b080f41c25146c67c4c2368af7da1d25db58d58 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Tue, 25 Oct 2022 14:48:05 +0400 Subject: [PATCH] #74 -- add new library, create middle service --- .../rule/service/FuzzyInferenceService.java | 187 +++++++----------- 1 file changed, 68 insertions(+), 119 deletions(-) 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 862166c..4119729 100644 --- a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java +++ b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java @@ -1,27 +1,25 @@ package ru.ulstu.extractor.rule.service; -import net.sourceforge.jFuzzyLogic.defuzzifier.DefuzzifierCenterOfGravity; -import net.sourceforge.jFuzzyLogic.membership.MembershipFunctionTriangular; -import net.sourceforge.jFuzzyLogic.rule.FuzzyRule; -import net.sourceforge.jFuzzyLogic.rule.FuzzyRuleExpression; -import net.sourceforge.jFuzzyLogic.rule.FuzzyRuleSet; -import net.sourceforge.jFuzzyLogic.rule.FuzzyRuleTerm; -import net.sourceforge.jFuzzyLogic.rule.LinguisticTerm; -import net.sourceforge.jFuzzyLogic.rule.Variable; -import net.sourceforge.jFuzzyLogic.ruleConnection.RuleConnectionMethodAndMin; -import net.sourceforge.jFuzzyLogic.ruleImplication.RuleImplicationMethodMin; +import com.fuzzylite.Engine; +import com.fuzzylite.activation.Highest; +import com.fuzzylite.norm.t.AlgebraicProduct; +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.springframework.stereotype.Service; import ru.ulstu.extractor.rule.model.AntecedentValue; -import ru.ulstu.extractor.rule.model.Rule; +import ru.ulstu.extractor.rule.model.DbRule; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class FuzzyInferenceService { + private final static String RULE_TEMPLATE = "if %s is %s AND %s is %s then state is %s"; private final RuleService ruleService; private final AntecedentValueService antecedentValueService; @@ -31,118 +29,69 @@ public class FuzzyInferenceService { this.antecedentValueService = antecedentValueService; } - private List getFuzzyRulesFromDb() { - List fuzzyRules = new ArrayList<>(); - //List variables = getFuzzyVariables(); - for (Rule dbRule : ruleService.getList()) { - FuzzyRule fuzzyRule = new FuzzyRule(String.format("Fuzzy rule %s", dbRule.getId())); - // fuzzyRule.setAntecedents(expression); - // fuzzyRule.setConsequents(new LinkedList<>(Collections.singleton(new FuzzyRuleTerm(dbRule.getConsequent(), false)))); - fuzzyRules.add(fuzzyRule); - } - return fuzzyRules; + public List getRulesFromDb() { + List dbDbRules = ruleService.getList(); + return dbDbRules.stream().map(this::getFuzzyRule).collect(Collectors.toList()); } - private List getFuzzyVariablesWithoutMembership() { - List variables = new ArrayList<>(); - List antecedentValues = antecedentValueService.getList(); - for (AntecedentValue antecedentValue : antecedentValues) { - variables.add(new Variable(antecedentValue.getAntecedentValue())); - } - return variables; + private String getFuzzyRule(DbRule dbRule) { + return String.format(RULE_TEMPLATE, + dbRule.getFirstAntecedent().name(), + dbRule.getFirstAntecedentValue().getAntecedentValue(), + dbRule.getSecondAntecedent().name(), + dbRule.getSecondAntecedentValue().getAntecedentValue(), + dbRule.getConsequent()); } -// private FuzzyRuleExpression getFuzzyRulesAntecedents(TimeSeriesType timeSeriesType1, TimeSeriesType timeSeriesType2) { -// return new FuzzyRuleExpression(getFuzzyRuleTerm(), getFuzzyRuleTerm(), new RuleConnectionMethodAndMin()); -// } - - private FuzzyRuleExpression getFuzzyRuleExpression(FuzzyRuleTerm term1, FuzzyRuleTerm term2) { - return new FuzzyRuleExpression(term1, term2, new RuleConnectionMethodAndMin()); + private RuleBlock getRuleBlock(Engine engine, Map variableValues, List antecedentValues) { + variableValues.forEach((key, value) -> { + InputVariable input = new InputVariable(); + input.setName(key); + input.setDescription(""); + input.setEnabled(true); + input.setRange(0.000, 1.000); + input.setLockValueInRange(false); + for (int i = 0; i < antecedentValues.size(); i++) { + input.addTerm(new Triangle(antecedentValues.get(i).getAntecedentValue(), i, i + 2)); + } + engine.addInputVariable(input); + }); + + + RuleBlock mamdani = new RuleBlock(); + mamdani.setName("mamdani"); + mamdani.setDescription(""); + mamdani.setEnabled(true); + mamdani.setConjunction(null); + mamdani.setDisjunction(null); + mamdani.setImplication(new AlgebraicProduct()); + mamdani.setActivation(new Highest()); + getRulesFromDb().forEach(r -> mamdani.addRule(Rule.parse(r, engine))); + return mamdani; } - private FuzzyRuleTerm getFuzzyRuleTerm(Variable variable, String term) { - return new FuzzyRuleTerm(variable, term, false); + private Engine getFuzzyEngine() { + Engine engine = new Engine(); + engine.setName("Git rules"); + engine.setDescription(""); + return engine; } + public String run() { + Engine engine = getFuzzyEngine(); + List antecedentValues = antecedentValueService.getList(); + Map variableValues = new HashMap<>(); + engine.addRuleBlock(getRuleBlock(engine, variableValues, antecedentValues)); + return getConsequent(engine, variableValues); + } - public void run() { - FuzzyRule fuzzyRule1 = new FuzzyRule("rule 1"); - FuzzyRule fuzzyRule2 = new FuzzyRule("rule 2"); - FuzzyRule fuzzyRule3 = new FuzzyRule("rule 3"); - - Variable weather = new Variable("Погода"); - weather.getLinguisticTerms().put("солнечно", - new LinguisticTerm("солнечно", new MembershipFunctionTriangular(0, 20, 30))); - weather.getLinguisticTerms().put("мороз", - new LinguisticTerm("мороз", new MembershipFunctionTriangular(-50, -10, 10))); - weather.setDefuzzifier(new DefuzzifierCenterOfGravity(weather)); - - - Variable suit = new Variable("Одежда"); - suit.getLinguisticTerms().put("легко одет", - new LinguisticTerm("легко одет", new MembershipFunctionTriangular(0, 5, 10))); - suit.getLinguisticTerms().put("тепло одет", - new LinguisticTerm("тепло одет", new MembershipFunctionTriangular(5, 10, 20))); - suit.setDefuzzifier(new DefuzzifierCenterOfGravity(suit)); - - Variable feel = new Variable("Ощущение"); - feel.getLinguisticTerms().put("Холодно", - new LinguisticTerm("Холодно", new MembershipFunctionTriangular(0, 5, 10))); - feel.getLinguisticTerms().put("Жарко", - new LinguisticTerm("Жарко", new MembershipFunctionTriangular(5, 10, 20))); - feel.setDefuzzifier(new DefuzzifierCenterOfGravity(feel)); - - FuzzyRuleTerm weatherTerm1 = new FuzzyRuleTerm(weather, "солнечно", false); - FuzzyRuleTerm weatherTerm2 = new FuzzyRuleTerm(weather, "мороз", false); - - FuzzyRuleTerm suitTerm1 = new FuzzyRuleTerm(suit, "легко одет", false); - FuzzyRuleTerm suitTerm2 = new FuzzyRuleTerm(suit, "тепло одет", false); - - FuzzyRuleTerm feelCold = new FuzzyRuleTerm(feel, "Холодно", false); - FuzzyRuleTerm feelWarm = new FuzzyRuleTerm(feel, "Жарко", false); - - FuzzyRuleExpression expression1 = new FuzzyRuleExpression(weatherTerm1, suitTerm2, new RuleConnectionMethodAndMin()); - fuzzyRule1.setAntecedents(expression1); - fuzzyRule1.setConsequents(new LinkedList<>(Collections.singleton(feelWarm))); - - FuzzyRuleExpression expression2 = new FuzzyRuleExpression(weatherTerm2, suitTerm1, new RuleConnectionMethodAndMin()); - fuzzyRule2.setAntecedents(expression2); - fuzzyRule2.setConsequents(new LinkedList<>(Collections.singleton(feelCold))); - - FuzzyRuleExpression expression3 = new FuzzyRuleExpression(weatherTerm1, suitTerm1, new RuleConnectionMethodAndMin()); - fuzzyRule3.setAntecedents(expression3); - fuzzyRule3.setConsequents(new LinkedList<>(Collections.singleton(feelCold))); - - fuzzyRule1.evaluate(new RuleImplicationMethodMin()); - fuzzyRule2.evaluate(new RuleImplicationMethodMin()); - //fuzzyRule3.evaluate(new RuleImplicationMethodMin()); - - FuzzyRuleSet set = new FuzzyRuleSet(); - set.add(fuzzyRule1); - set.add(fuzzyRule2); - set.add(fuzzyRule3); - set.evaluate(); - - set.setVariable("Погода", 25); - set.setVariable("Одежда", 7); - // Evaluate fuzzy set - set.evaluate(); - - // Show output variable's chart - //set.getVariable("Ощущение").chartDefuzzifier(true); - System.out.println(set.getVariable("Ощущение").getLatestDefuzzifiedValue()); - System.out.println(set); - System.out.println(set.getVariable("Ощущение")); - System.out.println( - feel.getLinguisticTerms() - .entrySet() - .stream() - .max(Comparator.comparing(e -> e.getValue() - .getMembershipFunction() - .membership(set.getVariable("Ощущение").getLatestDefuzzifiedValue()))) - .get() - .getValue().getTermName() - ); - set.getVariable("Ощущение").chartDefuzzifier(true); + private String getConsequent(Engine engine, Map variableValues) { + OutputVariable outputVariable = engine.getOutputVariable("state"); + for (Map.Entry variableValue : variableValues.entrySet()) { + InputVariable inputVariable = engine.getInputVariable(variableValue.getKey()); + inputVariable.setValue(variableValue.getValue()); + } + engine.process(); + return outputVariable.highestMembership(outputVariable.getValue()).getSecond().getName(); } }