diff options
Diffstat (limited to 'subprojects/store-query-viatra/src')
5 files changed, 6 insertions, 151 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 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.pquery; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; | ||
5 | import tools.refinery.store.query.atom.ComparisonOperator; | ||
6 | import tools.refinery.store.query.atom.CountingPolarity; | ||
7 | |||
8 | import java.util.List; | ||
9 | |||
10 | public 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 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.pquery; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | public 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; | |||
5 | import tools.refinery.store.model.representation.TruthValue; | 5 | import tools.refinery.store.model.representation.TruthValue; |
6 | import tools.refinery.store.query.*; | 6 | import tools.refinery.store.query.*; |
7 | import tools.refinery.store.query.atom.*; | 7 | import tools.refinery.store.query.atom.*; |
8 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; | ||
9 | import tools.refinery.store.query.view.FilteredRelationView; | 8 | import tools.refinery.store.query.view.FilteredRelationView; |
10 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 9 | import tools.refinery.store.query.view.KeyOnlyRelationView; |
11 | import tools.refinery.store.query.view.RelationView; | 10 | import 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(); |