Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ public boolean isConflicting(TripleVarBinding tvb) {
return false;
}

/**
* True if two Bindings have a different value for at least one variable. Note
* that it looks not at variable instances.
*/
public boolean isConflicting2(TripleVarBinding tvb, Set<Var> overlappingVars) {

Node l, val;
for (Var e : overlappingVars) {
l = tvb.getVarValue(e);

val = this.getVarValue(e);

if (val != null && l != null && !val.sameValueAs(l)) {
return true;
}
}
return false;
}

/**
* We assume all occurrences of a var have the same literal, we just return the
* first one found.
Expand Down Expand Up @@ -253,4 +272,8 @@ public boolean containsTriplePattern(TriplePattern value) {
return false;
}

public Set<Var> getVars() {
return this.variableTripleVarMapping.keySet();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,24 @@ public class TripleVarBindingSet {
private Set<TriplePattern> graphPattern;
private Set<TripleVarBinding> bindings;
private Set<TripleNode> tripleVarsCache;
private Set<Var> varsCache;

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

public TripleVarBindingSet(Set<TriplePattern> aGraphPattern) {

this(aGraphPattern, 16);
}

public TripleVarBindingSet(Set<TriplePattern> aGraphPattern, int initialCapacity) {

this.graphPattern = aGraphPattern;
bindings = ConcurrentHashMap.newKeySet();
bindings = ConcurrentHashMap.newKeySet(initialCapacity);
}

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

this(aGraphPattern);
this(aGraphPattern, aBindingSet.size());

for (Binding b : aBindingSet) {
this.add(new TripleVarBinding(this.graphPattern, b));
Expand Down Expand Up @@ -171,6 +177,15 @@ public TripleVarBindingSet merge(TripleVarBindingSet aBindingSet) {
return gbs;
}

public Set<Var> getVariables() {
if (this.varsCache == null) {
this.varsCache = new HashSet<Var>();
for (TriplePattern tp : this.graphPattern)
this.varsCache.addAll(tp.getVariables());
}
return this.varsCache;
}

/**
* Special merge that only combines the current bindings with the given
* bindings. It only adds bindings that are a combination of two input bindings
Expand All @@ -187,17 +202,26 @@ public TripleVarBindingSet combine(TripleVarBindingSet aBindingSet) {
LOG.trace("Merging {} bindings with our {} bindings.", aBindingSet.getBindings().size(),
this.getBindings().size());

TripleVarBindingSet gbs = new TripleVarBindingSet(this.graphPattern);

final int otherBindingSetSize = aBindingSet.getBindings().size();
final long totalCount = (long) otherBindingSetSize * (long) this.getBindings().size();
if (totalCount > LARGE_BS_SIZE)
LOG.warn("Merging 2 large BindingSets ({} * {} = {}). This can take some time.",
aBindingSet.getBindings().size(), this.getBindings().size(), totalCount);
TripleVarBindingSet gbs = new TripleVarBindingSet(this.graphPattern, (int) totalCount);

if (this.bindings.isEmpty()) {
gbs.addAll(aBindingSet.getBindings());
} else {

Set<Var> overlappingVars = new HashSet<Var>();
if (this.bindings.size() > 0 && aBindingSet.getBindings().size() > 0) {
Set<Var> vars1 = this.getVariables();
Set<Var> vars2 = aBindingSet.getVariables();
overlappingVars.addAll(vars1);
overlappingVars.retainAll(vars2);
LOG.trace("Overlapping vars found: {} - {} = {}", vars1, vars2, overlappingVars);
}

// Cartesian product is the base case
AtomicLong progress = new AtomicLong(0);

Expand All @@ -207,7 +231,7 @@ public TripleVarBindingSet combine(TripleVarBindingSet aBindingSet) {
this.bindings.stream().parallel().forEach(tvb1 -> {
for (TripleVarBinding otherB : aBindingSet.getBindings()) {
// always add a merged version of the two bindings, except when they conflict.
if (!tvb1.isConflicting(otherB)) {
if (!tvb1.isConflicting2(otherB, overlappingVars)) {
gbs.add(tvb1.merge(otherB));
}
}
Expand All @@ -221,7 +245,7 @@ public TripleVarBindingSet combine(TripleVarBindingSet aBindingSet) {
}

if (totalCount > LARGE_BS_SIZE)
LOG.debug("Merging large BindingSets done!");
LOG.trace("Merging large BindingSets done!");

return gbs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -92,7 +93,7 @@ public boolean haveAllNeighborsContributedExcept(Set<RuleNode> nodes) {
}

/**
* Translates the given TripleVarBindingSets from neighbors to a single
* Combine the given TripleVarBindingSets from neighbors to a single
* TripleVarBindingSet using the given combi matches. Because the combi matches
* are very specific to how they should be formed, using this information should
* speed up the binding set merging process considerably.
Expand All @@ -104,15 +105,16 @@ public boolean haveAllNeighborsContributedExcept(Set<RuleNode> nodes) {
* @return A TripleVarBindingSet that consists of only valid (according to the
* combimatches) bindings.
*/
private TripleVarBindingSet translateWithCombiMatches(Set<TriplePattern> aGraphPattern,
private TripleVarBindingSet combineWithCombiMatches(Set<TriplePattern> aGraphPattern,
Set<CombiMatch> someCombiMatches, Map<BaseRule, Map<Match, TripleVarBindingSet>> someNeighborBS) {
var combinedTVBS = new TripleVarBindingSet(aGraphPattern);

int i = 0;
AtomicLong i = new AtomicLong(0);
int size = someCombiMatches.size();
for (CombiMatch cMatch : someCombiMatches) {
i = i + 1;
LOG.trace("Creating binding set for combi match: {}/{}", i, size);

someCombiMatches.stream().forEach(cMatch -> {
i.incrementAndGet();
LOG.trace("Creating binding set for combi match: {}/{}", i.get(), size);

// keep separate binding set per combi match
var cMatchTVBS = new TripleVarBindingSet(aGraphPattern);
Expand All @@ -128,15 +130,15 @@ private TripleVarBindingSet translateWithCombiMatches(Set<TriplePattern> aGraphP
TripleVarBindingSet tvbs = matchToBS.get(cSingleMatch);

if (tvbs != null)
cMatchTVBS.addAll(cMatchTVBS.combine(tvbs).getBindings());
cMatchTVBS = cMatchTVBS.combine(tvbs);
}
}
}

// addAll instead of merge, because different combi matches do not need to be
// combined.
combinedTVBS.addAll(cMatchTVBS.getBindings());
}
});

return combinedTVBS;

Expand Down Expand Up @@ -167,7 +169,7 @@ public TripleVarBindingSet get() {
// at the consequent/antecedent neighbors depending on backward/forward
// reasoning) we use the older (slower) method when there are no combi matches.
if (this.combiMatches != null)
this.cache = this.translateWithCombiMatches(this.graphPattern, this.combiMatches, this.neighborBindingSet);
this.cache = this.combineWithCombiMatches(this.graphPattern, this.combiMatches, this.neighborBindingSet);
else {
LOG.trace("Ignoring combi matches for binding set construction.");
TripleVarBindingSet combinedBS = new TripleVarBindingSet(graphPattern);
Expand Down
Loading