aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-06-29 02:08:40 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-06-29 02:22:13 +0200
commit8d79e7f39df0fde9b4f0ba8e6264f2900e9024c6 (patch)
tree9cc6850dba18ed526eb27a911bc3f73b28752a14 /subprojects/store-query-viatra
parentfix: FilteredView default value (diff)
downloadrefinery-8d79e7f39df0fde9b4f0ba8e6264f2900e9024c6.tar.gz
refinery-8d79e7f39df0fde9b4f0ba8e6264f2900e9024c6.tar.zst
refinery-8d79e7f39df0fde9b4f0ba8e6264f2900e9024c6.zip
feat: ordered query ResultSet
Enable deterministic state-space exploration by ordering activations in lexicographic order. This preliminary implementation adds oredering as a wrapper for ResultSet instances, but more sophisticated support could be built directly into query engine adapters if a query engine supports deterministic output by default. * Implements Comparable for tuples with loops unrolled for small tuples by hand. * Cleans up the contents of the (root of the) tools.refinery.query package. * Adds ResultSetListener to notify clients about ResultSet changes. * Adds OrderStatisticTree data structure for determinisitc ordering of keys.
Diffstat (limited to 'subprojects/store-query-viatra')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java6
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/AbstractViatraMatcher.java32
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java34
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java10
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java29
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java4
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/OrderedResultSetTest.java117
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java2
8 files changed, 183 insertions, 51 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 7103a561..5f3e86b4 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
@@ -13,9 +13,9 @@ import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend;
13import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; 13import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
14import tools.refinery.store.model.Model; 14import tools.refinery.store.model.Model;
15import tools.refinery.store.model.ModelListener; 15import tools.refinery.store.model.ModelListener;
16import tools.refinery.store.query.AnyResultSet; 16import tools.refinery.store.query.resultset.AnyResultSet;
17import tools.refinery.store.query.EmptyResultSet; 17import tools.refinery.store.query.resultset.EmptyResultSet;
18import tools.refinery.store.query.ResultSet; 18import tools.refinery.store.query.resultset.ResultSet;
19import tools.refinery.store.query.dnf.AnyQuery; 19import tools.refinery.store.query.dnf.AnyQuery;
20import tools.refinery.store.query.dnf.FunctionalQuery; 20import tools.refinery.store.query.dnf.FunctionalQuery;
21import tools.refinery.store.query.dnf.Query; 21import tools.refinery.store.query.dnf.Query;
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/AbstractViatraMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/AbstractViatraMatcher.java
new file mode 100644
index 00000000..99b0a3d8
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/AbstractViatraMatcher.java
@@ -0,0 +1,32 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.matcher;
7
8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
9import org.eclipse.viatra.query.runtime.matchers.backend.IUpdateable;
10import tools.refinery.store.query.dnf.Query;
11import tools.refinery.store.query.resultset.AbstractResultSet;
12import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
13
14public abstract class AbstractViatraMatcher<T> extends AbstractResultSet<T> implements IUpdateable {
15 protected final IQueryResultProvider backend;
16
17 protected AbstractViatraMatcher(ViatraModelQueryAdapterImpl adapter, Query<T> query,
18 RawPatternMatcher rawPatternMatcher) {
19 super(adapter, query);
20 backend = rawPatternMatcher.getBackend();
21 }
22
23 @Override
24 protected void startListeningForChanges() {
25 backend.addUpdateListener(this, this, false);
26 }
27
28 @Override
29 protected void stopListeningForChanges() {
30 backend.removeUpdateListener(this);
31 }
32}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java
index f018288b..db4740cd 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java
@@ -5,16 +5,12 @@
5 */ 5 */
6package tools.refinery.store.query.viatra.internal.matcher; 6package tools.refinery.store.query.viatra.internal.matcher;
7 7
8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
9import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; 8import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
10import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 9import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
11import org.eclipse.viatra.query.runtime.rete.index.IterableIndexer; 10import org.eclipse.viatra.query.runtime.rete.index.IterableIndexer;
12import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher; 11import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher;
13import tools.refinery.store.map.Cursor; 12import tools.refinery.store.map.Cursor;
14import tools.refinery.store.query.ModelQueryAdapter;
15import tools.refinery.store.query.ResultSet;
16import tools.refinery.store.query.dnf.FunctionalQuery; 13import tools.refinery.store.query.dnf.FunctionalQuery;
17import tools.refinery.store.query.dnf.Query;
18import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; 14import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
19import tools.refinery.store.tuple.Tuple; 15import tools.refinery.store.tuple.Tuple;
20 16
@@ -28,23 +24,18 @@ import tools.refinery.store.tuple.Tuple;
28 * implementation for these methods. 24 * implementation for these methods.
29 * Using this class with any other runtime context may lead to undefined behavior. 25 * Using this class with any other runtime context may lead to undefined behavior.
30 */ 26 */
31public class FunctionalViatraMatcher<T> implements ResultSet<T> { 27public class FunctionalViatraMatcher<T> extends AbstractViatraMatcher<T> {
32 private final ViatraModelQueryAdapterImpl adapter;
33 private final FunctionalQuery<T> query;
34 private final TupleMask emptyMask; 28 private final TupleMask emptyMask;
35 private final TupleMask omitOutputMask; 29 private final TupleMask omitOutputMask;
36 private final IQueryResultProvider backend;
37 private final IterableIndexer omitOutputIndexer; 30 private final IterableIndexer omitOutputIndexer;
38 31
39 public FunctionalViatraMatcher(ViatraModelQueryAdapterImpl adapter, FunctionalQuery<T> query, 32 public FunctionalViatraMatcher(ViatraModelQueryAdapterImpl adapter, FunctionalQuery<T> query,
40 RawPatternMatcher rawPatternMatcher) { 33 RawPatternMatcher rawPatternMatcher) {
41 this.adapter = adapter; 34 super(adapter, query, rawPatternMatcher);
42 this.query = query;
43 int arity = query.arity(); 35 int arity = query.arity();
44 int arityWithOutput = arity + 1; 36 int arityWithOutput = arity + 1;
45 emptyMask = TupleMask.empty(arityWithOutput); 37 emptyMask = TupleMask.empty(arityWithOutput);
46 omitOutputMask = TupleMask.omit(arity, arityWithOutput); 38 omitOutputMask = TupleMask.omit(arity, arityWithOutput);
47 backend = rawPatternMatcher.getBackend();
48 if (backend instanceof RetePatternMatcher reteBackend) { 39 if (backend instanceof RetePatternMatcher reteBackend) {
49 var maybeIterableOmitOutputIndexer = IndexerUtils.getIndexer(reteBackend, omitOutputMask); 40 var maybeIterableOmitOutputIndexer = IndexerUtils.getIndexer(reteBackend, omitOutputMask);
50 if (maybeIterableOmitOutputIndexer instanceof IterableIndexer iterableOmitOutputIndexer) { 41 if (maybeIterableOmitOutputIndexer instanceof IterableIndexer iterableOmitOutputIndexer) {
@@ -58,16 +49,6 @@ public class FunctionalViatraMatcher<T> implements ResultSet<T> {
58 } 49 }
59 50
60 @Override 51 @Override
61 public ModelQueryAdapter getAdapter() {
62 return adapter;
63 }
64
65 @Override
66 public Query<T> getQuery() {
67 return query;
68 }
69
70 @Override
71 public T get(Tuple parameters) { 52 public T get(Tuple parameters) {
72 var tuple = MatcherUtils.toViatraTuple(parameters); 53 var tuple = MatcherUtils.toViatraTuple(parameters);
73 if (omitOutputIndexer == null) { 54 if (omitOutputIndexer == null) {
@@ -93,4 +74,15 @@ public class FunctionalViatraMatcher<T> implements ResultSet<T> {
93 } 74 }
94 return omitOutputIndexer.getBucketCount(); 75 return omitOutputIndexer.getBucketCount();
95 } 76 }
77
78 @Override
79 public void update(org.eclipse.viatra.query.runtime.matchers.tuple.Tuple updateElement, boolean isInsertion) {
80 var key = MatcherUtils.keyToRefineryTuple(updateElement);
81 var value = MatcherUtils.<T>getValue(updateElement);
82 if (isInsertion) {
83 notifyChange(key, null, value);
84 } else {
85 notifyChange(key, value, null);
86 }
87 }
96} 88}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java
index 1c784492..6e24812a 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java
@@ -86,6 +86,13 @@ final class MatcherUtils {
86 return getWrapper(viatraTuple, index).value0(); 86 return getWrapper(viatraTuple, index).value0();
87 } 87 }
88 88
89 public static <T> T getValue(ITuple match) {
90 // This is only safe if we know for sure that match came from a functional query of type {@code T}.
91 @SuppressWarnings("unchecked")
92 var result = (T) match.get(match.getSize() - 1);
93 return result;
94 }
95
89 public static <T> T getSingleValue(@Nullable Iterable<? extends ITuple> viatraTuples) { 96 public static <T> T getSingleValue(@Nullable Iterable<? extends ITuple> viatraTuples) {
90 if (viatraTuples == null) { 97 if (viatraTuples == null) {
91 return null; 98 return null;
@@ -98,8 +105,7 @@ final class MatcherUtils {
98 return null; 105 return null;
99 } 106 }
100 var match = iterator.next(); 107 var match = iterator.next();
101 @SuppressWarnings("unchecked") 108 var result = MatcherUtils.<T>getValue(match);
102 var result = (T) match.get(match.getSize() - 1);
103 if (iterator.hasNext()) { 109 if (iterator.hasNext()) {
104 var input = keyToRefineryTuple(match); 110 var input = keyToRefineryTuple(match);
105 throw new IllegalStateException("Query is not functional for input tuple: " + input); 111 throw new IllegalStateException("Query is not functional for input tuple: " + input);
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java
index d1476920..ac95dcc0 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java
@@ -5,16 +5,12 @@
5 */ 5 */
6package tools.refinery.store.query.viatra.internal.matcher; 6package tools.refinery.store.query.viatra.internal.matcher;
7 7
8import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
9import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; 8import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
10import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 9import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
11import org.eclipse.viatra.query.runtime.rete.index.Indexer; 10import org.eclipse.viatra.query.runtime.rete.index.Indexer;
12import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher; 11import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher;
13import tools.refinery.store.map.Cursor; 12import tools.refinery.store.map.Cursor;
14import tools.refinery.store.map.Cursors; 13import tools.refinery.store.map.Cursors;
15import tools.refinery.store.query.ModelQueryAdapter;
16import tools.refinery.store.query.ResultSet;
17import tools.refinery.store.query.dnf.Query;
18import tools.refinery.store.query.dnf.RelationalQuery; 14import tools.refinery.store.query.dnf.RelationalQuery;
19import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; 15import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl;
20import tools.refinery.store.tuple.Tuple; 16import tools.refinery.store.tuple.Tuple;
@@ -29,22 +25,17 @@ import tools.refinery.store.tuple.Tuple;
29 * implementation for these methods. 25 * implementation for these methods.
30 * Using this class with any other runtime context may lead to undefined behavior. 26 * Using this class with any other runtime context may lead to undefined behavior.
31 */ 27 */
32public class RelationalViatraMatcher implements ResultSet<Boolean> { 28public class RelationalViatraMatcher extends AbstractViatraMatcher<Boolean> {
33 private final ViatraModelQueryAdapterImpl adapter;
34 private final RelationalQuery query;
35 private final TupleMask emptyMask; 29 private final TupleMask emptyMask;
36 private final TupleMask identityMask; 30 private final TupleMask identityMask;
37 private final IQueryResultProvider backend;
38 private final Indexer emptyMaskIndexer; 31 private final Indexer emptyMaskIndexer;
39 32
40 public RelationalViatraMatcher(ViatraModelQueryAdapterImpl adapter, RelationalQuery query, 33 public RelationalViatraMatcher(ViatraModelQueryAdapterImpl adapter, RelationalQuery query,
41 RawPatternMatcher rawPatternMatcher) { 34 RawPatternMatcher rawPatternMatcher) {
42 this.adapter = adapter; 35 super(adapter, query, rawPatternMatcher);
43 this.query = query;
44 int arity = query.arity(); 36 int arity = query.arity();
45 emptyMask = TupleMask.empty(arity); 37 emptyMask = TupleMask.empty(arity);
46 identityMask = TupleMask.identity(arity); 38 identityMask = TupleMask.identity(arity);
47 backend = rawPatternMatcher.getBackend();
48 if (backend instanceof RetePatternMatcher reteBackend) { 39 if (backend instanceof RetePatternMatcher reteBackend) {
49 emptyMaskIndexer = IndexerUtils.getIndexer(reteBackend, emptyMask); 40 emptyMaskIndexer = IndexerUtils.getIndexer(reteBackend, emptyMask);
50 } else { 41 } else {
@@ -53,16 +44,6 @@ public class RelationalViatraMatcher implements ResultSet<Boolean> {
53 } 44 }
54 45
55 @Override 46 @Override
56 public ModelQueryAdapter getAdapter() {
57 return adapter;
58 }
59
60 @Override
61 public Query<Boolean> getQuery() {
62 return query;
63 }
64
65 @Override
66 public Boolean get(Tuple parameters) { 47 public Boolean get(Tuple parameters) {
67 var tuple = MatcherUtils.toViatraTuple(parameters); 48 var tuple = MatcherUtils.toViatraTuple(parameters);
68 if (emptyMaskIndexer == null) { 49 if (emptyMaskIndexer == null) {
@@ -90,4 +71,10 @@ public class RelationalViatraMatcher implements ResultSet<Boolean> {
90 var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf()); 71 var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf());
91 return matches == null ? 0 : matches.size(); 72 return matches == null ? 0 : matches.size();
92 } 73 }
74
75 @Override
76 public void update(org.eclipse.viatra.query.runtime.matchers.tuple.Tuple updateElement, boolean isInsertion) {
77 var key = MatcherUtils.toRefineryTuple(updateElement);
78 notifyChange(key, !isInsertion, isInsertion);
79 }
93} 80}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java
index 4a41d724..b0b507fe 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java
@@ -46,9 +46,7 @@ class UnsafeFunctionalCursor<T> implements Cursor<Tuple, T> {
46 if (!terminated && tuplesIterator.hasNext()) { 46 if (!terminated && tuplesIterator.hasNext()) {
47 var match = tuplesIterator.next(); 47 var match = tuplesIterator.next();
48 key = MatcherUtils.keyToRefineryTuple(match); 48 key = MatcherUtils.keyToRefineryTuple(match);
49 @SuppressWarnings("unchecked") 49 value = MatcherUtils.getValue(match);
50 var typedValue = (T) match.get(match.getSize() - 1);
51 value = typedValue;
52 return true; 50 return true;
53 } 51 }
54 terminated = true; 52 terminated = true;
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/OrderedResultSetTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/OrderedResultSetTest.java
new file mode 100644
index 00000000..8ede6c80
--- /dev/null
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/OrderedResultSetTest.java
@@ -0,0 +1,117 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra;
7
8import org.junit.jupiter.api.Test;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query;
12import tools.refinery.store.query.resultset.OrderedResultSet;
13import tools.refinery.store.query.term.Variable;
14import tools.refinery.store.query.view.AnySymbolView;
15import tools.refinery.store.query.view.KeyOnlyView;
16import tools.refinery.store.representation.Symbol;
17import tools.refinery.store.tuple.Tuple;
18
19import static org.hamcrest.MatcherAssert.assertThat;
20import static org.hamcrest.Matchers.is;
21
22class OrderedResultSetTest {
23 private static final Symbol<Boolean> friend = Symbol.of("friend", 2);
24 private static final AnySymbolView friendView = new KeyOnlyView<>(friend);
25
26 @Test
27 void relationalFlushTest() {
28 var query = Query.of("Relation", (builder, p1, p2) -> builder.clause(
29 friendView.call(p1, p2)
30 ));
31
32 var store = ModelStore.builder()
33 .symbols(friend)
34 .with(ViatraModelQueryAdapter.builder()
35 .queries(query))
36 .build();
37
38 var model = store.createEmptyModel();
39 var friendInterpretation = model.getInterpretation(friend);
40 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
41 var resultSet = queryEngine.getResultSet(query);
42
43 friendInterpretation.put(Tuple.of(0, 1), true);
44 friendInterpretation.put(Tuple.of(1, 2), true);
45 friendInterpretation.put(Tuple.of(1, 1), true);
46 queryEngine.flushChanges();
47
48 try (var orderedResultSet = new OrderedResultSet<>(resultSet)) {
49 assertThat(orderedResultSet.size(), is(3));
50 assertThat(orderedResultSet.getKey(0), is(Tuple.of(0, 1)));
51 assertThat(orderedResultSet.getKey(1), is(Tuple.of(1, 1)));
52 assertThat(orderedResultSet.getKey(2), is(Tuple.of(1, 2)));
53
54 friendInterpretation.put(Tuple.of(1, 2), false);
55 friendInterpretation.put(Tuple.of(0, 2), true);
56 queryEngine.flushChanges();
57
58 assertThat(orderedResultSet.size(), is(3));
59 assertThat(orderedResultSet.getKey(0), is(Tuple.of(0, 1)));
60 assertThat(orderedResultSet.getKey(1), is(Tuple.of(0, 2)));
61 assertThat(orderedResultSet.getKey(2), is(Tuple.of(1, 1)));
62 }
63 }
64
65 @Test
66 void functionalFlushTest() {
67 var query = Query.of("Function", Integer.class, (builder, p1, output) -> builder.clause(
68 friendView.call(p1, Variable.of()),
69 output.assign(friendView.count(p1, Variable.of()))
70 ));
71
72 var store = ModelStore.builder()
73 .symbols(friend)
74 .with(ViatraModelQueryAdapter.builder()
75 .queries(query))
76 .build();
77
78 var model = store.createEmptyModel();
79 var friendInterpretation = model.getInterpretation(friend);
80 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
81 var resultSet = queryEngine.getResultSet(query);
82
83 friendInterpretation.put(Tuple.of(0, 1), true);
84 friendInterpretation.put(Tuple.of(1, 2), true);
85 friendInterpretation.put(Tuple.of(1, 1), true);
86 queryEngine.flushChanges();
87
88 try (var orderedResultSet = new OrderedResultSet<>(resultSet)) {
89 assertThat(orderedResultSet.size(), is(2));
90 assertThat(orderedResultSet.getKey(0), is(Tuple.of(0)));
91 assertThat(orderedResultSet.getKey(1), is(Tuple.of(1)));
92
93 friendInterpretation.put(Tuple.of(0, 1), false);
94 friendInterpretation.put(Tuple.of(2, 1), true);
95 queryEngine.flushChanges();
96
97 assertThat(orderedResultSet.size(), is(2));
98 assertThat(orderedResultSet.getKey(0), is(Tuple.of(1)));
99 assertThat(orderedResultSet.getKey(1), is(Tuple.of(2)));
100
101 friendInterpretation.put(Tuple.of(1, 1), false);
102 queryEngine.flushChanges();
103
104 assertThat(orderedResultSet.size(), is(2));
105 assertThat(orderedResultSet.getKey(0), is(Tuple.of(1)));
106 assertThat(orderedResultSet.getKey(1), is(Tuple.of(2)));
107
108 friendInterpretation.put(Tuple.of(1, 2), false);
109 friendInterpretation.put(Tuple.of(1, 0), true);
110 queryEngine.flushChanges();
111
112 assertThat(orderedResultSet.size(), is(2));
113 assertThat(orderedResultSet.getKey(0), is(Tuple.of(1)));
114 assertThat(orderedResultSet.getKey(1), is(Tuple.of(2)));
115 }
116 }
117}
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java
index 7a25cfdc..ca089a9d 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java
@@ -6,7 +6,7 @@
6package tools.refinery.store.query.viatra.tests; 6package tools.refinery.store.query.viatra.tests;
7 7
8import org.junit.jupiter.api.function.Executable; 8import org.junit.jupiter.api.function.Executable;
9import tools.refinery.store.query.ResultSet; 9import tools.refinery.store.query.resultset.ResultSet;
10import tools.refinery.store.tuple.Tuple; 10import tools.refinery.store.tuple.Tuple;
11 11
12import java.util.*; 12import java.util.*;