From b28a1931e9902b6031892cee26265ef6a4570b00 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Wed, 6 Sep 2023 12:41:05 +0400 Subject: [PATCH] #1 -- Add fuzzy inference template service --- .../rule/service/FuzzyInferenceService.java | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/main/java/ru/ulstu/fc/rule/service/FuzzyInferenceService.java diff --git a/src/main/java/ru/ulstu/fc/rule/service/FuzzyInferenceService.java b/src/main/java/ru/ulstu/fc/rule/service/FuzzyInferenceService.java new file mode 100644 index 0000000..70a9746 --- /dev/null +++ b/src/main/java/ru/ulstu/fc/rule/service/FuzzyInferenceService.java @@ -0,0 +1,127 @@ +package ru.ulstu.fc.rule.service; + +import com.fuzzylite.Engine; +import com.fuzzylite.term.Activated; +import com.fuzzylite.variable.InputVariable; +import com.fuzzylite.variable.OutputVariable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.stream.Collectors; + +@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 + + " is %s"; + private final static String NO_RESULT = "Нет результата"; + +// private List mapRulesToString(List dbRules) { +// return dbRules.stream().map(this::getFuzzyRule).collect(Collectors.toList()); +// } + +// private String getFuzzyRule(DbRule dbRule) { +// return format(RULE_TEMPLATE, +// dbRule.getFirstAntecedent().name(), +// dbRule.getFirstAntecedentValue().getAntecedentValue(), +// dbRule.getSecondAntecedent().name(), +// dbRule.getSecondAntecedentValue().getAntecedentValue(), +// dbRule.getId()); +// } + +// private RuleBlock getRuleBlock(Engine engine, +// List dbRules, +// Map variableValues, +// List antecedentValues, +// List consequentValues) { +// variableValues.forEach((key, value) -> { +// InputVariable input = new InputVariable(); +// input.setName(key); +// input.setDescription(""); +// input.setEnabled(true); +// input.setRange(-1, 1); +// input.setLockValueInRange(false); +// input.addTerm(new Triangle("спад", -1, 0)); +// input.addTerm(new Triangle("стабильно", -0.1, 0.1)); +// input.addTerm(new Triangle("рост", 0, 1)); +// engine.addInputVariable(input); +// }); +// +// OutputVariable output = new OutputVariable(); +// output.setName(OUTPUT_VARIABLE_NAME); +// output.setDescription(""); +// output.setEnabled(true); +// output.setRange(0, consequentValues.size() + 0.1); +// output.setAggregation(new Maximum()); +// 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, i + 1)); +// } +// engine.addOutputVariable(output); +// +// RuleBlock mamdani = new RuleBlock(); +// mamdani.setName("mamdani"); +// mamdani.setDescription(""); +// mamdani.setEnabled(true); +// mamdani.setConjunction(new Minimum()); +// //mamdani.setDisjunction(null); +// mamdani.setImplication(new AlgebraicProduct()); +// mamdani.setActivation(new General()); +// mapRulesToString(dbRules).forEach(r -> { +// LOG.info(r); +// mamdani.addRule(Rule.parse(r, engine)); +// }); +// return mamdani; +// } + + private Engine getFuzzyEngine() { + Engine engine = new Engine(); + engine.setName("Fuzzy rules"); + engine.setDescription(""); + return engine; + } + +// public List getFuzzyInference(List dbRules, +// List antecedentValues, +// Map variableValues) { +// validateVariables(variableValues, dbRules); +// variableValues.entrySet().forEach(e -> System.out.println(e.getKey() + " " + e.getValue())); +// Engine engine = getFuzzyEngine(); +// List consequentValues = dbRules.stream().map(DbRule::getId).collect(Collectors.toList()); +// engine.addRuleBlock(getRuleBlock(engine, dbRules, variableValues, antecedentValues, consequentValues)); +// Map consequents = getConsequent(engine, variableValues); +// if (consequents.containsKey(NO_RESULT)) { +// return new ArrayList<>(); +// } +// List assessments = new ArrayList<>(); +// for (Map.Entry consequent : consequents.entrySet()) { +// for (DbRule dbRule : dbRules) { +// if (dbRule.getId().equals(Integer.valueOf(consequent.getKey()))) { +// assessments.add(new Assessment(dbRule, consequent.getValue())); +// } +// } +// } +// return assessments; +// } + + private Map getConsequent(Engine engine, Map variableValues) { + OutputVariable outputVariable = engine.getOutputVariable(OUTPUT_VARIABLE_NAME); + for (Map.Entry variableValue : variableValues.entrySet()) { + InputVariable inputVariable = engine.getInputVariable(variableValue.getKey()); + inputVariable.setValue(variableValue.getValue()); + } + engine.process(); + if (outputVariable != null) { + LOG.info("Output: {}", outputVariable.getValue()); + } + return Double.isNaN(outputVariable.getValue()) + ? Map.of(NO_RESULT, 0.0) + : outputVariable.fuzzyOutput().getTerms().stream().collect(Collectors.toMap(t -> t.getTerm().getName(), Activated::getDegree)); + } +}