aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java29
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/IndexerUtils.java48
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java127
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java7
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java29
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java16
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java (renamed from subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Seed.java)2
7 files changed, 151 insertions, 107 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 e0341598..37700413 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
@@ -21,32 +21,37 @@ import java.util.Map;
21 21
22public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter { 22public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
23 private static final String DELAY_MESSAGE_DELIVERY_FIELD_NAME = "delayMessageDelivery"; 23 private static final String DELAY_MESSAGE_DELIVERY_FIELD_NAME = "delayMessageDelivery";
24 private static final MethodHandle SET_UPDATE_PROPAGATION_DELAYED_HANDLE;
24 private static final String QUERY_BACKENDS_FIELD_NAME = "queryBackends"; 25 private static final String QUERY_BACKENDS_FIELD_NAME = "queryBackends";
26 private static final MethodHandle GET_QUERY_BACKENDS_HANDLE;
25 27
26 private final Model model; 28 private final Model model;
27 private final ViatraModelQueryStoreAdapterImpl storeAdapter; 29 private final ViatraModelQueryStoreAdapterImpl storeAdapter;
28 private final ViatraQueryEngineImpl queryEngine; 30 private final ViatraQueryEngineImpl queryEngine;
29 private final MethodHandle setUpdatePropagationDelayedHandle; 31
30 private final MethodHandle getQueryBackendsHandle;
31 private final Map<Dnf, ResultSet> resultSets; 32 private final Map<Dnf, ResultSet> resultSets;
32 private boolean pendingChanges; 33 private boolean pendingChanges;
33 34
34 ViatraModelQueryAdapterImpl(Model model, ViatraModelQueryStoreAdapterImpl storeAdapter) { 35 static {
35 this.model = model;
36 this.storeAdapter = storeAdapter;
37 var scope = new RelationalScope(this);
38 queryEngine = (ViatraQueryEngineImpl) AdvancedViatraQueryEngine.createUnmanagedEngine(scope);
39
40 try { 36 try {
41 var lookup = MethodHandles.privateLookupIn(ViatraQueryEngineImpl.class, MethodHandles.lookup()); 37 var lookup = MethodHandles.privateLookupIn(ViatraQueryEngineImpl.class, MethodHandles.lookup());
42 setUpdatePropagationDelayedHandle = lookup.findSetter(ViatraQueryEngineImpl.class, 38 SET_UPDATE_PROPAGATION_DELAYED_HANDLE = lookup.findSetter(ViatraQueryEngineImpl.class,
43 DELAY_MESSAGE_DELIVERY_FIELD_NAME, Boolean.TYPE); 39 DELAY_MESSAGE_DELIVERY_FIELD_NAME, Boolean.TYPE);
44 getQueryBackendsHandle = lookup.findGetter(ViatraQueryEngineImpl.class, QUERY_BACKENDS_FIELD_NAME, 40 GET_QUERY_BACKENDS_HANDLE = lookup.findGetter(ViatraQueryEngineImpl.class, QUERY_BACKENDS_FIELD_NAME,
45 Map.class); 41 Map.class);
46 } catch (IllegalAccessException | NoSuchFieldException e) { 42 } catch (IllegalAccessException | NoSuchFieldException e) {
47 throw new IllegalStateException("Cannot access private members of %s" 43 throw new IllegalStateException("Cannot access private members of %s"
48 .formatted(ViatraQueryEngineImpl.class.getName()), e); 44 .formatted(ViatraQueryEngineImpl.class.getName()), e);
49 } 45 }
46 }
47
48 ViatraModelQueryAdapterImpl(Model model, ViatraModelQueryStoreAdapterImpl storeAdapter) {
49 this.model = model;
50 this.storeAdapter = storeAdapter;
51 var scope = new RelationalScope(this);
52 queryEngine = (ViatraQueryEngineImpl) AdvancedViatraQueryEngine.createUnmanagedEngine(scope);
53
54
50 55
51 var querySpecifications = storeAdapter.getQuerySpecifications(); 56 var querySpecifications = storeAdapter.getQuerySpecifications();
52 GenericQueryGroup.of( 57 GenericQueryGroup.of(
@@ -67,7 +72,7 @@ public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
67 72
68 private void setUpdatePropagationDelayed(boolean value) { 73 private void setUpdatePropagationDelayed(boolean value) {
69 try { 74 try {
70 setUpdatePropagationDelayedHandle.invokeExact(queryEngine, value); 75 SET_UPDATE_PROPAGATION_DELAYED_HANDLE.invokeExact(queryEngine, value);
71 } catch (Error e) { 76 } catch (Error e) {
72 // Fatal JVM errors should not be wrapped. 77 // Fatal JVM errors should not be wrapped.
73 throw e; 78 throw e;
@@ -79,7 +84,7 @@ public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter {
79 private Collection<IQueryBackend> getQueryBackends() { 84 private Collection<IQueryBackend> getQueryBackends() {
80 try { 85 try {
81 @SuppressWarnings("unchecked") 86 @SuppressWarnings("unchecked")
82 var backendMap = (Map<IQueryBackendFactory, IQueryBackend>) getQueryBackendsHandle.invokeExact(queryEngine); 87 var backendMap = (Map<IQueryBackendFactory, IQueryBackend>) GET_QUERY_BACKENDS_HANDLE.invokeExact(queryEngine);
83 return backendMap.values(); 88 return backendMap.values();
84 } catch (Error e) { 89 } catch (Error e) {
85 // Fatal JVM errors should not be wrapped. 90 // Fatal JVM errors should not be wrapped.
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/IndexerUtils.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/IndexerUtils.java
new file mode 100644
index 00000000..75588b81
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/IndexerUtils.java
@@ -0,0 +1,48 @@
1package tools.refinery.store.query.viatra.internal.pquery;
2
3import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
4import org.eclipse.viatra.query.runtime.rete.index.Indexer;
5import org.eclipse.viatra.query.runtime.rete.matcher.ReteEngine;
6import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher;
7import org.eclipse.viatra.query.runtime.rete.traceability.RecipeTraceInfo;
8
9import java.lang.invoke.MethodHandle;
10import java.lang.invoke.MethodHandles;
11import java.lang.invoke.MethodType;
12
13final class IndexerUtils {
14 private static final MethodHandle GET_ENGINE_HANDLE;
15 private static final MethodHandle GET_PRODUCTION_NODE_TRACE_HANDLE;
16 private static final MethodHandle ACCESS_PROJECTION_HANDLE;
17
18 static {
19 try {
20 var lookup = MethodHandles.privateLookupIn(RetePatternMatcher.class, MethodHandles.lookup());
21 GET_ENGINE_HANDLE = lookup.findGetter(RetePatternMatcher.class, "engine", ReteEngine.class);
22 GET_PRODUCTION_NODE_TRACE_HANDLE = lookup.findGetter(RetePatternMatcher.class, "productionNodeTrace",
23 RecipeTraceInfo.class);
24 ACCESS_PROJECTION_HANDLE = lookup.findVirtual(ReteEngine.class, "accessProjection",
25 MethodType.methodType(Indexer.class, RecipeTraceInfo.class, TupleMask.class));
26 } catch (IllegalAccessException | NoSuchFieldException | NoSuchMethodException e) {
27 throw new IllegalStateException("Cannot access private members of %s"
28 .formatted(RetePatternMatcher.class.getPackageName()), e);
29 }
30 }
31
32 private IndexerUtils() {
33 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
34 }
35
36 public static Indexer getIndexer(RetePatternMatcher backend, TupleMask mask) {
37 try {
38 var engine = (ReteEngine) GET_ENGINE_HANDLE.invokeExact(backend);
39 var trace = (RecipeTraceInfo) GET_PRODUCTION_NODE_TRACE_HANDLE.invokeExact(backend);
40 return (Indexer) ACCESS_PROJECTION_HANDLE.invokeExact(engine, trace, mask);
41 } catch (Error e) {
42 // Fatal JVM errors should not be wrapped.
43 throw e;
44 } catch (Throwable e) {
45 throw new IllegalStateException("Cannot access matcher for mask " + mask, e);
46 }
47 }
48}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java
index e944e873..8f56586e 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java
@@ -2,71 +2,92 @@ package tools.refinery.store.query.viatra.internal.pquery;
2 2
3import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; 3import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher;
4import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; 4import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification;
5import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
6import org.eclipse.viatra.query.runtime.matchers.backend.IMatcherCapability;
7import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider;
8import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
9import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
10import org.eclipse.viatra.query.runtime.rete.index.Indexer;
11import org.eclipse.viatra.query.runtime.rete.matcher.RetePatternMatcher;
5import tools.refinery.store.query.ResultSet; 12import tools.refinery.store.query.ResultSet;
6import tools.refinery.store.query.viatra.ViatraTupleLike; 13import tools.refinery.store.query.viatra.ViatraTupleLike;
7import tools.refinery.store.tuple.Tuple; 14import tools.refinery.store.tuple.Tuple;
8import tools.refinery.store.tuple.TupleLike; 15import tools.refinery.store.tuple.TupleLike;
9 16
10import java.util.Optional;
11import java.util.stream.Stream; 17import java.util.stream.Stream;
12 18
19/**
20 * Directly access the tuples inside a VIATRA pattern matcher.<p>
21 * This class neglects calling
22 * {@link org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext#wrapTuple(org.eclipse.viatra.query.runtime.matchers.tuple.Tuple)}
23 * and
24 * {@link org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext#unwrapTuple(org.eclipse.viatra.query.runtime.matchers.tuple.Tuple)},
25 * because {@link tools.refinery.store.query.viatra.internal.context.RelationalRuntimeContext} provides a trivial
26 * implementation for these methods.
27 * Using this class with any other runtime context may lead to undefined behavior.
28 */
13public class RawPatternMatcher extends GenericPatternMatcher implements ResultSet { 29public class RawPatternMatcher extends GenericPatternMatcher implements ResultSet {
14 protected final Object[] empty; 30 private final Object[] empty;
31 private final TupleMask identityMask;
32 private Indexer emptyMaskIndexer;
15 33
16 public RawPatternMatcher(GenericQuerySpecification<? extends GenericPatternMatcher> specification) { 34 public RawPatternMatcher(GenericQuerySpecification<? extends GenericPatternMatcher> specification) {
17 super(specification); 35 super(specification);
18 empty = new Object[specification.getParameterNames().size()]; 36 var arity = specification.getParameterNames().size();
19 } 37 empty = new Object[arity];
38 identityMask = TupleMask.identity(arity);
39 }
20 40
21 @Override 41 @Override
22 public boolean hasResult() { 42 protected void setBackend(ViatraQueryEngine engine, IQueryResultProvider resultProvider,
23 return backend.hasMatch(empty); 43 IMatcherCapability capabilities) {
24 } 44 super.setBackend(engine, resultProvider, capabilities);
45 if (resultProvider instanceof RetePatternMatcher reteBackend) {
46 emptyMaskIndexer = IndexerUtils.getIndexer(reteBackend, TupleMask.empty(identityMask.sourceWidth));
47 }
48 }
25 49
26 @Override 50 @Override
27 public boolean hasResult(Tuple parameters) { 51 public boolean hasResult(TupleLike parameters) {
28 return backend.hasMatch(toParametersArray(parameters)); 52 org.eclipse.viatra.query.runtime.matchers.tuple.Tuple tuple;
29 } 53 if (parameters instanceof ViatraTupleLike viatraTupleLike) {
54 tuple = viatraTupleLike.wrappedTuple().toImmutable();
55 } else {
56 var parametersArray = toParametersArray(parameters);
57 tuple = Tuples.flatTupleOf(parametersArray);
58 }
59 if (emptyMaskIndexer == null) {
60 return backend.hasMatch(identityMask, tuple);
61 }
62 var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf());
63 return matches != null && matches.contains(tuple);
64 }
30 65
31 @Override 66 @Override
32 public Optional<TupleLike> oneResult() { 67 public Stream<TupleLike> allResults() {
33 return backend.getOneArbitraryMatch(empty).map(ViatraTupleLike::new); 68 if (emptyMaskIndexer == null) {
34 } 69 return backend.getAllMatches(empty).map(ViatraTupleLike::new);
70 }
71 var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf());
72 return matches == null ? Stream.of() : matches.stream().map(ViatraTupleLike::new);
73 }
35 74
36 @Override 75 @Override
37 public Optional<TupleLike> oneResult(Tuple parameters) { 76 public int countResults() {
38 return backend.getOneArbitraryMatch(toParametersArray(parameters)).map(ViatraTupleLike::new); 77 if (emptyMaskIndexer == null) {
39 } 78 return backend.countMatches(empty);
79 }
80 var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf());
81 return matches == null ? 0 : matches.size();
82 }
40 83
41 @Override 84 private Object[] toParametersArray(TupleLike tuple) {
42 public Stream<TupleLike> allResults() { 85 int size = tuple.getSize();
43 return backend.getAllMatches(empty).map(ViatraTupleLike::new); 86 var array = new Object[size];
44 } 87 for (int i = 0; i < size; i++) {
45 88 var value = tuple.get(i);
46 @Override 89 array[i] = Tuple.of(value);
47 public Stream<TupleLike> allResults(Tuple parameters) { 90 }
48 return backend.getAllMatches(toParametersArray(parameters)).map(ViatraTupleLike::new); 91 return array;
49 } 92 }
50
51 @Override
52 public int countResults() {
53 return backend.countMatches(empty);
54 }
55
56 @Override
57 public int countResults(Tuple parameters) {
58 return backend.countMatches(toParametersArray(parameters));
59 }
60
61 private Object[] toParametersArray(Tuple tuple) {
62 int size = tuple.getSize();
63 var array = new Object[tuple.getSize()];
64 for (int i = 0; i < size; i++) {
65 var value = tuple.get(i);
66 if (value >= 0) {
67 array[i] = Tuple.of(value);
68 }
69 }
70 return array;
71 }
72} 93}
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 54ae70c3..3dd517c4 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
@@ -16,8 +16,7 @@ import java.util.HashSet;
16import java.util.Set; 16import 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.*;
20import static org.junit.jupiter.api.Assertions.assertThrows;
21import static tools.refinery.store.query.literal.Literals.not; 20import static tools.refinery.store.query.literal.Literals.not;
22 21
23class QueryTest { 22class QueryTest {
@@ -97,10 +96,14 @@ class QueryTest {
97 friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); 96 friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE);
98 97
99 assertEquals(0, predicateResultSet.countResults()); 98 assertEquals(0, predicateResultSet.countResults());
99 assertFalse(predicateResultSet.hasResult(Tuple.of(0, 1)));
100 assertFalse(predicateResultSet.hasResult(Tuple.of(0, 2)));
100 101
101 queryEngine.flushChanges(); 102 queryEngine.flushChanges();
102 assertEquals(3, predicateResultSet.countResults()); 103 assertEquals(3, predicateResultSet.countResults());
103 compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(1, 2))); 104 compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(1, 2)));
105 assertTrue(predicateResultSet.hasResult(Tuple.of(0, 1)));
106 assertFalse(predicateResultSet.hasResult(Tuple.of(0, 2)));
104 } 107 }
105 108
106 @Test 109 @Test
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java
index a01a5a2f..0c2e07d6 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java
@@ -1,49 +1,22 @@
1package tools.refinery.store.query; 1package tools.refinery.store.query;
2 2
3import tools.refinery.store.tuple.Tuple;
4import tools.refinery.store.tuple.TupleLike; 3import tools.refinery.store.tuple.TupleLike;
5 4
6import java.util.Optional;
7import java.util.stream.Stream; 5import java.util.stream.Stream;
8 6
9public class EmptyResultSet implements ResultSet { 7public class EmptyResultSet implements ResultSet {
10 @Override 8 @Override
11 public boolean hasResult() { 9 public boolean hasResult(TupleLike parameters) {
12 return false; 10 return false;
13 } 11 }
14 12
15 @Override 13 @Override
16 public boolean hasResult(Tuple parameters) {
17 return false;
18 }
19
20 @Override
21 public Optional<TupleLike> oneResult() {
22 return Optional.empty();
23 }
24
25 @Override
26 public Optional<TupleLike> oneResult(Tuple parameters) {
27 return Optional.empty();
28 }
29
30 @Override
31 public Stream<TupleLike> allResults() { 14 public Stream<TupleLike> allResults() {
32 return Stream.of(); 15 return Stream.of();
33 } 16 }
34 17
35 @Override 18 @Override
36 public Stream<TupleLike> allResults(Tuple parameters) {
37 return Stream.of();
38 }
39
40 @Override
41 public int countResults() { 19 public int countResults() {
42 return 0; 20 return 0;
43 } 21 }
44
45 @Override
46 public int countResults(Tuple parameters) {
47 return 0;
48 }
49} 22}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java
index 3542e252..407cf075 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java
@@ -1,25 +1,17 @@
1package tools.refinery.store.query; 1package tools.refinery.store.query;
2 2
3import tools.refinery.store.tuple.Tuple;
4import tools.refinery.store.tuple.TupleLike; 3import tools.refinery.store.tuple.TupleLike;
5 4
6import java.util.Optional;
7import java.util.stream.Stream; 5import java.util.stream.Stream;
8 6
9public interface ResultSet { 7public interface ResultSet {
10 boolean hasResult(); 8 default boolean hasResult() {
9 return countResults() > 0;
10 }
11 11
12 boolean hasResult(Tuple parameters); 12 boolean hasResult(TupleLike parameters);
13
14 Optional<TupleLike> oneResult();
15
16 Optional<TupleLike> oneResult(Tuple parameters);
17 13
18 Stream<TupleLike> allResults(); 14 Stream<TupleLike> allResults();
19 15
20 Stream<TupleLike> allResults(Tuple parameters);
21
22 int countResults(); 16 int countResults();
23
24 int countResults(Tuple parameters);
25} 17}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Seed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java
index 779eadbe..042c2636 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Seed.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java
@@ -6,6 +6,8 @@ import tools.refinery.store.tuple.Tuple;
6public interface Seed<T> { 6public interface Seed<T> {
7 int arity(); 7 int arity();
8 8
9 T getReducedValue();
10
9 T get(Tuple key); 11 T get(Tuple key);
10 12
11 Cursor<Tuple, T> getCursor(T defaultValue, int nodeCount); 13 Cursor<Tuple, T> getCursor(T defaultValue, int nodeCount);