Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

411 implement combimatch to improve reasoner performance #526

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
696 changes: 513 additions & 183 deletions reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java

Large diffs are not rendered by default.

36 changes: 35 additions & 1 deletion reasoner/src/main/java/eu/knowledge/engine/reasoner/Match.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,41 @@ public Node getOtherNode(Map<TripleNode, TripleNode> aContext, Node aNode) {

@Override
public String toString() {
return "Match " + mapping;

StringBuilder sb = new StringBuilder();
sb.append("{");
for (Map.Entry<TriplePattern, TriplePattern> entry : this.matchingPatterns.entrySet()) {

boolean firstTriplePattern = true;
for (TriplePattern tp : new TriplePattern[] { entry.getKey(), entry.getValue() }) {
boolean firstTime = true;
Node[] nodes = new Node[] { tp.getSubject(), tp.getPredicate(), tp.getObject() };
for (int i = 0; i < 3; i++) {
Node n = nodes[i];

if (!firstTime) {
sb.append(" ");
}
var truncatedNode = TriplePattern.trunc(n);

var tn = new TripleNode(tp, n, i);

if (firstTriplePattern ? this.mapping.containsValue(tn) : this.mapping.containsKey(tn)) {
sb.append("|").append(truncatedNode).append("|");
} else {
sb.append(truncatedNode);
}
firstTime = false;
}
if (firstTriplePattern)
sb.append("=");
firstTriplePattern = false;
}
sb.append(", ");
}
sb.deleteCharAt(sb.length() - 1).deleteCharAt(sb.length() - 1).append("}");

return "Match " + sb.toString();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutionException;

Expand Down Expand Up @@ -39,7 +38,7 @@ public class ReasonerPlan {
private final ProactiveRule start;
private final Map<BaseRule, RuleNode> ruleToRuleNode;
private boolean done;
private MatchStrategy strategy = MatchStrategy.FIND_ALL_MATCHES;
private MatchStrategy strategy = MatchStrategy.ULTRA_LEVEL;
private boolean useTaskBoard = true;

public ReasonerPlan(RuleStore aStore, ProactiveRule aStartRule) {
Expand Down Expand Up @@ -101,6 +100,7 @@ public TaskBoard execute(BindingSet bindingSet) {
Set<RuleNode> changed = new HashSet<>();

do {
LOG.trace("New round.");
stack.clear();
visited.clear();
changed.clear();
Expand Down Expand Up @@ -267,8 +267,8 @@ private RuleNode createOrGetReasonerNode(BaseRule aRule, BaseRule aParent) {
boolean ourAntecedentFullyMatchesParentConsequent = false;

if (aParent != null && this.store.getAntecedentNeighbors(aRule, this.strategy).containsKey(aParent)) {
ourAntecedentFullyMatchesParentConsequent = antecedentFullyMatchesConsequent(aRule.getAntecedent(),
aParent.getConsequent(), this.getMatchStrategy());
ourAntecedentFullyMatchesParentConsequent = antecedentFullyMatchesConsequent(aRule, aParent,
this.store.getAntecedentNeighbors(aRule, this.strategy).get(aParent), this.strategy);
}

if (!ourAntecedentFullyMatchesParentConsequent) {
Expand Down Expand Up @@ -312,22 +312,23 @@ private void scheduleOrDoTask(RuleNode current, TaskBoard taskBoard) {
* that if the antecedent is a subset of the consequent this method also return
* true.
*
* @param consequent
* @param antecedent
* @param consequentRule
* @param antecedentRule
* @return
*/
private boolean antecedentFullyMatchesConsequent(Set<TriplePattern> antecedent, Set<TriplePattern> consequent,
MatchStrategy aMatchStrategy) {
private boolean antecedentFullyMatchesConsequent(BaseRule antecedentRule, BaseRule consequentRule,
Set<Match> someMatches, MatchStrategy aMatchStrategy) {

var antecedent = antecedentRule.getAntecedent();
var consequent = consequentRule.getConsequent();

assert !antecedent.isEmpty();
assert !consequent.isEmpty();

if (antecedent.size() > consequent.size())
return false;

Set<Match> matches = BaseRule.matches(antecedent, consequent, aMatchStrategy);

for (Match m : matches) {
for (Match m : someMatches) {
// check if there is a match that is full
boolean allFound = true;
for (TriplePattern tp : antecedent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ public static String trunc(Node n) {
return uri.getFragment();
}
var path = uri.getPath();
if (path != null)
if (path != null && path.substring(path.lastIndexOf('/') + 1).length() > 0)
return path.substring(path.lastIndexOf('/') + 1);

} else if (n.isLiteral()) {
return n.getLiteralLexicalForm();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package eu.knowledge.engine.reasoner.api;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -141,6 +142,16 @@ public boolean containsKey(TripleNode key) {
return this.tripleVarMapping.containsKey(key);
}

public Set<TripleNode> getTripleNodes(TriplePattern aTriplePattern) {
Set<TripleNode> nodes = new HashSet<TripleNode>();
for (TripleNode tv : this.tripleVarMapping.keySet()) {
if (tv.tp.equals(aTriplePattern)) {
nodes.add(tv);
}
}
return nodes;
}

public boolean containsVar(Var aVar) {
assert aVar instanceof Var;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package eu.knowledge.engine.reasoner.api;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.jena.atlas.logging.Log;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Node_Concrete;
import org.apache.jena.sparql.core.Var;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.knowledge.engine.reasoner.Match;

Expand All @@ -16,17 +21,17 @@ public class TripleVarBindingSet {
private Set<TripleVarBinding> bindings;
private Set<TripleNode> tripleVarsCache;

private static final Logger LOG = LoggerFactory.getLogger(TripleVarBindingSet.class);

public TripleVarBindingSet(Set<TriplePattern> aGraphPattern) {

this.graphPattern = aGraphPattern;
bindings = new HashSet<>();
bindings = ConcurrentHashMap.newKeySet();
}

public TripleVarBindingSet(Set<TriplePattern> aGraphPattern, BindingSet aBindingSet) {

this.graphPattern = aGraphPattern;

this.bindings = new HashSet<>();
this(aGraphPattern);

for (Binding b : aBindingSet) {
this.add(new TripleVarBinding(this.graphPattern, b));
Expand Down Expand Up @@ -160,21 +165,17 @@ public TripleVarBindingSet merge(TripleVarBindingSet aGraphBindingSet) {
}
} else {
// Cartesian product is the base case
boolean firstTime = true;
for (TripleVarBinding tvb1 : this.bindings) {
gbs.add(tvb1);
gbs.addAll(aGraphBindingSet.getBindings());
gbs.addAll(this.bindings);
this.bindings.stream().parallel().forEach(tvb1 -> {

for (TripleVarBinding otherB : aGraphBindingSet.getBindings()) {
if (firstTime)
gbs.add(otherB);

// always add a merged version of the two bindings, except when they conflict.
if (!tvb1.isConflicting(otherB)) {
gbs.add(tvb1.merge(otherB));
}
}
firstTime = false;
}
});
}

return gbs;
Expand All @@ -199,6 +200,10 @@ public boolean isEmpty() {
* @return
*/
public TripleVarBindingSet translate(Set<TriplePattern> graphPattern, Set<Match> match) {
LOG.trace("Translating binding set with '{}' bindings and '{}' matches.", this.bindings.size(), match.size());

long start = System.currentTimeMillis();

TripleVarBindingSet newOne = new TripleVarBindingSet(graphPattern);
TripleVarBinding toB;
for (TripleVarBinding fromB : this.bindings) {
Expand Down Expand Up @@ -247,6 +252,7 @@ public TripleVarBindingSet translate(Set<TriplePattern> graphPattern, Set<Match>
newOne.add(toB);
}
}

return newOne;

}
Expand Down Expand Up @@ -287,4 +293,79 @@ public TripleVarBindingSet keepCompatible(TripleVarBindingSet bindingSet) {

return newBS;
}

/**
* Prints the debugging table of this triple Var binding set
*/
public void printDebuggingTable() {
StringBuilder table = new StringBuilder();

// header row
int count = 0;
table.append("| Graph Pattern |");
count++;

List<TripleVarBinding> tvbindings = new ArrayList<>(this.getBindings());

for (int i = 0; i < tvbindings.size(); i++) {
table.append("Binding-" + i).append(" | ");
count++;
}

table.append("\n");

// separator row
table.append("|");
for (int i = 0; i < count; i++) {
table.append("-------|");
}
table.append("\n");

// content rows
for (TriplePattern tp : this.graphPattern) {
// triple pattern
table.append(" | ").append(tp.toString()).append(" | ");

// bindings

for (TripleVarBinding tvb : tvbindings) {
Set<TripleNode> nodes = tvb.getTripleNodes(tp);
if (!nodes.isEmpty()) {

Node_Concrete subject = null;
Node_Concrete predicate = null;
Node_Concrete object = null;

for (TripleNode tn : nodes) {
if (tn.nodeIdx == 0) {
subject = tvb.get(tn);
} else if (tn.nodeIdx == 1)
predicate = tvb.get(tn);
else if (tn.nodeIdx == 2)
object = tvb.get(tn);
}

table.append(subject != null ? subject : formatNode(tp.getSubject())).append(" ");
table.append(predicate != null ? predicate : formatNode(tp.getPredicate())).append(" ");
table.append(object != null ? object : formatNode(tp.getObject())).append(" ");

} else {
table.append("");
}

table.append(" | ");
}

table.append("\n");
}
System.out.println(table.toString());
}

private String formatNode(Node n) {

String before = "<span style=\"color:red\">";
String after = "</span>";

return n.isVariable() ? before + TriplePattern.trunc(n) + after : TriplePattern.trunc(n);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ public Set<RuleNode> getAllNeighbours() {
public boolean addResultBindingSetInput(RuleNode aNeighbor, TripleVarBindingSet aBindingSet) {
assert (antecedentNeighbours.keySet().contains(aNeighbor));
TripleVarBindingSet filteredBS = aBindingSet;
if (this.filterBindingSetOutput != null) {
if (this.filterBindingSetOutput != null && !this.hasProactiveParent(aNeighbor)) {
filteredBS = aBindingSet.keepCompatible(this.filterBindingSetOutput);
}

var changed = this.resultBindingSetInput.add(aNeighbor, filteredBS);
if (changed && this.filterBindingSetOutput == null) {
if (changed && this.filterBindingSetOutput == null && this.hasProactiveParent(aNeighbor)) {
var previousBindingSetOutput = this.filterBindingSetOutput;
this.filterBindingSetOutput = this.resultBindingSetInput.get();

Expand Down Expand Up @@ -94,4 +94,12 @@ public TripleVarBindingSet getFilterBindingSetInput() {
return null;
}

/**
* Prints the binding set store of this Rule Node to the std out in a markdown
* table format.
*/
public void printResultBindingSetInputStore() {
this.resultBindingSetInput.printDebuggingTable();
}

}
Loading
Loading