diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java index fa9a4bf05..d3108c421 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java @@ -82,10 +82,6 @@ public static enum MatchFlag { public static final EnumSet ALL_OPTS = EnumSet.allOf(MatchFlag.class); } - public static enum MatchStrategy { - SUPREME_LEVEL, ULTRA_LEVEL, ADVANCED_LEVEL, NORMAL_LEVEL, ENTRY_LEVEL - } - public static class TrivialBindingSetHandler implements TransformBindingSetHandler { private Set consequent; @@ -169,7 +165,7 @@ public Set getConsequent() { return this.consequent; } - public Set consequentMatches(Set anAntecedent, MatchStrategy aMatchStrategy) { + public Set consequentMatches(Set anAntecedent, EnumSet aMatchConfig) { if (!this.consequent.isEmpty()) { Rule r = new Rule(anAntecedent, new SinkBindingSetHandler() { @@ -179,8 +175,7 @@ public CompletableFuture handle(BindingSet aBindingSet) { return null; } }); - Map> matches = getMatches(this, new HashSet<>(Arrays.asList(r)), false, - aMatchStrategy); + Map> matches = getMatches(this, new HashSet<>(Arrays.asList(r)), false, aMatchConfig); if (matches.containsKey(r)) return matches.get(r); @@ -188,10 +183,10 @@ public CompletableFuture handle(BindingSet aBindingSet) { return new HashSet<>(); } - public Set antecedentMatches(Set aConsequent, MatchStrategy aMatchStrategy) { + public Set antecedentMatches(Set aConsequent, EnumSet aMatchConfig) { if (!this.antecedent.isEmpty()) { Rule r = new Rule(new HashSet<>(), aConsequent); - Map> matches = getMatches(this, new HashSet<>(Arrays.asList(r)), true, aMatchStrategy); + Map> matches = getMatches(this, new HashSet<>(Arrays.asList(r)), true, aMatchConfig); if (matches.containsKey(r)) return matches.get(r); } @@ -382,9 +377,7 @@ public static Map> getMatchesPerTriplePerRule(Set * @return A set of matches that all contribute to some full matche. */ public static Map> getMatches(BaseRule aTargetRule, Set someCandidateRules, - boolean antecedentOfTarget, MatchStrategy aStrategy) { - - EnumSet config = fromStrategyToConfig(aStrategy, antecedentOfTarget); + boolean antecedentOfTarget, EnumSet config) { Set targetGP = antecedentOfTarget ? aTargetRule.getAntecedent() : aTargetRule.getConsequent(); @@ -417,8 +410,8 @@ public static Map> getMatches(BaseRule aTargetRule, Set value = triplePatternMatchesIter.next().getValue(); - LOG.trace("{}/{} ({}): biggest: {}, smaller: {}", 1, combiMatchesPerTriple.size(), value.size(), - biggestMatches.size(), smallerMatches.size()); + LOG.trace("{}/{} ({}): biggest: {}, smaller: {} ({})", 1, combiMatchesPerTriple.size(), value.size(), + biggestMatches.size(), smallerMatches.size(), config); biggestMatches.addAll(value); } @@ -545,39 +538,6 @@ private static boolean isSubCombiMatch(CombiMatch aSmallerMatch, List fromStrategyToConfig(MatchStrategy aStrategy, boolean antecedentOfTarget) { - EnumSet config; - switch (aStrategy) { - case ENTRY_LEVEL: - config = EnumSet.of(MatchFlag.FULLY_COVERED, MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST, - MatchFlag.SINGLE_RULE); - break; - case NORMAL_LEVEL: - config = EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST); - - // disable fully covered when matching consequents. - if (antecedentOfTarget) - config.add(MatchFlag.FULLY_COVERED); - break; - case ADVANCED_LEVEL: - config = EnumSet.of(MatchFlag.ONLY_BIGGEST); - - // disable fully covered when matching consequents. - if (antecedentOfTarget) - config.add(MatchFlag.FULLY_COVERED); - break; - case ULTRA_LEVEL: - config = EnumSet.of(MatchFlag.ONLY_BIGGEST); - break; - case SUPREME_LEVEL: - config = EnumSet.noneOf(MatchFlag.class); - break; - default: - config = EnumSet.noneOf(MatchFlag.class); - } - return config; - } - private static void printCombiMatchesPerTriple(Map> combiMatchesPerTriple) { StringBuilder sb = new StringBuilder(); diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/ReasonerPlan.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/ReasonerPlan.java index 537234c17..c8b79ab69 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/ReasonerPlan.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/ReasonerPlan.java @@ -2,6 +2,7 @@ import java.util.ArrayDeque; import java.util.Deque; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -11,7 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.api.Binding; import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.reasoner.api.TriplePattern; @@ -38,7 +39,7 @@ public class ReasonerPlan { private final ProactiveRule start; private final Map ruleToRuleNode; private boolean done; - private MatchStrategy strategy = MatchStrategy.ULTRA_LEVEL; + private EnumSet matchConfig = EnumSet.noneOf(MatchFlag.class); private boolean useTaskBoard = true; public ReasonerPlan(RuleStore aStore, ProactiveRule aStartRule) { @@ -48,11 +49,11 @@ public ReasonerPlan(RuleStore aStore, ProactiveRule aStartRule) { createOrGetReasonerNode(this.start, null); } - public ReasonerPlan(RuleStore aStore, ProactiveRule aStartRule, MatchStrategy aStrategy) { + public ReasonerPlan(RuleStore aStore, ProactiveRule aStartRule, EnumSet aConfig) { this.store = aStore; this.start = aStartRule; this.ruleToRuleNode = new HashMap<>(); - this.strategy = aStrategy; + this.matchConfig = aConfig; createOrGetReasonerNode(this.start, null); } @@ -231,7 +232,7 @@ private RuleNode createOrGetReasonerNode(BaseRule aRule, BaseRule aParent) { // for now we only are interested in antecedent neighbors. // TODO for looping we DO want to consider consequent neighbors as well. - this.store.getAntecedentNeighbors(aRule, this.strategy).forEach((rule, matches) -> { + this.store.getAntecedentNeighbors(aRule, this.matchConfig).forEach((rule, matches) -> { if (!(rule instanceof ProactiveRule)) { assert reasonerNode instanceof AntSide; var newNode = createOrGetReasonerNode(rule, aRule); @@ -247,7 +248,7 @@ private RuleNode createOrGetReasonerNode(BaseRule aRule, BaseRule aParent) { }); } else { // interested in both consequent and antecedent neighbors - this.store.getConsequentNeighbors(aRule, this.strategy).forEach((rule, matches) -> { + this.store.getConsequentNeighbors(aRule, this.matchConfig).forEach((rule, matches) -> { if (!(rule instanceof ProactiveRule)) { assert reasonerNode instanceof ConsSide; var newNode = createOrGetReasonerNode(rule, aRule); @@ -266,13 +267,13 @@ private RuleNode createOrGetReasonerNode(BaseRule aRule, BaseRule aParent) { // determine whether our parent matches us partially boolean ourAntecedentFullyMatchesParentConsequent = false; - if (aParent != null && this.store.getAntecedentNeighbors(aRule, this.strategy).containsKey(aParent)) { + if (aParent != null && this.store.getAntecedentNeighbors(aRule, this.matchConfig).containsKey(aParent)) { ourAntecedentFullyMatchesParentConsequent = antecedentFullyMatchesConsequent(aRule, aParent, - this.store.getAntecedentNeighbors(aRule, this.strategy).get(aParent), this.strategy); + this.store.getAntecedentNeighbors(aRule, this.matchConfig).get(aParent)); } if (!ourAntecedentFullyMatchesParentConsequent) { - this.store.getAntecedentNeighbors(aRule, this.strategy).forEach((rule, matches) -> { + this.store.getAntecedentNeighbors(aRule, this.matchConfig).forEach((rule, matches) -> { if (!(rule instanceof ProactiveRule)) { assert reasonerNode instanceof AntSide; var newNode = createOrGetReasonerNode(rule, aRule); @@ -317,7 +318,7 @@ private void scheduleOrDoTask(RuleNode current, TaskBoard taskBoard) { * @return */ private boolean antecedentFullyMatchesConsequent(BaseRule antecedentRule, BaseRule consequentRule, - Set someMatches, MatchStrategy aMatchStrategy) { + Set someMatches) { var antecedent = antecedentRule.getAntecedent(); var consequent = consequentRule.getConsequent(); @@ -348,8 +349,8 @@ private boolean antecedentFullyMatchesConsequent(BaseRule antecedentRule, BaseRu return false; } - public MatchStrategy getMatchStrategy() { - return this.strategy; + public EnumSet getMatchConfig() { + return this.matchConfig; } public RuleStore getStore() { diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/MatchNode.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/MatchNode.java index 7166ac051..bcf8e317f 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/MatchNode.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/MatchNode.java @@ -1,11 +1,12 @@ package eu.knowledge.engine.reasoner.rulestore; +import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import java.util.Set; import eu.knowledge.engine.reasoner.BaseRule; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.Match; /** @@ -31,46 +32,19 @@ public class MatchNode { * All other rules in the {@link MatchNode#store} whose consequents match this * rule's antecedent according to the {@link MatchStrategy#NORMAL_LEVEL} */ - private Map> antecedentNeighborsNormal; - - /** - * All other rules in the {@link MatchNode#store} whose consequents match this - * rule's antecedent according to the {@link MatchStrategy#ADVANCED_LEVEL} - */ - private Map> antecedentNeighborsAdvanced; - - /** - * All other rules in the {@link MatchNode#store} whose consequents match this - * rule's antecedent according to the {@link MatchStrategy#ULTRA_LEVEL} - */ - private Map> antecedentNeighborsUltra; + private Map> antecedentNeighbors; /** * All other rules in the {@link MatchNode#store} whose antecedents match this * rule's consequent according to the {@link MatchStrategy#NORMAL_LEVEL} */ - private Map> consequentNeighborsNormal; - - /** - * All other rules in the {@link MatchNode#store} whose antecedents match this - * rule's consequent according to the {@link MatchStrategy#ADVANCED_LEVEL} - */ - private Map> consequentNeighborsAdvanced; - - /** - * All other rules in the {@link MatchNode#store} whose antecedents match this - * rule's consequent according to the {@link MatchStrategy#ULTRA_LEVEL} - */ - private Map> consequentNeighborsUltra; + private Map> consequentNeighbors; public MatchNode(BaseRule aRule) { this.rule = aRule; - this.antecedentNeighborsNormal = new HashMap<>(); - this.antecedentNeighborsAdvanced = new HashMap<>(); - this.antecedentNeighborsUltra = new HashMap<>(); - this.consequentNeighborsNormal = new HashMap<>(); - this.consequentNeighborsAdvanced = new HashMap<>(); - this.consequentNeighborsUltra = new HashMap<>(); + this.antecedentNeighbors = new HashMap<>(); + this.consequentNeighbors = new HashMap<>(); + } public BaseRule getRule() { @@ -78,43 +52,15 @@ public BaseRule getRule() { } public void setConsequentNeighbor(BaseRule aRule, Set someMatches) { - this.setConsequentNeighbor(aRule, someMatches, MatchStrategy.ULTRA_LEVEL); - } - - public void setAntecedentNeighbor(BaseRule aRule, Set someMatches) { - this.setAntecedentNeighbor(aRule, someMatches, MatchStrategy.ULTRA_LEVEL); - } - - public void setConsequentNeighbor(BaseRule aRule, Set someMatches, MatchStrategy aStrategy) { - Map> neighbors; - if (aStrategy.equals(MatchStrategy.NORMAL_LEVEL) || aStrategy.equals(MatchStrategy.ENTRY_LEVEL)) { - neighbors = this.consequentNeighborsNormal; - } else if (aStrategy.equals(MatchStrategy.ADVANCED_LEVEL)) { - neighbors = this.consequentNeighborsAdvanced; - } else if (aStrategy.equals(MatchStrategy.ULTRA_LEVEL)) { - neighbors = this.consequentNeighborsUltra; - } else { - assert false; - neighbors = new HashMap<>(); - } + Map> neighbors = this.consequentNeighbors; if (!neighbors.containsKey(aRule)) { neighbors.put(aRule, someMatches); } } - public void setAntecedentNeighbor(BaseRule aRule, Set someMatches, MatchStrategy aStrategy) { - Map> neighbors; - if (aStrategy.equals(MatchStrategy.NORMAL_LEVEL) || aStrategy.equals(MatchStrategy.ENTRY_LEVEL)) { - neighbors = this.antecedentNeighborsNormal; - } else if (aStrategy.equals(MatchStrategy.ADVANCED_LEVEL)) { - neighbors = this.antecedentNeighborsAdvanced; - } else if (aStrategy.equals(MatchStrategy.ULTRA_LEVEL)) { - neighbors = this.antecedentNeighborsUltra; - } else { - assert false; - neighbors = new HashMap<>(); - } + public void setAntecedentNeighbor(BaseRule aRule, Set someMatches) { + Map> neighbors = this.antecedentNeighbors; if (!neighbors.containsKey(aRule)) { neighbors.put(aRule, someMatches); @@ -122,37 +68,11 @@ public void setAntecedentNeighbor(BaseRule aRule, Set someMatches, MatchS } public Map> getConsequentNeighbors() { - return this.getConsequentNeighbors(MatchStrategy.ULTRA_LEVEL); + return this.consequentNeighbors; } public Map> getAntecedentNeighbors() { - return this.getAntecedentNeighbors(MatchStrategy.ULTRA_LEVEL); - } - - public Map> getConsequentNeighbors(MatchStrategy aStrategy) { - if (aStrategy.equals(MatchStrategy.NORMAL_LEVEL)) { - return this.consequentNeighborsNormal; - } else if (aStrategy.equals(MatchStrategy.ADVANCED_LEVEL)) { - return this.consequentNeighborsAdvanced; - } else if (aStrategy.equals(MatchStrategy.ULTRA_LEVEL)) { - return this.consequentNeighborsUltra; - } else { - assert false; - return null; - } - } - - public Map> getAntecedentNeighbors(MatchStrategy aStrategy) { - if (aStrategy.equals(MatchStrategy.NORMAL_LEVEL)) { - return this.antecedentNeighborsNormal; - } else if (aStrategy.equals(MatchStrategy.ADVANCED_LEVEL)) { - return this.antecedentNeighborsAdvanced; - } else if (aStrategy.equals(MatchStrategy.ULTRA_LEVEL)) { - return this.antecedentNeighborsUltra; - } else { - assert false; - return null; - } + return this.antecedentNeighbors; } /** @@ -163,12 +83,8 @@ public RuleStore getStore() { } public void reset() { - this.antecedentNeighborsNormal.clear(); - this.antecedentNeighborsAdvanced.clear(); - this.antecedentNeighborsUltra.clear(); - this.consequentNeighborsNormal.clear(); - this.consequentNeighborsAdvanced.clear(); - this.consequentNeighborsUltra.clear(); + this.antecedentNeighbors.clear(); + this.consequentNeighbors.clear(); } } diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java index f0fc54426..319943139 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java @@ -6,6 +6,7 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -16,7 +17,7 @@ import org.slf4j.LoggerFactory; import eu.knowledge.engine.reasoner.BaseRule; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.Match; import eu.knowledge.engine.reasoner.ProactiveRule; import eu.knowledge.engine.reasoner.ReasonerPlan; @@ -75,7 +76,7 @@ public Set getRules() { * @see #getAntecedentNeighbors(BaseRule, MatchStrategy) */ public Map> getAntecedentNeighbors(BaseRule aRule) { - return this.getAntecedentNeighbors(aRule, MatchStrategy.NORMAL_LEVEL); + return this.getAntecedentNeighbors(aRule, EnumSet.noneOf(MatchFlag.class)); } /** @@ -86,16 +87,16 @@ public Map> getAntecedentNeighbors(BaseRule aRule) { * @return A mapping from a neighbor rulenode and the way its consequent matches * this rule's antecedent. */ - public Map> getAntecedentNeighbors(BaseRule aRule, MatchStrategy aStrategy) { + public Map> getAntecedentNeighbors(BaseRule aRule, EnumSet aConfig) { MatchNode aRuleNode = this.ruleToRuleNode.get(aRule); assert aRuleNode != null; - Map> newMapping = BaseRule.getMatches(aRule, this.getRules(), true, aStrategy); + Map> newMapping = BaseRule.getMatches(aRule, this.getRules(), true, aConfig); for (Map.Entry> entry : newMapping.entrySet()) { - aRuleNode.setAntecedentNeighbor(entry.getKey(), Match.invertAll(entry.getValue()), aStrategy); - this.ruleToRuleNode.get(entry.getKey()).setConsequentNeighbor(aRule, entry.getValue(), aStrategy); + aRuleNode.setAntecedentNeighbor(entry.getKey(), Match.invertAll(entry.getValue())); + this.ruleToRuleNode.get(entry.getKey()).setConsequentNeighbor(aRule, entry.getValue()); } return newMapping; @@ -115,7 +116,7 @@ public void addToNewMapping(Map> newMapping, Map.Entry> getConsequentNeighbors(BaseRule aRule) { - return this.getConsequentNeighbors(aRule, MatchStrategy.NORMAL_LEVEL); + return this.getConsequentNeighbors(aRule, EnumSet.noneOf(MatchFlag.class)); } @@ -129,16 +130,16 @@ public Map> getConsequentNeighbors(BaseRule aRule) { * @return A mapping from a neighbor rulenode and the way its antecedent matches * this rule's consequent. */ - public Map> getConsequentNeighbors(BaseRule aRule, MatchStrategy aStrategy) { + public Map> getConsequentNeighbors(BaseRule aRule, EnumSet aConfig) { MatchNode aRuleNode = this.ruleToRuleNode.get(aRule); assert aRuleNode != null; - Map> newMapping = BaseRule.getMatches(aRule, this.getRules(), false, aStrategy); + Map> newMapping = BaseRule.getMatches(aRule, this.getRules(), false, aConfig); for (Map.Entry> entry : newMapping.entrySet()) { - aRuleNode.setConsequentNeighbor(entry.getKey(), Match.invertAll(entry.getValue()), aStrategy); - this.ruleToRuleNode.get(entry.getKey()).setAntecedentNeighbor(aRule, entry.getValue(), aStrategy); + aRuleNode.setConsequentNeighbor(entry.getKey(), Match.invertAll(entry.getValue())); + this.ruleToRuleNode.get(entry.getKey()).setAntecedentNeighbor(aRule, entry.getValue()); } return newMapping; @@ -200,9 +201,8 @@ public void printGraphVizCode(ReasonerPlan aPlan) { ruleToName.put(r.getRule(), currentName); } - - Map> antecedentNeighbors = this.getAntecedentNeighbors(r.getRule(), - aPlan != null ? aPlan.getMatchStrategy() : MatchStrategy.NORMAL_LEVEL); + + Map> antecedentNeighbors = r.getAntecedentNeighbors(); Set anteNeigh = antecedentNeighbors.keySet(); String neighName; for (BaseRule neighR : anteNeigh) { diff --git a/reasoner/src/test/java/eu/knowledge/engine/reasoner/BindingTest.java b/reasoner/src/test/java/eu/knowledge/engine/reasoner/BindingTest.java index 6373452c2..444930684 100644 --- a/reasoner/src/test/java/eu/knowledge/engine/reasoner/BindingTest.java +++ b/reasoner/src/test/java/eu/knowledge/engine/reasoner/BindingTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; +import java.util.EnumSet; import java.util.HashSet; import java.util.Set; @@ -10,7 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.api.Binding; import eu.knowledge.engine.reasoner.api.TriplePattern; @@ -60,7 +61,7 @@ public void testFruitfulVsActualMatches() { BaseRule r = new BaseRule("test", toTriplePattern(gp2), new HashSet<>()); - Set matches = r.antecedentMatches(toTriplePattern(gp1), MatchStrategy.ULTRA_LEVEL); + Set matches = r.antecedentMatches(toTriplePattern(gp1), EnumSet.of(MatchFlag.ONLY_BIGGEST)); LOG.info("matches size: {}", matches.size()); diff --git a/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/MatchTest.java b/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/MatchTest.java index df6c293d0..fd5179847 100644 --- a/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/MatchTest.java +++ b/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/MatchTest.java @@ -7,6 +7,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -20,7 +21,7 @@ import org.junit.jupiter.api.TestInstance.Lifecycle; import eu.knowledge.engine.reasoner.BaseRule; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.Match; import eu.knowledge.engine.reasoner.ProactiveRule; import eu.knowledge.engine.reasoner.Rule; @@ -54,7 +55,7 @@ public void testGPMatcher() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -69,7 +70,7 @@ public void testGPMatcher2() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -86,7 +87,7 @@ public void testGPMatcher3() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -100,7 +101,7 @@ public void testGPMatcher4() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); // there should be a match, but its mapping should be empty nothing needs to // happen to translate one to the other. @@ -117,7 +118,7 @@ public void testGPMatcher5() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); // there should be a match and its mapping should be empty because nothing needs // to happen to translate one to the other. @@ -137,7 +138,7 @@ public void testGPMatcher6() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -164,7 +165,7 @@ public void testGPMatcher7() { BaseRule r = new ProactiveRule(obj, new HashSet<>()); - Set findMatchesWithConsequent = r.antecedentMatches(obj, MatchStrategy.NORMAL_LEVEL); + Set findMatchesWithConsequent = r.antecedentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST, MatchFlag.FULLY_COVERED)); System.out.println("Size: " + findMatchesWithConsequent.size()); for (Match m : findMatchesWithConsequent) { @@ -186,7 +187,7 @@ public void testGPMatcher8() { Rule r = new Rule(new HashSet<>(), tp2); - Set findMatchesWithConsequent = r.consequentMatches(tp1, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(tp1, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -204,7 +205,7 @@ public void testGPMatcher9() { Rule r = new Rule(new HashSet<>(), tp2); - Set findMatchesWithConsequent = r.consequentMatches(tp1, MatchStrategy.ADVANCED_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(tp1, EnumSet.of(MatchFlag.ONLY_BIGGEST)); System.out.println(findMatchesWithConsequent); } @@ -268,8 +269,10 @@ public void testGPMatcher10OrderingWithinGraphPatternsShouldNotMatter() { Rule r = new Rule(new HashSet<>(), obj); Rule r2 = new Rule(new HashSet<>(), obj2); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.NORMAL_LEVEL); - Set findMatchesWithConsequent2 = r2.consequentMatches(obj2, MatchStrategy.NORMAL_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST)); + Set findMatchesWithConsequent2 = r2.consequentMatches(obj2, + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST)); System.out.println("Size 1: " + findMatchesWithConsequent.size()); System.out.println(findMatchesWithConsequent); @@ -301,8 +304,10 @@ public void testGPMatcher11VariableNamesMatter() { Rule r = new Rule(new HashSet<>(), obj); Rule r2 = new Rule(new HashSet<>(), obj2); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.NORMAL_LEVEL); - Set findMatchesWithConsequent2 = r2.consequentMatches(obj2, MatchStrategy.NORMAL_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST)); + Set findMatchesWithConsequent2 = r2.consequentMatches(obj2, + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST)); System.out.println("Size 1: " + findMatchesWithConsequent.size()); System.out.println(findMatchesWithConsequent); @@ -335,7 +340,7 @@ public void testGPMatcher12() { }); Set findMatchesWithAntecedent = r.antecedentMatches( - new HashSet<>(Arrays.asList(/* t1, */ t5, t9, t8, t7, t6, t4, t3)), MatchStrategy.ADVANCED_LEVEL); + new HashSet<>(Arrays.asList(/* t1, */ t5, t9, t8, t7, t6, t4, t3)), EnumSet.of(MatchFlag.ONLY_BIGGEST, MatchFlag.FULLY_COVERED)); System.out.println("Size: " + findMatchesWithAntecedent.size()); // System.out.println(findMatchesWithConsequent); @@ -423,7 +428,7 @@ public void testGPMatcherCardinalityTest() { Rule r = new Rule(new HashSet<>(), obj); Set findMatchesWithConsequent = r.consequentMatches(new HashSet<>(Arrays.asList(graphPattern)), - MatchStrategy.SUPREME_LEVEL); + EnumSet.noneOf(MatchFlag.class)); System.out.println("graph pattern size " + gpSize + " gives matches size " + findMatchesWithConsequent.size() + "-" + getNumberOfMatches(gpSize)); @@ -473,7 +478,7 @@ public void testBugTranslate() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.noneOf(MatchFlag.class)); BindingSet bs = Util.toBindingSet("s=,p=

,o="); @@ -496,7 +501,7 @@ public void testOtherBurgTranslate() { Rule r = new Rule(new HashSet<>(), rhs); - Set findMatchesWithConsequent = r.consequentMatches(obj, MatchStrategy.ULTRA_LEVEL); + Set findMatchesWithConsequent = r.consequentMatches(obj, EnumSet.noneOf(MatchFlag.class)); BindingSet bs = Util.toBindingSet("p=,q=\"22.0\"^^"); @@ -589,7 +594,7 @@ public CompletableFuture handle(BindingSet aBindingSet) { System.out.println("NrOfMatches with " + obj.size() + " triple patterns: " + getNumberOfMatches(obj.size())); - Set findMatchesWithAntecedent = r.antecedentMatches(obj, MatchStrategy.ADVANCED_LEVEL); + Set findMatchesWithAntecedent = r.antecedentMatches(obj, EnumSet.of(MatchFlag.ONLY_BIGGEST, MatchFlag.FULLY_COVERED)); System.out.println("Size: " + findMatchesWithAntecedent.size()); @@ -661,7 +666,7 @@ public void testPloutosGPMatcher2() { System.out.println("NrOfMatches with " + obj.size() + " triple patterns: " + getNumberOfMatches(obj.size())); var findMatchesWithConsequent = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, - MatchStrategy.NORMAL_LEVEL); + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST, MatchFlag.FULLY_COVERED)); System.out.println("Size: " + findMatchesWithConsequent.size()); assertEquals(1, findMatchesWithConsequent.size()); @@ -682,7 +687,8 @@ public void testNewGPMatcher1() { BaseRule r2 = new Rule(new HashSet<>(), tp2); - var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, MatchStrategy.NORMAL_LEVEL); + var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, + EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST)); System.out.println(matches); @@ -702,7 +708,7 @@ public void testNewGPMatcherTransitivity() { BaseRule r2 = new Rule(new HashSet<>(), tp2); - var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, MatchStrategy.ULTRA_LEVEL); + var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, EnumSet.noneOf(MatchFlag.class)); System.out.println(matches); assertEquals(1, matches.size()); @@ -723,7 +729,7 @@ public void testNewGPMatcher2() { BaseRule r2 = new Rule(new HashSet<>(), tp2); - var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, MatchStrategy.ULTRA_LEVEL); + var matches = BaseRule.getMatches(r1, new HashSet<>(Arrays.asList(r2)), true, EnumSet.noneOf(MatchFlag.class)); System.out.println(matches); assertEquals(1, matches.size()); diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AnswerKnowledgeInteraction.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AnswerKnowledgeInteraction.java index 6282a3168..0992ae1de 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AnswerKnowledgeInteraction.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AnswerKnowledgeInteraction.java @@ -16,36 +16,33 @@ public final class AnswerKnowledgeInteraction extends KnowledgeInteraction { */ private final GraphPattern pattern; - /** - * Create an {@link AnswerKnowledgeInteraction}. - * - * @param act The {@link CommunicativeAct} of this - * {@link KnowledgeInteraction}. It can be read as the 'goal' or - * 'purpose' of the data exchange and whether it has side-effects - * or not. - * @param pattern The {@link GraphPattern} expresses the 'shape' of knowledge - * that this {@link KnowledgeInteraction} can provide. - */ public AnswerKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern) { - this(act, pattern, null, false, false); + this(act, pattern, null, false, false, null); } public AnswerKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern, String name) { - this(act, pattern, name, false, false); + this(act, pattern, name, false, false, null); } - public AnswerKnowledgeInteraction(CommunicativeAct anAct, GraphPattern aPattern, boolean anIsFullMatch) { - this(anAct, aPattern, null, false, anIsFullMatch); + public AnswerKnowledgeInteraction(CommunicativeAct anAct, GraphPattern aPattern, boolean anIncludeMetaKIs) { + this(anAct, aPattern, null, false, anIncludeMetaKIs, null); } public AnswerKnowledgeInteraction(CommunicativeAct anAct, GraphPattern aPattern, boolean anIsMeta, - boolean anIsFullMatch) { - this(anAct, aPattern, null, anIsMeta, anIsFullMatch); + boolean anIncludeMetaKIs) { + this(anAct, aPattern, null, anIsMeta, anIncludeMetaKIs, null); } - public AnswerKnowledgeInteraction(CommunicativeAct anAct, GraphPattern aPattern, String name, boolean anIsMeta, - boolean anIsFullMatch) { - super(anAct, name, anIsMeta, anIsFullMatch); + /** + * Create an {@link AnswerKnowledgeInteraction}. See + * {@link KnowledgeInteraction#KnowledgeInteraction(CommunicativeAct, String, boolean, boolean, MatchStrategy) + * + * @param aPattern The {@link GraphPattern} expresses the 'shape' of knowledge + * that this {@link KnowledgeInteraction} can provide. + */ + public AnswerKnowledgeInteraction(CommunicativeAct anAct, GraphPattern aPattern, String aName, boolean anIsMeta, + boolean anIncludeMetaKIs, MatchStrategy aMatchStrategy) { + super(anAct, aName, anIsMeta, anIncludeMetaKIs, aMatchStrategy); this.pattern = aPattern; } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskKnowledgeInteraction.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskKnowledgeInteraction.java index 1f680cdc6..8fc7e2f2a 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskKnowledgeInteraction.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskKnowledgeInteraction.java @@ -16,36 +16,33 @@ public final class AskKnowledgeInteraction extends KnowledgeInteraction { */ private final GraphPattern pattern; - /** - * Create a {@link AskKnowledgeInteraction}. - * - * @param act The {@link CommunicativeAct} of this - * {@link KnowledgeInteraction}. It can be read as the 'goal' or - * 'purpose' of the data exchange and whether it has side-effects - * or not. - * @param pattern The {@link GraphPattern} expresses the 'shape' of knowledge - * that this {@link KnowledgeInteraction} asks for. - */ public AskKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern) { - this(act, pattern, null, false, false); + this(act, pattern, null, false, false, null); } public AskKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern, String name) { - this(act, pattern, name, false, false); + this(act, pattern, name, false, false, null); } public AskKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern, boolean anIncludeMetaKIs) { - this(act, pattern, null, false, anIncludeMetaKIs); + this(act, pattern, null, false, anIncludeMetaKIs, null); } public AskKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern, boolean anisMeta, boolean anIncludeMetaKIs) { - this(act, pattern, null, anisMeta, anIncludeMetaKIs); + this(act, pattern, null, anisMeta, anIncludeMetaKIs, null); } + /** + * Create a {@link AskKnowledgeInteraction}. See + * {@link KnowledgeInteraction#KnowledgeInteraction(CommunicativeAct, String, boolean, boolean, MatchStrategy) + * + * @param pattern The {@link GraphPattern} expresses the 'shape' of knowledge + * that this {@link KnowledgeInteraction} asks for. + */ public AskKnowledgeInteraction(CommunicativeAct act, GraphPattern pattern, String name, boolean anisMeta, - boolean anIncludeMetaKIs) { - super(act, name, anisMeta, anIncludeMetaKIs); + boolean anIncludeMetaKIs, MatchStrategy aMatchStrategy) { + super(act, name, anisMeta, anIncludeMetaKIs, aMatchStrategy); this.pattern = pattern; } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/KnowledgeInteraction.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/KnowledgeInteraction.java index eb324c862..fb8b3ae0b 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/KnowledgeInteraction.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/KnowledgeInteraction.java @@ -1,6 +1,6 @@ package eu.knowledge.engine.smartconnector.api; -import org.apache.jena.ext.xerces.impl.xpath.regex.RegularExpression; +import com.fasterxml.jackson.core.format.MatchStrength; /** * A {@link KnowledgeInteraction} represents an agreement about the exchange of @@ -16,7 +16,7 @@ public abstract class KnowledgeInteraction { * the intent/purpose or goal of this interaction and whether it has * side-effects. */ - private final CommunicativeAct act; + private final CommunicativeAct anAct; /** * When executing this knowledge interaction, should the meta knowledge @@ -32,6 +32,17 @@ public abstract class KnowledgeInteraction { */ private final boolean isMeta; + /** + * Optionally configure the matching strategy (which has a large impact on the + * performance) to a different level than the one configured at the smart + * connector level. + * + * For example, this configuration option is used to set the matching process on + * all internal (meta) KIs to {@link MatchStrategy#ENTRY_LEVEL}, because we can + * make certain assumptions to increase the performance. + */ + private MatchStrategy matchStrategy = null; + protected final String name; /** @@ -42,33 +53,45 @@ public abstract class KnowledgeInteraction { * whether it has side-effects or not. */ public KnowledgeInteraction(CommunicativeAct act) { - this(act, null, false, false); + this(act, null, false, false, null); } - /** - * Create a {@link KnowledgeInteraction}. - * - * @param act The {@link CommunicativeAct} of this - * {@link KnowledgeInteraction}. It can be read as the 'goal' or - * 'purpose' of the data exchange and whether it has side-effects - * or not. - * @param isMeta Whether or not this knowledge interaction contains metadata - * about the knowledge base itself. - */ public KnowledgeInteraction(CommunicativeAct act, boolean isMeta) { - this(act, null, isMeta, false); + this(act, null, isMeta, false, null); } public KnowledgeInteraction(CommunicativeAct act, boolean isMeta, boolean anIncludeMetaKIs) { - this(act, null, isMeta, anIncludeMetaKIs); + this(act, null, isMeta, anIncludeMetaKIs, null); } - public KnowledgeInteraction(CommunicativeAct act, String name, boolean isMeta, boolean anIncludeMetaKIs) { + /** + * Create a {@link KnowledgeInteraction}. + * + * @param act The {@link CommunicativeAct} of this + * {@link KnowledgeInteraction}. It can be read as the + * 'goal' or 'purpose' of the data exchange and whether + * it has side-effects or not. + * @param name An optional name for the KI (that also influences and + * stabilize the URI). + * @param isMeta Whether or not this knowledge interaction contains + * metadata about the knowledge base itself. + * @param anIncludeMetaKIs When processing this knowledge interaction, do we + * need to include the meta KIs of the SCs within the + * network? This needs to be set to {@code true} if this + * KI relies on exchanging KE metadata. + * @param aMatchConfig Optionally configure the match strategy that will be + * used when executing this KI. If set to {@code null} + * the match strategy configured at the SC level will be + * used. + */ + public KnowledgeInteraction(CommunicativeAct act, String name, boolean isMeta, boolean anIncludeMetaKIs, + MatchStrategy aMatchConfig) { this.validateName(name); - this.act = act; + this.anAct = act; this.name = name; this.isMeta = isMeta; this.includeMetaKIs = anIncludeMetaKIs; + this.matchStrategy = aMatchConfig; } public String getName() { @@ -79,7 +102,7 @@ public String getName() { * @return The {@link CommunicativeAct} of this {@link KnowledgeInteraction}. */ public CommunicativeAct getAct() { - return this.act; + return this.anAct; } public boolean isMeta() { @@ -90,6 +113,10 @@ public boolean includeMetaKIs() { return this.includeMetaKIs; } + public MatchStrategy getMatchStrategy() { + return this.matchStrategy; + } + /** * Throws an exception if {@code name} does not conform to the requirements of * knowledge interaction names. diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/MatchStrategy.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/MatchStrategy.java new file mode 100644 index 000000000..7a3c65f2b --- /dev/null +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/MatchStrategy.java @@ -0,0 +1,49 @@ +package eu.knowledge.engine.smartconnector.api; + +import java.util.EnumSet; + +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; + +/** + * the match strategy determines how many matches will be found between graph + * patterns. This is a very costly operation (especially with bigger (10+) + * triples per graph pattern. For some use cases it suffices to use ENTRY_LEVEL + * matching which is much faster, while others require SUPREME_LEVEL, which is + * extremely slow and often throws out of memory exceptions. + */ +public enum MatchStrategy { + SUPREME_LEVEL, ULTRA_LEVEL, ADVANCED_LEVEL, NORMAL_LEVEL, ENTRY_LEVEL; + + public EnumSet toConfig(boolean antecedentOfTarget) { + EnumSet config; + switch (this) { + case ENTRY_LEVEL: + config = EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST, MatchFlag.SINGLE_RULE, + MatchFlag.FULLY_COVERED); + break; + case NORMAL_LEVEL: + config = EnumSet.of(MatchFlag.ONE_TO_ONE, MatchFlag.ONLY_BIGGEST); + + // disable fully covered when matching consequents. + if (antecedentOfTarget) + config.add(MatchFlag.FULLY_COVERED); + break; + case ADVANCED_LEVEL: + config = EnumSet.of(MatchFlag.ONLY_BIGGEST); + + // disable fully covered when matching consequents. + if (antecedentOfTarget) + config.add(MatchFlag.FULLY_COVERED); + break; + case ULTRA_LEVEL: + config = EnumSet.of(MatchFlag.ONLY_BIGGEST); + break; + case SUPREME_LEVEL: + config = EnumSet.noneOf(MatchFlag.class); + break; + default: + config = EnumSet.noneOf(MatchFlag.class); + } + return config; + } +} \ No newline at end of file diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostKnowledgeInteraction.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostKnowledgeInteraction.java index 98b8493e6..17625d06b 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostKnowledgeInteraction.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostKnowledgeInteraction.java @@ -22,43 +22,42 @@ public final class PostKnowledgeInteraction extends KnowledgeInteraction { */ private final GraphPattern result; - /** - * Create a {@link PostKnowledgeInteraction}. - * - * @param act The {@link CommunicativeAct} of this - * {@link KnowledgeInteraction}. It can be read as the 'goal' or - * 'purpose' of the data exchange and whether it has - * side-effects or not. - * @param argument The {@code argument} of this - * {@link PostKnowledgeInteraction}. It can be seen as the - * argument of a function call. - * @param result The {@code result} of this {@link PostKnowledgeInteraction}. - * It can be seen as the result of a function call. Can be - * {@code null} if this interaction does not expect any result. - * @apiNote TODO Can {@code argument} also be {@code null}? Note that not both - * {@code argument} and {@code result} can be {@code null}. - */ public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result) { - this(act, argument, result, null, false, false); + this(act, argument, result, null, false, false, null); } public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name) { - this(act, argument, result, name, false, false); + this(act, argument, result, name, false, false, null); } public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, boolean anIncludeMetaKIs) { - this(act, argument, result, null, false, anIncludeMetaKIs); + this(act, argument, result, null, false, anIncludeMetaKIs, null); } public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, boolean anIsMeta, boolean anIncludeMetaKIs) { - this(act, argument, result, null, anIsMeta, anIncludeMetaKIs); + this(act, argument, result, null, anIsMeta, anIncludeMetaKIs, null); } - public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name, boolean anIsMeta, - boolean anIncludeMetaKIs) { - super(act, name, anIsMeta, anIncludeMetaKIs); + /** + * Create a {@link PostKnowledgeInteraction}. See + * {@link KnowledgeInteraction#KnowledgeInteraction(CommunicativeAct, String, boolean, boolean, MatchStrategy)} + * + * + * @param argument The {@code argument} of this + * {@link PostKnowledgeInteraction}. It can be seen as the + * argument of a function call. + * @param result The {@code result} of this {@link PostKnowledgeInteraction}. + * It can be seen as the result of a function call. Can be + * {@code null} if this interaction does not expect any result. + * @apiNote Can {@code argument} also be {@code null}? No, only the + * {@code result} graph pattern can be {@code null}. Note that not both + * {@code argument} and {@code result} can be {@code null}. + */ + public PostKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name, + boolean anIsMeta, boolean anIncludeMetaKIs, MatchStrategy aMatchStrategy) { + super(act, name, anIsMeta, anIncludeMetaKIs, aMatchStrategy); this.argument = argument; this.result = result; } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/ReactKnowledgeInteraction.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/ReactKnowledgeInteraction.java index 06cbd373b..aa9951ba9 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/ReactKnowledgeInteraction.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/ReactKnowledgeInteraction.java @@ -19,42 +19,40 @@ public final class ReactKnowledgeInteraction extends KnowledgeInteraction { */ private final GraphPattern result; - /** - * Creates a {@link ReactKnowledgeInteraction}. - * - * @param act The {@link CommunicativeAct} of this - * {@link KnowledgeInteraction}. It can be read as the 'goal' or - * 'purpose' of the data exchange and whether it has - * side-effects or not. - * @param argument The {@code argument} of this {@link KnowledgeInteraction}. It - * can be seen as the argument of a function call. - * @param result The {@code result} of this {@link PostKnowledgeInteraction}. - * It can be seen as the result of a function call. Can be - * {@code null} if this interaction does not expect any result. - * @apiNote TODO Can {@code argument} also be {@code null}? Note that not both - * {@code argument} and {@code result} can be {@code null}. - */ public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result) { - this(act, argument, result, null, false, false); + this(act, argument, result, null, false, false, null); } public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name) { - this(act, argument, result, name, false, false); + this(act, argument, result, name, false, false, null); } public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, boolean anIsFullMatch) { - this(act, argument, result, null, false, anIsFullMatch); + this(act, argument, result, null, false, anIsFullMatch, null); } public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, boolean anIsMeta, boolean anIsFullMatch) { - this(act, argument, result, null, anIsMeta, anIsFullMatch); + this(act, argument, result, null, anIsMeta, anIsFullMatch, null); } - public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name, boolean anIsMeta, - boolean anIsFullMatch) { - super(act, name, anIsMeta, anIsFullMatch); + /** + * Creates a {@link ReactKnowledgeInteraction}. See + * {@link KnowledgeInteraction#KnowledgeInteraction(CommunicativeAct, String, boolean, boolean, MatchStrategy)} + * + * @param argument The {@code argument} of this {@link KnowledgeInteraction}. It + * can be seen as the argument of a function call. + * @param result The {@code result} of this {@link PostKnowledgeInteraction}. + * It can be seen as the result of a function call. Can be + * {@code null} if this interaction does not expect any result. + * @apiNote TODO Can {@code argument} also be {@code null}? No, only the + * {@code result} graph pattern can be {@code null}. Note that not both + * {@code argument} and {@code result} can be {@code null}. + */ + public ReactKnowledgeInteraction(CommunicativeAct act, GraphPattern argument, GraphPattern result, String name, + boolean anIsMeta, boolean anIsFullMatch, MatchStrategy aMatchStrategy) { + super(act, name, anIsMeta, anIsFullMatch, aMatchStrategy); this.argument = argument; this.result = result; } diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java index 2acfa44a0..3a9e7d044 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java @@ -31,7 +31,6 @@ import org.slf4j.Logger; import eu.knowledge.engine.reasoner.Rule; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; import eu.knowledge.engine.smartconnector.api.AnswerExchangeInfo; import eu.knowledge.engine.smartconnector.api.AnswerKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.AskPlan; @@ -40,6 +39,7 @@ import eu.knowledge.engine.smartconnector.api.BindingValidator; import eu.knowledge.engine.smartconnector.api.CommunicativeAct; import eu.knowledge.engine.smartconnector.api.GraphPattern; +import eu.knowledge.engine.smartconnector.api.MatchStrategy; import eu.knowledge.engine.smartconnector.api.PostPlan; import eu.knowledge.engine.smartconnector.api.ReactExchangeInfo; import eu.knowledge.engine.smartconnector.api.ReactKnowledgeInteraction; @@ -135,7 +135,7 @@ public AskPlan planAskFromKnowledgeBase(MyKnowledgeInteractionInfo anAKI, Recipi } else { processor = new ReasonerProcessor(otherKnowledgeInteractions, messageRouter, this.additionalDomainKnowledge); - ((ReasonerProcessor) processor).setDefaultReasoningStrategy(MatchStrategy.ENTRY_LEVEL); + ((ReasonerProcessor) processor).setMatchStrategy(MatchStrategy.ENTRY_LEVEL); } // give the caller something to chew on while it waits. This method starts the @@ -305,7 +305,7 @@ public PostPlan planPostFromKnowledgeBase(MyKnowledgeInteractionInfo aPKI, Recip } else { processor = new ReasonerProcessor(otherKnowledgeInteractions, this.messageRouter, this.additionalDomainKnowledge); - ((ReasonerProcessor) processor).setDefaultReasoningStrategy(MatchStrategy.ENTRY_LEVEL); + ((ReasonerProcessor) processor).setMatchStrategy(MatchStrategy.ENTRY_LEVEL); } // give the caller something to chew on while it waits. This method starts the // interaction process as far as it can until it is blocked because it waits for diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java index 6f54b5176..f2a73dc3e 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java @@ -40,6 +40,7 @@ import eu.knowledge.engine.smartconnector.api.CommunicativeAct; import eu.knowledge.engine.smartconnector.api.GraphPattern; import eu.knowledge.engine.smartconnector.api.KnowledgeEngineRuntimeException; +import eu.knowledge.engine.smartconnector.api.MatchStrategy; import eu.knowledge.engine.smartconnector.api.PostKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.PostResult; import eu.knowledge.engine.smartconnector.api.ReactKnowledgeInteraction; @@ -86,47 +87,52 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa "?ki rdf:type ?kiType .", "?ki kb:isMeta ?isMeta .", "?ki kb:hasCommunicativeAct ?act .", "?act rdf:type kb:CommunicativeAct .", "?act kb:hasRequirement ?req .", "?act kb:hasSatisfaction ?sat .", "?req rdf:type ?reqType .", "?sat rdf:type ?satType .", - "?ki kb:hasGraphPattern ?gp .", "?gp rdf:type ?patternType .", - "?gp kb:hasPattern ?pattern ."); + "?ki kb:hasGraphPattern ?gp .", "?gp rdf:type ?patternType .", "?gp kb:hasPattern ?pattern ."); - this.metaAnswerKI = new AnswerKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, true, true); - this.knowledgeBaseStore.register(this.metaAnswerKI, (anAKI, anAnswerExchangeInfo) -> this.fillMetaBindings(anAnswerExchangeInfo.getIncomingBindings()), + this.metaAnswerKI = new AnswerKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, null, true, + true, MatchStrategy.ENTRY_LEVEL); + this.knowledgeBaseStore.register(this.metaAnswerKI, + (anAKI, anAnswerExchangeInfo) -> this.fillMetaBindings(anAnswerExchangeInfo.getIncomingBindings()), true); - this.metaAskKI = new AskKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, true, true); + this.metaAskKI = new AskKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, null, true, true, + MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaAskKI, true); this.metaPostNewKI = new PostKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.NEW_KNOWLEDGE_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaPostNewKI, true); this.metaPostChangedKI = new PostKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.CHANGED_KNOWLEDGE_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaPostChangedKI, true); this.metaPostRemovedKI = new PostKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.REMOVED_KNOWLEDGE_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaPostRemovedKI, true); this.metaReactNewKI = new ReactKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.NEW_KNOWLEDGE_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaReactNewKI, (aRKI, aReactExchangeInfo) -> { var postingKi = aReactExchangeInfo.getPostingKnowledgeInteractionId(); - var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), KnowledgeInteractionInfo.Type.POST, Vocab.NEW_KNOWLEDGE_PURPOSE); + var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), + KnowledgeInteractionInfo.Type.POST, Vocab.NEW_KNOWLEDGE_PURPOSE); if (!postingKi.equals(itShouldBeThis)) { this.LOG.error("Received meta bindings from non-meta (or incorrect meta) KI {}", postingKi); this.LOG.debug("Received meta bindings: {}", aReactExchangeInfo.getArgumentBindings()); - throw new KnowledgeEngineRuntimeException("Received meta bindings from non-meta (or incorrect meta) KI."); + throw new KnowledgeEngineRuntimeException( + "Received meta bindings from non-meta (or incorrect meta) KI."); } - var newKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), aReactExchangeInfo.getPostingKnowledgeBaseId()); + var newKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.addKnowledgeBase(newKb); return new BindingSet(); }, true); @@ -134,16 +140,19 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa this.metaReactChangedKI = new ReactKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.CHANGED_KNOWLEDGE_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaReactChangedKI, (aRKI, aReactExchangeInfo) -> { var postingKi = aReactExchangeInfo.getPostingKnowledgeInteractionId(); - var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), KnowledgeInteractionInfo.Type.POST, Vocab.CHANGED_KNOWLEDGE_PURPOSE); + var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), + KnowledgeInteractionInfo.Type.POST, Vocab.CHANGED_KNOWLEDGE_PURPOSE); if (!postingKi.equals(itShouldBeThis)) { this.LOG.error("Received meta bindings from non-meta (or incorrect meta) KI {}", postingKi); this.LOG.debug("Received meta bindings: {}", aReactExchangeInfo.getArgumentBindings()); - throw new KnowledgeEngineRuntimeException("Received meta bindings from non-meta (or incorrect meta) KI."); + throw new KnowledgeEngineRuntimeException( + "Received meta bindings from non-meta (or incorrect meta) KI."); } - var changedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), aReactExchangeInfo.getPostingKnowledgeBaseId()); + var changedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.updateKnowledgeBase(changedKb); return new BindingSet(); }, true); @@ -151,33 +160,36 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa this.metaReactRemovedKI = new ReactKnowledgeInteraction( new CommunicativeAct(new HashSet<>(Arrays.asList(Vocab.REMOVED_KNOWLEDGE_PURPOSE)), new HashSet<>(Arrays.asList(Vocab.INFORM_PURPOSE))), - this.metaGraphPattern, null, true, true); + this.metaGraphPattern, null, null, true, true, MatchStrategy.ENTRY_LEVEL); this.knowledgeBaseStore.register(this.metaReactRemovedKI, (aRKI, aReactExchangeInfo) -> { var postingKi = aReactExchangeInfo.getPostingKnowledgeInteractionId(); - var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), KnowledgeInteractionInfo.Type.POST, Vocab.REMOVED_KNOWLEDGE_PURPOSE); + var itShouldBeThis = this.knowledgeBaseStore.getMetaId(aReactExchangeInfo.getPostingKnowledgeBaseId(), + KnowledgeInteractionInfo.Type.POST, Vocab.REMOVED_KNOWLEDGE_PURPOSE); if (!postingKi.equals(itShouldBeThis)) { this.LOG.error("Received meta bindings from non-meta (or incorrect meta) KI {}", postingKi); this.LOG.debug("Received meta bindings: {}", aReactExchangeInfo.getArgumentBindings()); - throw new KnowledgeEngineRuntimeException("Received meta bindings from non-meta (or incorrect meta) KI."); + throw new KnowledgeEngineRuntimeException( + "Received meta bindings from non-meta (or incorrect meta) KI."); } - var removedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), aReactExchangeInfo.getPostingKnowledgeBaseId()); + var removedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.removeKnowledgeBase(removedKb); return new BindingSet(); }, true); } /** - * Generate a binding set that (together with the meta graph pattern) - * represents this knowledge base and its knowledge interactions. + * Generate a binding set that (together with the meta graph pattern) represents + * this knowledge base and its knowledge interactions. * - * @param incoming If given, this method will make sure to return a binding - * set that only contains bindings that 'fit on' a binding in the given - * binding set by removing bindings that do not 'fit'. If null, no such - * operation is performed. + * @param incoming If given, this method will make sure to return a binding set + * that only contains bindings that 'fit on' a binding in the + * given binding set by removing bindings that do not 'fit'. If + * null, no such operation is performed. * * @return a binding set (or part thereof, if {@code incoming} is given) that - * (together with the meta graph pattern) represents this knowledge base and - * its knowledge interactions. + * (together with the meta graph pattern) represents this knowledge base + * and its knowledge interactions. */ private BindingSet fillMetaBindings(BindingSet incoming) { @@ -326,13 +338,17 @@ public CompletableFuture getOtherKnowledgeBase(URI toKnowled try { this.LOG.trace("Received message: {}", answerMsg); var answeringKi = answerMsg.getFromKnowledgeInteraction(); - var itShouldBeThis = this.knowledgeBaseStore.getMetaId(toKnowledgeBaseId, KnowledgeInteractionInfo.Type.ANSWER, null); + var itShouldBeThis = this.knowledgeBaseStore.getMetaId(toKnowledgeBaseId, + KnowledgeInteractionInfo.Type.ANSWER, null); if (!answeringKi.equals(itShouldBeThis)) { - this.LOG.error("Received meta bindings from non-meta (or incorrect meta) KI {}", answeringKi); + this.LOG.error("Received meta bindings from non-meta (or incorrect meta) KI {}", + answeringKi); this.LOG.debug("Received meta bindings: {}", answerMsg.getBindings()); - throw new KnowledgeEngineRuntimeException("Received meta bindings from non-meta (or incorrect meta) KI."); + throw new KnowledgeEngineRuntimeException( + "Received meta bindings from non-meta (or incorrect meta) KI."); } - var otherKB = this.constructOtherKnowledgeBaseFromBindingSet(answerMsg.getBindings(), toKnowledgeBaseId); + var otherKB = this.constructOtherKnowledgeBaseFromBindingSet(answerMsg.getBindings(), + toKnowledgeBaseId); return otherKB; } catch (Throwable t) { this.LOG.error("The construction of other knowledge base should succeed.", t); @@ -349,7 +365,8 @@ public CompletableFuture getOtherKnowledgeBase(URI toKnowled } } - private OtherKnowledgeBase constructOtherKnowledgeBaseFromBindingSet(BindingSet bindings, URI otherKnowledgeBaseId) { + private OtherKnowledgeBase constructOtherKnowledgeBaseFromBindingSet(BindingSet bindings, + URI otherKnowledgeBaseId) { assert !bindings.isEmpty() : "An answer meta message should always have at least a single binding."; Model model; @@ -395,8 +412,8 @@ private OtherKnowledgeBase constructOtherKnowledgeBaseFromBindingSet(BindingSet var kiMeta = model.listObjectsOfProperty(ki, Vocab.IS_META).next(); boolean isMeta = kiMeta.asLiteral().getBoolean(); - assert isMeta == kiMeta.toString().contains("true") : "If the text contains 'true' (=" + kiMeta - + ") then the boolean should be true."; + assert isMeta == kiMeta.toString().contains("true") + : "If the text contains 'true' (=" + kiMeta + ") then the boolean should be true."; this.LOG.trace("meta: {} = {}", FmtUtils.stringForNode(kiMeta.asNode()), isMeta); @@ -462,19 +479,23 @@ private OtherKnowledgeBase constructOtherKnowledgeBaseFromBindingSet(BindingSet Resource gpType = graphPattern.getPropertyResourceValue(RDF.type); if (gpType.equals(Vocab.ARGUMENT_GRAPH_PATTERN)) { if (argumentGraphPatternString != null) { - throw new IllegalArgumentException("Knowledge interaction cannot have multiple argument patterns."); + throw new IllegalArgumentException( + "Knowledge interaction cannot have multiple argument patterns."); } argumentGraphPatternString = graphPattern.getProperty(Vocab.HAS_PATTERN).getString(); } else if (gpType.equals(Vocab.RESULT_GRAPH_PATTERN)) { if (resultGraphPatternString != null) { - throw new IllegalArgumentException("Knowledge interaction cannot have multiple result patterns."); + throw new IllegalArgumentException( + "Knowledge interaction cannot have multiple result patterns."); } resultGraphPatternString = graphPattern.getProperty(Vocab.HAS_PATTERN).getString(); } else { - throw new IllegalArgumentException(String.format("For a POST/REACT Knowledge Interaction, their graph pattern must be either %s or %s. Not %s.", Vocab.ARGUMENT_GRAPH_PATTERN, Vocab.RESULT_GRAPH_PATTERN, gpType)); + throw new IllegalArgumentException(String.format( + "For a POST/REACT Knowledge Interaction, their graph pattern must be either %s or %s. Not %s.", + Vocab.ARGUMENT_GRAPH_PATTERN, Vocab.RESULT_GRAPH_PATTERN, gpType)); } } - + if (argumentGraphPatternString == null) { throw new IllegalArgumentException( "Every Post or React Knowledge Interaction should have an argument graph pattern."); diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java index 4dc05bb6e..f561bce40 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.time.Instant; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -22,7 +23,7 @@ import org.slf4j.helpers.MessageFormatter; import eu.knowledge.engine.reasoner.BaseRule; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.ProactiveRule; import eu.knowledge.engine.reasoner.ReasonerPlan; import eu.knowledge.engine.reasoner.Rule; @@ -41,6 +42,7 @@ import eu.knowledge.engine.smartconnector.api.ExchangeInfo.Status; import eu.knowledge.engine.smartconnector.api.GraphPattern; import eu.knowledge.engine.smartconnector.api.KnowledgeInteraction; +import eu.knowledge.engine.smartconnector.api.MatchStrategy; import eu.knowledge.engine.smartconnector.api.PostExchangeInfo; import eu.knowledge.engine.smartconnector.api.PostKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.PostResult; @@ -72,7 +74,8 @@ public class ReasonerProcessor extends SingleInteractionProcessor { private final Set postExchangeInfos; private Set additionalDomainKnowledge; private ReasonerPlan reasonerPlan; - private MatchStrategy defaultStrategy = MatchStrategy.NORMAL_LEVEL; + + private MatchStrategy matchStrategy = MatchStrategy.NORMAL_LEVEL; /** * These two bindingset handler are a bit dodgy. We need them to make the post @@ -146,8 +149,14 @@ public void planAskInteraction(MyKnowledgeInteractionInfo aAKI) { ProactiveRule aRule = new ProactiveRule(ruleName, translateGraphPatternTo(aki.getPattern()), new HashSet<>()); this.store.addRule(aRule); - this.reasonerPlan = new ReasonerPlan(this.store, aRule, - ki.includeMetaKIs() ? MatchStrategy.ENTRY_LEVEL : this.defaultStrategy); + + EnumSet config; + if (aAKI.getKnowledgeInteraction().getMatchStrategy() == null) + config = this.matchStrategy.toConfig(true); + else + config = aAKI.getKnowledgeInteraction().getMatchStrategy().toConfig(true); + + this.reasonerPlan = new ReasonerPlan(this.store, aRule, config); } else { LOG.warn("Type should be Ask, not {}", this.myKnowledgeInteraction.getType()); this.finalBindingSetFuture.complete(new eu.knowledge.engine.reasoner.api.BindingSet()); @@ -212,8 +221,13 @@ public void planPostInteraction(MyKnowledgeInteractionInfo aPKI) { ProactiveRule aRule = new ProactiveRule(ruleName, new HashSet<>(), new HashSet<>(translatedGraphPattern)); store.addRule(aRule); - this.reasonerPlan = new ReasonerPlan(this.store, aRule, - pki.includeMetaKIs() ? MatchStrategy.ENTRY_LEVEL : this.defaultStrategy); + EnumSet config; + if (aPKI.getKnowledgeInteraction().getMatchStrategy() == null) + config = this.matchStrategy.toConfig(false); + else + config = aPKI.getKnowledgeInteraction().getMatchStrategy().toConfig(false); + + this.reasonerPlan = new ReasonerPlan(this.store, aRule, config); } else { LOG.warn("Type should be Post, not {}", this.myKnowledgeInteraction.getType()); @@ -607,7 +621,7 @@ public ReasonerPlan getReasonerPlan() { return this.reasonerPlan; } - public void setDefaultReasoningStrategy(MatchStrategy aStrategy) { - this.defaultStrategy = aStrategy; + public void setMatchStrategy(MatchStrategy aStrategy) { + this.matchStrategy = aStrategy; } } diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeNetwork.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeNetwork.java index a177f9cf9..bf35d20d9 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeNetwork.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeNetwork.java @@ -17,6 +17,7 @@ import eu.knowledge.engine.smartconnector.api.AskKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.CommunicativeAct; import eu.knowledge.engine.smartconnector.api.GraphPattern; +import eu.knowledge.engine.smartconnector.api.MatchStrategy; import eu.knowledge.engine.smartconnector.api.Vocab; public class KnowledgeNetwork { @@ -76,7 +77,7 @@ private void startAndWaitForReady() { // register our state check Knowledge Interaction on each Smart Connecotr GraphPattern gp = new GraphPattern(this.prefixMapping, - // @formatter:off + // @formatter:off "?kb rdf:type kb:KnowledgeBase .", "?kb kb:hasName ?name .", "?kb kb:hasDescription ?description .", "?kb kb:hasKnowledgeInteraction ?ki .", "?ki rdf:type ?kiType .", "?ki kb:isMeta ?isMeta .", "?ki kb:hasCommunicativeAct ?act .", "?act rdf:type kb:CommunicativeAct .", @@ -87,7 +88,8 @@ private void startAndWaitForReady() { ); for (MockedKnowledgeBase kb : justStartedKBs) { - AskKnowledgeInteraction anAskKI = new AskKnowledgeInteraction(new CommunicativeAct(), gp, true); + AskKnowledgeInteraction anAskKI = new AskKnowledgeInteraction(new CommunicativeAct(), gp, null, false, true, + MatchStrategy.ENTRY_LEVEL); this.knowledgeInteractionMetadata.put(kb, anAskKI); kb.register(anAskKI); } diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java index 0331b5b25..7db735f52 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java @@ -262,7 +262,8 @@ public float convert(float fahrenheit) { """; GraphPattern gp2 = new GraphPattern(prefixes, TestUtils.convertGP(pattern)); - AskKnowledgeInteraction askKI = new AskKnowledgeInteraction(new CommunicativeAct(), gp2); + AskKnowledgeInteraction askKI = new AskKnowledgeInteraction(new CommunicativeAct(), gp2, null, false, false, + MatchStrategy.NORMAL_LEVEL); dashboardKB.setDomainKnowledge(new HashSet<>( Arrays.asList(locatedInRule, thermostatSensorRule, opencloseSensorRule, fahrenheitConverterRule))); dashboardKB.register(askKI); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java index 81fad1de6..4b0966933 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java @@ -7,6 +7,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -27,7 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.knowledge.engine.reasoner.BaseRule.MatchStrategy; +import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.Match; import eu.knowledge.engine.reasoner.ReasonerPlan; import eu.knowledge.engine.reasoner.Rule; @@ -202,7 +203,7 @@ private void updateNetwork(Set> gaps) { Rule r = new Rule(translateGraphPatternTo(ki.getArgument()), translateGraphPatternTo(ki.getResult())); - Set matches = r.consequentMatches(gap, MatchStrategy.ADVANCED_LEVEL); + Set matches = r.consequentMatches(gap, EnumSet.of(MatchFlag.ONLY_BIGGEST)); if (!matches.isEmpty()) { kn.addKB(kb);