aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-06 16:13:55 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-09 00:07:39 +0100
commiteedc0ac8c20710e20095e0c19269601c2719543a (patch)
tree86341ae1eb585eb41167670ab970d2aa6dc16609
parentrefactor(frontend): theme improvements (diff)
downloadrefinery-eedc0ac8c20710e20095e0c19269601c2719543a.tar.gz
refinery-eedc0ac8c20710e20095e0c19269601c2719543a.tar.zst
refinery-eedc0ac8c20710e20095e0c19269601c2719543a.zip
refactor(store): remove CountPolarity
We will have to implement counting in DNF queries in another way.
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java7
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountExpressionEvaluator.java38
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountNotEqualsExpressionEvaluator.java30
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java37
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java45
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java27
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/ComparisonOperator.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CountNotEqualsAtom.java31
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CountingPolarity.java13
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/SimplePolarity.java26
10 files changed, 28 insertions, 248 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
index 59fb1171..37cd91a6 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
@@ -57,8 +57,6 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
57 validateRelationAtom(relationViews, dnfPredicate, relationViewAtom); 57 validateRelationAtom(relationViews, dnfPredicate, relationViewAtom);
58 } else if (atom instanceof CallAtom<?> queryCallAtom) { 58 } else if (atom instanceof CallAtom<?> queryCallAtom) {
59 validatePredicateAtom(predicates, dnfPredicate, queryCallAtom); 59 validatePredicateAtom(predicates, dnfPredicate, queryCallAtom);
60 } else if (atom instanceof CountNotEqualsAtom<?> countNotEqualsAtom) {
61 validateCountNotEqualsAtom(predicates, dnfPredicate, countNotEqualsAtom);
62 } else if (!(atom instanceof EquivalenceAtom || atom instanceof ConstantAtom)) { 60 } else if (!(atom instanceof EquivalenceAtom || atom instanceof ConstantAtom)) {
63 throw new IllegalArgumentException("Unknown constraint: " + atom.toString()); 61 throw new IllegalArgumentException("Unknown constraint: " + atom.toString());
64 } 62 }
@@ -89,11 +87,6 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
89 validatePredicateReference(predicates, dnfPredicate, queryCallAtom.getTarget()); 87 validatePredicateReference(predicates, dnfPredicate, queryCallAtom.getTarget());
90 } 88 }
91 89
92 private void validateCountNotEqualsAtom(Set<DNF> predicates, DNF dnfPredicate,
93 CountNotEqualsAtom<?> countNotEqualsAtom) {
94 validatePredicateReference(predicates, dnfPredicate, countNotEqualsAtom.mayTarget());
95 validatePredicateReference(predicates, dnfPredicate, countNotEqualsAtom.mustTarget());
96 }
97 90
98 private Map<DNF, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNF> predicates) { 91 private Map<DNF, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNF> predicates) {
99 Map<DNF, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); 92 Map<DNF, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>();
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountExpressionEvaluator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountExpressionEvaluator.java
deleted file mode 100644
index e583e187..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountExpressionEvaluator.java
+++ /dev/null
@@ -1,38 +0,0 @@
1package tools.refinery.store.query.viatra.internal.pquery;
2
3import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator;
4import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider;
5import tools.refinery.store.query.atom.ComparisonOperator;
6import tools.refinery.store.query.atom.CountingPolarity;
7
8import java.util.List;
9
10public record CountExpressionEvaluator(String variableName, ComparisonOperator operator,
11 int threshold) implements IExpressionEvaluator {
12 public CountExpressionEvaluator(String variableName, CountingPolarity polarity) {
13 this(variableName, polarity.operator(), polarity.threshold());
14 }
15
16 @Override
17 public String getShortDescription() {
18 return "%s %s %d".formatted(variableName, operator, threshold);
19 }
20
21 @Override
22 public Iterable<String> getInputParameterNames() {
23 return List.of(variableName);
24 }
25
26 @Override
27 public Object evaluateExpression(IValueProvider provider) {
28 int value = (Integer) provider.getValue(variableName);
29 return switch (operator) {
30 case EQUALS -> value == threshold;
31 case NOT_EQUALS -> value != threshold;
32 case LESS -> value < threshold;
33 case LESS_EQUALS -> value <= threshold;
34 case GREATER -> value > threshold;
35 case GREATER_EQUALS -> value >= threshold;
36 };
37 }
38}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountNotEqualsExpressionEvaluator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountNotEqualsExpressionEvaluator.java
deleted file mode 100644
index 6f333a06..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CountNotEqualsExpressionEvaluator.java
+++ /dev/null
@@ -1,30 +0,0 @@
1package tools.refinery.store.query.viatra.internal.pquery;
2
3import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator;
4import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider;
5
6import java.util.List;
7
8public record CountNotEqualsExpressionEvaluator(boolean must, int threshold, String mayVariableName,
9 String mustVariableName) implements IExpressionEvaluator {
10 @Override
11 public String getShortDescription() {
12 return "%d %s not in [%s; %s]".formatted(threshold, must ? "must" : "may", mustVariableName, mayVariableName);
13 }
14
15 @Override
16 public Iterable<String> getInputParameterNames() {
17 return List.of(mayVariableName, mustVariableName);
18 }
19
20 @Override
21 public Object evaluateExpression(IValueProvider provider) throws Exception {
22 int mayCount = (Integer) provider.getValue(mayVariableName);
23 int mustCount = (Integer) provider.getValue(mustVariableName);
24 if (must) {
25 return mayCount < threshold || mustCount > threshold;
26 } else {
27 return mayCount > threshold || mustCount < threshold;
28 }
29 }
30}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
index ae99365d..98054161 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
@@ -85,8 +85,6 @@ public class DNF2PQuery {
85 translateCallAtom(callAtom, body); 85 translateCallAtom(callAtom, body);
86 } else if (constraint instanceof ConstantAtom constantAtom) { 86 } else if (constraint instanceof ConstantAtom constantAtom) {
87 translateConstantAtom(constantAtom, body); 87 translateConstantAtom(constantAtom, body);
88 } else if (constraint instanceof CountNotEqualsAtom<?> countNotEqualsAtom) {
89 translateCountNotEqualsAtom(countNotEqualsAtom, body);
90 } else { 88 } else {
91 throw new IllegalArgumentException("Unknown constraint: " + constraint.toString()); 89 throw new IllegalArgumentException("Unknown constraint: " + constraint.toString());
92 } 90 }
@@ -128,20 +126,11 @@ public class DNF2PQuery {
128 var variablesTuple = translateSubstitution(callAtom.getSubstitution(), body); 126 var variablesTuple = translateSubstitution(callAtom.getSubstitution(), body);
129 var translatedReferred = translate(target); 127 var translatedReferred = translate(target);
130 var polarity = callAtom.getPolarity(); 128 var polarity = callAtom.getPolarity();
131 if (polarity instanceof SimplePolarity simplePolarity) { 129 switch (polarity) {
132 switch (simplePolarity) { 130 case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred);
133 case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred); 131 case TRANSITIVE -> new BinaryTransitiveClosure(body, variablesTuple, translatedReferred);
134 case TRANSITIVE -> new BinaryTransitiveClosure(body, variablesTuple, translatedReferred); 132 case NEGATIVE -> new NegativePatternCall(body, variablesTuple, translatedReferred);
135 case NEGATIVE -> new NegativePatternCall(body, variablesTuple, translatedReferred); 133 default -> throw new IllegalArgumentException("Unknown polarity: " + polarity);
136 default -> throw new IllegalArgumentException("Unknown BasicCallKind: " + simplePolarity);
137 }
138 } else if (polarity instanceof CountingPolarity countingPolarity) {
139 var countVariableName = DNFUtils.generateUniqueName("count");
140 var countPVariable = body.getOrCreateVariableByName(countVariableName);
141 new PatternMatchCounter(body, variablesTuple, translatedReferred, countPVariable);
142 new ExpressionEvaluation(body, new CountExpressionEvaluator(countVariableName, countingPolarity), null);
143 } else {
144 throw new IllegalArgumentException("Unknown CallKind: " + polarity);
145 } 134 }
146 } 135 }
147 136
@@ -149,20 +138,4 @@ public class DNF2PQuery {
149 var variable = body.getOrCreateVariableByName(constantAtom.variable().getUniqueName()); 138 var variable = body.getOrCreateVariableByName(constantAtom.variable().getUniqueName());
150 new ConstantValue(body, variable, constantAtom.nodeId()); 139 new ConstantValue(body, variable, constantAtom.nodeId());
151 } 140 }
152
153 private void translateCountNotEqualsAtom(CountNotEqualsAtom<?> countNotEqualsAtom, PBody body) {
154 if (!(countNotEqualsAtom.mayTarget() instanceof DNF mayTarget) ||
155 !(countNotEqualsAtom.mustTarget() instanceof DNF mustTarget)) {
156 throw new IllegalArgumentException("Only calls to DNF are supported");
157 }
158 var variablesTuple = translateSubstitution(countNotEqualsAtom.substitution(), body);
159 var mayCountName = DNFUtils.generateUniqueName("countMay");
160 var mayCountVariable = body.getOrCreateVariableByName(mayCountName);
161 new PatternMatchCounter(body, variablesTuple, translate(mayTarget), mayCountVariable);
162 var mustCountName = DNFUtils.generateUniqueName("countMust");
163 var mustCountVariable = body.getOrCreateVariableByName(mustCountName);
164 new PatternMatchCounter(body, variablesTuple, translate(mustTarget), mustCountVariable);
165 new ExpressionEvaluation(body, new CountNotEqualsExpressionEvaluator(countNotEqualsAtom.must(),
166 countNotEqualsAtom.threshold(), mayCountName, mustCountName), null);
167 }
168} 141}
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
index d18187e5..e82e006c 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
@@ -5,7 +5,6 @@ import tools.refinery.store.model.representation.Relation;
5import tools.refinery.store.model.representation.TruthValue; 5import tools.refinery.store.model.representation.TruthValue;
6import tools.refinery.store.query.*; 6import tools.refinery.store.query.*;
7import tools.refinery.store.query.atom.*; 7import tools.refinery.store.query.atom.*;
8import tools.refinery.store.query.viatra.ViatraQueryableModelStore;
9import tools.refinery.store.query.view.FilteredRelationView; 8import tools.refinery.store.query.view.FilteredRelationView;
10import tools.refinery.store.query.view.KeyOnlyRelationView; 9import tools.refinery.store.query.view.KeyOnlyRelationView;
11import tools.refinery.store.query.view.RelationView; 10import tools.refinery.store.query.view.RelationView;
@@ -438,7 +437,7 @@ class QueryTest {
438 .clause( 437 .clause(
439 new RelationViewAtom(personView, p3), 438 new RelationViewAtom(personView, p3),
440 new RelationViewAtom(personView, p4), 439 new RelationViewAtom(personView, p4),
441 new CallAtom<>(SimplePolarity.TRANSITIVE, friendPredicate, p3, p4) 440 new CallAtom<>(CallPolarity.TRANSITIVE, friendPredicate, p3, p4)
442 ) 441 )
443 .build(); 442 .build();
444 443
@@ -456,48 +455,6 @@ class QueryTest {
456 assertEquals(3, model.countResults(predicate)); 455 assertEquals(3, model.countResults(predicate));
457 } 456 }
458 457
459 @Test
460 void countMatchTest() {
461 Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false);
462 Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE);
463 RelationView<Boolean> personView = new KeyOnlyRelationView(person);
464 RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must",
465 TruthValue::must);
466
467 Variable p1 = new Variable("p1");
468 Variable p2 = new Variable("p2");
469
470 DNF called = DNF.builder("Called")
471 .parameters(p1, p2)
472 .clause(
473 new RelationViewAtom(personView, p1),
474 new RelationViewAtom(personView, p2),
475 new RelationViewAtom(friendMustView, p1, p2)
476 )
477 .build();
478
479 DNF predicate = DNF.builder("Count")
480 .parameters(p1)
481 .clause(
482 new RelationViewAtom(personView, p1),
483 new CallAtom<>(new CountingPolarity(ComparisonOperator.EQUALS, 2), called, p1, p2)
484 )
485 .build();
486
487 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
488 Set.of(personView, friendMustView), Set.of(called, predicate));
489 QueryableModel model = store.createModel();
490
491 model.put(person, Tuple.of(0), true);
492 model.put(person, Tuple.of(1), true);
493 model.put(person, Tuple.of(2), true);
494 model.put(friend, Tuple.of(0, 1), TruthValue.TRUE);
495 model.put(friend, Tuple.of(0, 2), TruthValue.TRUE);
496
497 model.flushChanges();
498 assertEquals(1, model.countResults(predicate));
499 }
500
501 static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) { 458 static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) {
502 Set<Tuple> translatedMatchSet = new HashSet<>(); 459 Set<Tuple> translatedMatchSet = new HashSet<>();
503 var iterator = matchSet.iterator(); 460 var iterator = matchSet.iterator();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java
index 2ab2b6d2..957e9b7b 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java
@@ -1,11 +1,28 @@
1package tools.refinery.store.query.atom; 1package tools.refinery.store.query.atom;
2 2
3public sealed interface CallPolarity permits SimplePolarity, CountingPolarity { 3public enum CallPolarity {
4 boolean isPositive(); 4 POSITIVE(true, false),
5 NEGATIVE(false, false),
6 TRANSITIVE(true, true);
5 7
6 boolean isTransitive(); 8 private final boolean positive;
7 9
8 static CallPolarity fromBoolean(boolean positive) { 10 private final boolean transitive;
9 return positive ? SimplePolarity.POSITIVE : SimplePolarity.NEGATIVE; 11
12 CallPolarity(boolean positive, boolean transitive) {
13 this.positive = positive;
14 this.transitive = transitive;
15 }
16
17 public boolean isPositive() {
18 return positive;
19 }
20
21 public boolean isTransitive() {
22 return transitive;
23 }
24
25 public static CallPolarity fromBoolean(boolean positive) {
26 return positive ? POSITIVE : NEGATIVE;
10 } 27 }
11} 28}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ComparisonOperator.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ComparisonOperator.java
deleted file mode 100644
index ca113181..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ComparisonOperator.java
+++ /dev/null
@@ -1,22 +0,0 @@
1package tools.refinery.store.query.atom;
2
3public enum ComparisonOperator {
4 EQUALS,
5 NOT_EQUALS,
6 LESS,
7 LESS_EQUALS,
8 GREATER,
9 GREATER_EQUALS;
10
11 @Override
12 public String toString() {
13 return switch (this) {
14 case EQUALS -> "==";
15 case NOT_EQUALS -> "!=";
16 case LESS -> "<";
17 case LESS_EQUALS -> "<=";
18 case GREATER -> ">";
19 case GREATER_EQUALS -> ">=";
20 };
21 }
22}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountNotEqualsAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountNotEqualsAtom.java
deleted file mode 100644
index 312e5fb8..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountNotEqualsAtom.java
+++ /dev/null
@@ -1,31 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.model.RelationLike;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7import java.util.Set;
8
9public record CountNotEqualsAtom<T extends RelationLike>(boolean must, int threshold, T mayTarget, T mustTarget,
10 List<Variable> substitution) implements DNFAtom {
11 public CountNotEqualsAtom {
12 if (substitution.size() != mayTarget.getArity()) {
13 throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(mayTarget.getName(),
14 mayTarget.getArity(), substitution.size()));
15 }
16 if (substitution.size() != mustTarget.getArity()) {
17 throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(mustTarget.getName(),
18 mustTarget.getArity(), substitution.size()));
19 }
20 }
21
22 public CountNotEqualsAtom(boolean must, int threshold, T mayTarget, T mustTarget, Variable... substitution) {
23 this(must, threshold, mayTarget, mustTarget, List.of(substitution));
24 }
25
26 @Override
27 public void collectAllVariables(Set<Variable> variables) {
28 // No variables to collect, because all variables should either appear in other clauses,
29 // or are quantified by this clause.
30 }
31}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountingPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountingPolarity.java
deleted file mode 100644
index 08a62f4f..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CountingPolarity.java
+++ /dev/null
@@ -1,13 +0,0 @@
1package tools.refinery.store.query.atom;
2
3public record CountingPolarity(ComparisonOperator operator, int threshold) implements CallPolarity {
4 @Override
5 public boolean isPositive() {
6 return false;
7 }
8
9 @Override
10 public boolean isTransitive() {
11 return false;
12 }
13}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/SimplePolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/SimplePolarity.java
deleted file mode 100644
index d243bf26..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/SimplePolarity.java
+++ /dev/null
@@ -1,26 +0,0 @@
1package tools.refinery.store.query.atom;
2
3public enum SimplePolarity implements CallPolarity {
4 POSITIVE(true, false),
5 NEGATIVE(false, false),
6 TRANSITIVE(true, true);
7
8 private final boolean positive;
9
10 private final boolean transitive;
11
12 SimplePolarity(boolean positive, boolean transitive) {
13 this.positive = positive;
14 this.transitive = transitive;
15 }
16
17 @Override
18 public boolean isPositive() {
19 return positive;
20 }
21
22 @Override
23 public boolean isTransitive() {
24 return transitive;
25 }
26}