aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-24 20:21:15 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-24 23:29:49 +0100
commitf8a3c575e400259a4985233c07b7a50e5d4d82c5 (patch)
treef5975a19fcce28eba17b5af8adde5a37ddba83c6 /subprojects/store-query-viatra
parentrefactor: split query and partial from store (diff)
downloadrefinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.tar.gz
refinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.tar.zst
refinery-f8a3c575e400259a4985233c07b7a50e5d4d82c5.zip
feat: Dnf reduction and structural equality
Diffstat (limited to 'subprojects/store-query-viatra')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java9
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java29
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java19
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java40
4 files changed, 83 insertions, 14 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
index e5d8e2f6..e0341598 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java
@@ -8,6 +8,7 @@ import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; 8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
9import tools.refinery.store.model.Model; 9import tools.refinery.store.model.Model;
10import tools.refinery.store.query.Dnf; 10import tools.refinery.store.query.Dnf;
11import tools.refinery.store.query.EmptyResultSet;
11import tools.refinery.store.query.ResultSet; 12import tools.refinery.store.query.ResultSet;
12import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; 13import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
13 14
@@ -15,7 +16,7 @@ import java.lang.invoke.MethodHandle;
15import java.lang.invoke.MethodHandles; 16import java.lang.invoke.MethodHandles;
16import java.util.Collection; 17import java.util.Collection;
17import java.util.Collections; 18import java.util.Collections;
18import java.util.HashMap; 19import java.util.LinkedHashMap;
19import java.util.Map; 20import java.util.Map;
20 21
21public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter { 22public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
@@ -51,11 +52,15 @@ public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
51 GenericQueryGroup.of( 52 GenericQueryGroup.of(
52 Collections.<IQuerySpecification<?>>unmodifiableCollection(querySpecifications.values()).stream() 53 Collections.<IQuerySpecification<?>>unmodifiableCollection(querySpecifications.values()).stream()
53 ).prepare(queryEngine); 54 ).prepare(queryEngine);
54 resultSets = new HashMap<>(querySpecifications.size()); 55 var vacuousQueries = storeAdapter.getVacuousQueries();
56 resultSets = new LinkedHashMap<>(querySpecifications.size() + vacuousQueries.size());
55 for (var entry : querySpecifications.entrySet()) { 57 for (var entry : querySpecifications.entrySet()) {
56 var matcher = queryEngine.getMatcher(entry.getValue()); 58 var matcher = queryEngine.getMatcher(entry.getValue());
57 resultSets.put(entry.getKey(), matcher); 59 resultSets.put(entry.getKey(), matcher);
58 } 60 }
61 for (var vacuousQuery : vacuousQueries) {
62 resultSets.put(vacuousQuery, new EmptyResultSet());
63 }
59 64
60 setUpdatePropagationDelayed(true); 65 setUpdatePropagationDelayed(true);
61 } 66 }
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
index af20033a..13641ace 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
@@ -14,14 +14,13 @@ import tools.refinery.store.query.viatra.ViatraModelQueryBuilder;
14import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery; 14import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery;
15import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher; 15import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher;
16 16
17import java.util.Collections; 17import java.util.*;
18import java.util.LinkedHashMap;
19import java.util.Map;
20import java.util.function.Function; 18import java.util.function.Function;
21 19
22public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder implements ViatraModelQueryBuilder { 20public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder implements ViatraModelQueryBuilder {
23 private ViatraQueryEngineOptions.Builder engineOptionsBuilder; 21 private ViatraQueryEngineOptions.Builder engineOptionsBuilder;
24 private final Dnf2PQuery dnf2PQuery = new Dnf2PQuery(); 22 private final Dnf2PQuery dnf2PQuery = new Dnf2PQuery();
23 private final Set<Dnf> vacuousQueries = new LinkedHashSet<>();
25 private final Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>(); 24 private final Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>();
26 25
27 public ViatraModelQueryBuilderImpl(ModelStoreBuilder storeBuilder) { 26 public ViatraModelQueryBuilderImpl(ModelStoreBuilder storeBuilder) {
@@ -64,11 +63,21 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp
64 63
65 @Override 64 @Override
66 public ViatraModelQueryBuilder query(Dnf query) { 65 public ViatraModelQueryBuilder query(Dnf query) {
67 if (querySpecifications.containsKey(query)) { 66 if (querySpecifications.containsKey(query) || vacuousQueries.contains(query)) {
68 throw new IllegalArgumentException("%s was already added to the query engine".formatted(query.name())); 67 // Ignore duplicate queries.
68 return this;
69 }
70 var reduction = query.getReduction();
71 switch (reduction) {
72 case NOT_REDUCIBLE -> {
73 var pQuery = dnf2PQuery.translate(query);
74 querySpecifications.put(query, pQuery.build());
75 }
76 case ALWAYS_FALSE -> vacuousQueries.add(query);
77 case ALWAYS_TRUE -> throw new IllegalArgumentException(
78 "Query %s is relationally unsafe (it matches every tuple)".formatted(query.name()));
79 default -> throw new IllegalArgumentException("Unknown reduction: " + reduction);
69 } 80 }
70 var pQuery = dnf2PQuery.translate(query);
71 querySpecifications.put(query, pQuery.build());
72 return this; 81 return this;
73 } 82 }
74 83
@@ -89,6 +98,10 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp
89 public ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint) { 98 public ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint) {
90 var pQuery = dnf2PQuery.getAlreadyTranslated(dnf); 99 var pQuery = dnf2PQuery.getAlreadyTranslated(dnf);
91 if (pQuery == null) { 100 if (pQuery == null) {
101 if (vacuousQueries.contains(dnf)) {
102 // Ignore hits for queries that will never be executed by the query engine.
103 return this;
104 }
92 throw new IllegalArgumentException( 105 throw new IllegalArgumentException(
93 "Cannot specify hint for %s, because it was not added to the query engine".formatted(dnf.name())); 106 "Cannot specify hint for %s, because it was not added to the query engine".formatted(dnf.name()));
94 } 107 }
@@ -100,7 +113,7 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp
100 public ViatraModelQueryStoreAdapterImpl createStoreAdapter(ModelStore store) { 113 public ViatraModelQueryStoreAdapterImpl createStoreAdapter(ModelStore store) {
101 validateSymbols(store); 114 validateSymbols(store);
102 return new ViatraModelQueryStoreAdapterImpl(store, engineOptionsBuilder.build(), dnf2PQuery.getRelationViews(), 115 return new ViatraModelQueryStoreAdapterImpl(store, engineOptionsBuilder.build(), dnf2PQuery.getRelationViews(),
103 Collections.unmodifiableMap(querySpecifications)); 116 Collections.unmodifiableMap(querySpecifications), Collections.unmodifiableSet(vacuousQueries));
104 } 117 }
105 118
106 private void validateSymbols(ModelStore store) { 119 private void validateSymbols(ModelStore store) {
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
index 8323118b..00660d0b 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java
@@ -10,22 +10,29 @@ import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter;
10import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher; 10import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher;
11import tools.refinery.store.query.view.AnyRelationView; 11import tools.refinery.store.query.view.AnyRelationView;
12 12
13import java.util.Collection; 13import java.util.*;
14import java.util.Map;
15 14
16public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAdapter { 15public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAdapter {
17 private final ModelStore store; 16 private final ModelStore store;
18 private final ViatraQueryEngineOptions engineOptions; 17 private final ViatraQueryEngineOptions engineOptions;
19 private final Map<AnyRelationView, IInputKey> inputKeys; 18 private final Map<AnyRelationView, IInputKey> inputKeys;
20 private final Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications; 19 private final Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications;
20 private final Set<Dnf> vacuousQueries;
21 private final Set<Dnf> allQueries;
21 22
22 ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions, 23 ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions,
23 Map<AnyRelationView, IInputKey> inputKeys, 24 Map<AnyRelationView, IInputKey> inputKeys,
24 Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications) { 25 Map<Dnf, IQuerySpecification<RawPatternMatcher>> querySpecifications,
26 Set<Dnf> vacuousQueries) {
25 this.store = store; 27 this.store = store;
26 this.engineOptions = engineOptions; 28 this.engineOptions = engineOptions;
27 this.inputKeys = inputKeys; 29 this.inputKeys = inputKeys;
28 this.querySpecifications = querySpecifications; 30 this.querySpecifications = querySpecifications;
31 this.vacuousQueries = vacuousQueries;
32 var mutableAllQueries = new LinkedHashSet<Dnf>(querySpecifications.size() + vacuousQueries.size());
33 mutableAllQueries.addAll(querySpecifications.keySet());
34 mutableAllQueries.addAll(vacuousQueries);
35 this.allQueries = Collections.unmodifiableSet(mutableAllQueries);
29 } 36 }
30 37
31 @Override 38 @Override
@@ -43,13 +50,17 @@ public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAd
43 50
44 @Override 51 @Override
45 public Collection<Dnf> getQueries() { 52 public Collection<Dnf> getQueries() {
46 return querySpecifications.keySet(); 53 return allQueries;
47 } 54 }
48 55
49 Map<Dnf, IQuerySpecification<RawPatternMatcher>> getQuerySpecifications() { 56 Map<Dnf, IQuerySpecification<RawPatternMatcher>> getQuerySpecifications() {
50 return querySpecifications; 57 return querySpecifications;
51 } 58 }
52 59
60 Set<Dnf> getVacuousQueries() {
61 return vacuousQueries;
62 }
63
53 @Override 64 @Override
54 public ViatraQueryEngineOptions getEngineOptions() { 65 public ViatraQueryEngineOptions getEngineOptions() {
55 return engineOptions; 66 return engineOptions;
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 6a3a62e3..54ae70c3 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
@@ -17,6 +17,7 @@ import java.util.Set;
17import java.util.stream.Stream; 17import java.util.stream.Stream;
18 18
19import static org.junit.jupiter.api.Assertions.assertEquals; 19import static org.junit.jupiter.api.Assertions.assertEquals;
20import static org.junit.jupiter.api.Assertions.assertThrows;
20import static tools.refinery.store.query.literal.Literals.not; 21import static tools.refinery.store.query.literal.Literals.not;
21 22
22class QueryTest { 23class QueryTest {
@@ -669,6 +670,45 @@ class QueryTest {
669 assertEquals(3, predicateResultSet.countResults()); 670 assertEquals(3, predicateResultSet.countResults());
670 } 671 }
671 672
673 @Test
674 void alwaysFalseTest() {
675 var person = new Symbol<>("Person", 1, Boolean.class, false);
676
677 var p1 = new Variable("p1");
678 var predicate = Dnf.builder("AlwaysFalse").parameters(p1).build();
679
680 var store = ModelStore.builder()
681 .symbols(person)
682 .with(ViatraModelQuery.ADAPTER)
683 .queries(predicate)
684 .build();
685
686 var model = store.createEmptyModel();
687 var personInterpretation = model.getInterpretation(person);
688 var queryEngine = model.getAdapter(ModelQuery.ADAPTER);
689 var predicateResultSet = queryEngine.getResultSet(predicate);
690
691 personInterpretation.put(Tuple.of(0), true);
692 personInterpretation.put(Tuple.of(1), true);
693 personInterpretation.put(Tuple.of(2), true);
694
695 queryEngine.flushChanges();
696 assertEquals(0, predicateResultSet.countResults());
697 }
698
699 @Test
700 void alwaysTrueTest() {
701 var person = new Symbol<>("Person", 1, Boolean.class, false);
702
703 var p1 = new Variable("p1");
704 var predicate = Dnf.builder("AlwaysTrue").parameters(p1).clause().build();
705
706 var storeBuilder = ModelStore.builder().symbols(person);
707 var queryBuilder = storeBuilder.with(ViatraModelQuery.ADAPTER);
708
709 assertThrows(IllegalArgumentException.class, () -> queryBuilder.queries(predicate));
710 }
711
672 static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) { 712 static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) {
673 Set<Tuple> translatedMatchSet = new HashSet<>(); 713 Set<Tuple> translatedMatchSet = new HashSet<>();
674 var iterator = matchSet.iterator(); 714 var iterator = matchSet.iterator();