aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-10 21:42:52 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-15 14:37:26 +0200
commit60e90db11d1a6898aa8b2e1d82ea647a7898f9f0 (patch)
treef0248c9b1148054357a74795bb8e9b20405fe8c9 /subprojects/store-query-viatra
parentfeat: DNF rewriting (diff)
downloadrefinery-60e90db11d1a6898aa8b2e1d82ea647a7898f9f0.tar.gz
refinery-60e90db11d1a6898aa8b2e1d82ea647a7898f9f0.tar.zst
refinery-60e90db11d1a6898aa8b2e1d82ea647a7898f9f0.zip
feat: query rewriters for Viatra
Diffstat (limited to 'subprojects/store-query-viatra')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java8
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java3
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java74
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java15
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java25
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java1
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java49
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java2
8 files changed, 113 insertions, 64 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java
index 931a07aa..66279c94 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java
@@ -9,9 +9,10 @@ import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions;
9import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; 9import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
10import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; 10import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
11import tools.refinery.store.model.ModelStore; 11import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.query.ModelQueryBuilder;
12import tools.refinery.store.query.dnf.AnyQuery; 13import tools.refinery.store.query.dnf.AnyQuery;
13import tools.refinery.store.query.dnf.Dnf; 14import tools.refinery.store.query.dnf.Dnf;
14import tools.refinery.store.query.ModelQueryBuilder; 15import tools.refinery.store.query.rewriter.DnfRewriter;
15 16
16import java.util.Collection; 17import java.util.Collection;
17import java.util.function.Function; 18import java.util.function.Function;
@@ -43,12 +44,11 @@ public interface ViatraModelQueryBuilder extends ModelQueryBuilder {
43 @Override 44 @Override
44 ViatraModelQueryBuilder query(AnyQuery query); 45 ViatraModelQueryBuilder query(AnyQuery query);
45 46
46 ViatraModelQueryBuilder query(AnyQuery query, QueryEvaluationHint queryEvaluationHint); 47 @Override
48 ViatraModelQueryBuilder rewriter(DnfRewriter rewriter);
47 49
48 ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint); 50 ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint);
49 51
50 ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint);
51
52 @Override 52 @Override
53 ViatraModelQueryStoreAdapter build(ModelStore store); 53 ViatraModelQueryStoreAdapter build(ModelStore store);
54} 54}
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 5f3e86b4..e17386e1 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
@@ -131,7 +131,8 @@ public class ViatraModelQueryAdapterImpl implements ViatraModelQueryAdapter, Mod
131 131
132 @Override 132 @Override
133 public <T> ResultSet<T> getResultSet(Query<T> query) { 133 public <T> ResultSet<T> getResultSet(Query<T> query) {
134 var resultSet = resultSets.get(query); 134 var canonicalQuery = storeAdapter.getCanonicalQuery(query);
135 var resultSet = resultSets.get(canonicalQuery);
135 if (resultSet == null) { 136 if (resultSet == null) {
136 throw new IllegalArgumentException("No matcher for query %s in model".formatted(query.name())); 137 throw new IllegalArgumentException("No matcher for query %s in model".formatted(query.name()));
137 } 138 }
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 ce2467b4..5ee8bd74 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
@@ -13,9 +13,12 @@ import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
13import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory; 13import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory;
14import tools.refinery.store.adapter.AbstractModelAdapterBuilder; 14import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
15import tools.refinery.store.model.ModelStore; 15import tools.refinery.store.model.ModelStore;
16import tools.refinery.store.model.ModelStoreBuilder;
17import tools.refinery.store.query.dnf.AnyQuery; 16import tools.refinery.store.query.dnf.AnyQuery;
18import tools.refinery.store.query.dnf.Dnf; 17import tools.refinery.store.query.dnf.Dnf;
18import tools.refinery.store.query.rewriter.CompositeRewriter;
19import tools.refinery.store.query.rewriter.DnfRewriter;
20import tools.refinery.store.query.rewriter.DuplicateDnfRemover;
21import tools.refinery.store.query.rewriter.InputParameterResolver;
19import tools.refinery.store.query.viatra.ViatraModelQueryBuilder; 22import tools.refinery.store.query.viatra.ViatraModelQueryBuilder;
20import tools.refinery.store.query.viatra.internal.localsearch.FlatCostFunction; 23import tools.refinery.store.query.viatra.internal.localsearch.FlatCostFunction;
21import tools.refinery.store.query.viatra.internal.localsearch.RelationalLocalSearchBackendFactory; 24import tools.refinery.store.query.viatra.internal.localsearch.RelationalLocalSearchBackendFactory;
@@ -32,15 +35,18 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder<Via
32 // Use a cost function that ignores the initial (empty) model but allows higher arity input keys. 35 // Use a cost function that ignores the initial (empty) model but allows higher arity input keys.
33 LocalSearchHintOptions.PLANNER_COST_FUNCTION, new FlatCostFunction() 36 LocalSearchHintOptions.PLANNER_COST_FUNCTION, new FlatCostFunction()
34 ), (IQueryBackendFactory) null); 37 ), (IQueryBackendFactory) null);
38 private final CompositeRewriter rewriter;
35 private final Dnf2PQuery dnf2PQuery = new Dnf2PQuery(); 39 private final Dnf2PQuery dnf2PQuery = new Dnf2PQuery();
36 private final Set<AnyQuery> vacuousQueries = new LinkedHashSet<>(); 40 private final Set<AnyQuery> queries = new LinkedHashSet<>();
37 private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>();
38 41
39 public ViatraModelQueryBuilderImpl() { 42 public ViatraModelQueryBuilderImpl() {
40 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() 43 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder()
41 .withDefaultBackend(ReteBackendFactory.INSTANCE) 44 .withDefaultBackend(ReteBackendFactory.INSTANCE)
42 .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) 45 .withDefaultCachingBackend(ReteBackendFactory.INSTANCE)
43 .withDefaultSearchBackend(RelationalLocalSearchBackendFactory.INSTANCE); 46 .withDefaultSearchBackend(RelationalLocalSearchBackendFactory.INSTANCE);
47 rewriter = new CompositeRewriter();
48 rewriter.addFirst(new DuplicateDnfRemover());
49 rewriter.addFirst(new InputParameterResolver());
44 } 50 }
45 51
46 @Override 52 @Override
@@ -79,58 +85,58 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder<Via
79 } 85 }
80 86
81 @Override 87 @Override
82 public ViatraModelQueryBuilder query(AnyQuery query) { 88 public ViatraModelQueryBuilder queries(Collection<? extends AnyQuery> queries) {
83 checkNotConfigured(); 89 checkNotConfigured();
84 if (querySpecifications.containsKey(query) || vacuousQueries.contains(query)) { 90 this.queries.addAll(queries);
85 // Ignore duplicate queries.
86 return this;
87 }
88 var dnf = query.getDnf();
89 var reduction = dnf.getReduction();
90 switch (reduction) {
91 case NOT_REDUCIBLE -> {
92 var pQuery = dnf2PQuery.translate(dnf);
93 querySpecifications.put(query, pQuery.build());
94 }
95 case ALWAYS_FALSE -> vacuousQueries.add(query);
96 case ALWAYS_TRUE -> throw new IllegalArgumentException(
97 "Query %s is relationally unsafe (it matches every tuple)".formatted(query.name()));
98 default -> throw new IllegalArgumentException("Unknown reduction: " + reduction);
99 }
100 return this; 91 return this;
101 } 92 }
102 93
103 @Override 94 @Override
104 public ViatraModelQueryBuilder query(AnyQuery query, QueryEvaluationHint queryEvaluationHint) { 95 public ViatraModelQueryBuilder query(AnyQuery query) {
105 hint(query.getDnf(), queryEvaluationHint); 96 checkNotConfigured();
106 query(query); 97 queries.add(query);
107 return this; 98 return this;
108 } 99 }
109 100
110 @Override 101 @Override
111 public ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint) { 102 public ViatraModelQueryBuilder rewriter(DnfRewriter rewriter) {
112 checkNotConfigured(); 103 this.rewriter.addFirst(rewriter);
113 dnf2PQuery.setComputeHint(computeHint);
114 return this; 104 return this;
115 } 105 }
116 106
117 @Override 107 @Override
118 public ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint) { 108 public ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint) {
119 checkNotConfigured(); 109 checkNotConfigured();
120 dnf2PQuery.hint(dnf, queryEvaluationHint); 110 dnf2PQuery.setComputeHint(computeHint);
121 return this; 111 return this;
122 } 112 }
123 113
124 @Override 114 @Override
125 public void doConfigure(ModelStoreBuilder storeBuilder) {
126 dnf2PQuery.assertNoUnusedHints();
127 }
128
129 @Override
130 public ViatraModelQueryStoreAdapterImpl doBuild(ModelStore store) { 115 public ViatraModelQueryStoreAdapterImpl doBuild(ModelStore store) {
116 var canonicalQueryMap = new HashMap<AnyQuery, AnyQuery>();
117 var querySpecifications = new LinkedHashMap<AnyQuery, IQuerySpecification<RawPatternMatcher>>();
118 var vacuousQueries = new LinkedHashSet<AnyQuery>();
119 for (var query : queries) {
120 var canonicalQuery = rewriter.rewrite(query);
121 canonicalQueryMap.put(query, canonicalQuery);
122 var dnf = canonicalQuery.getDnf();
123 var reduction = dnf.getReduction();
124 switch (reduction) {
125 case NOT_REDUCIBLE -> {
126 var pQuery = dnf2PQuery.translate(dnf);
127 querySpecifications.put(canonicalQuery, pQuery.build());
128 }
129 case ALWAYS_FALSE -> vacuousQueries.add(canonicalQuery);
130 case ALWAYS_TRUE -> throw new IllegalArgumentException(
131 "Query %s is relationally unsafe (it matches every tuple)".formatted(query.name()));
132 default -> throw new IllegalArgumentException("Unknown reduction: " + reduction);
133 }
134 }
135
131 validateSymbols(store); 136 validateSymbols(store);
132 return new ViatraModelQueryStoreAdapterImpl(store, buildEngineOptions(), dnf2PQuery.getSymbolViews(), 137 return new ViatraModelQueryStoreAdapterImpl(store, buildEngineOptions(), dnf2PQuery.getSymbolViews(),
133 Collections.unmodifiableMap(querySpecifications), Collections.unmodifiableSet(vacuousQueries)); 138 Collections.unmodifiableMap(canonicalQueryMap), Collections.unmodifiableMap(querySpecifications),
139 Collections.unmodifiableSet(vacuousQueries));
134 } 140 }
135 141
136 private ViatraQueryEngineOptions buildEngineOptions() { 142 private ViatraQueryEngineOptions buildEngineOptions() {
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 11a3c7fd..25f1cd02 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
@@ -11,6 +11,7 @@ import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
11import tools.refinery.store.model.Model; 11import tools.refinery.store.model.Model;
12import tools.refinery.store.model.ModelStore; 12import tools.refinery.store.model.ModelStore;
13import tools.refinery.store.query.dnf.AnyQuery; 13import tools.refinery.store.query.dnf.AnyQuery;
14import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter; 15import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter;
15import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher; 16import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher;
16import tools.refinery.store.query.view.AnySymbolView; 17import tools.refinery.store.query.view.AnySymbolView;
@@ -21,17 +22,20 @@ public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAd
21 private final ModelStore store; 22 private final ModelStore store;
22 private final ViatraQueryEngineOptions engineOptions; 23 private final ViatraQueryEngineOptions engineOptions;
23 private final Map<AnySymbolView, IInputKey> inputKeys; 24 private final Map<AnySymbolView, IInputKey> inputKeys;
25 private final Map<AnyQuery, AnyQuery> canonicalQueryMap;
24 private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications; 26 private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications;
25 private final Set<AnyQuery> vacuousQueries; 27 private final Set<AnyQuery> vacuousQueries;
26 private final Set<AnyQuery> allQueries; 28 private final Set<AnyQuery> allQueries;
27 29
28 ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions, 30 ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions,
29 Map<AnySymbolView, IInputKey> inputKeys, 31 Map<AnySymbolView, IInputKey> inputKeys,
32 Map<AnyQuery, AnyQuery> canonicalQueryMap,
30 Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications, 33 Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications,
31 Set<AnyQuery> vacuousQueries) { 34 Set<AnyQuery> vacuousQueries) {
32 this.store = store; 35 this.store = store;
33 this.engineOptions = engineOptions; 36 this.engineOptions = engineOptions;
34 this.inputKeys = inputKeys; 37 this.inputKeys = inputKeys;
38 this.canonicalQueryMap = canonicalQueryMap;
35 this.querySpecifications = querySpecifications; 39 this.querySpecifications = querySpecifications;
36 this.vacuousQueries = vacuousQueries; 40 this.vacuousQueries = vacuousQueries;
37 var mutableAllQueries = new LinkedHashSet<AnyQuery>(querySpecifications.size() + vacuousQueries.size()); 41 var mutableAllQueries = new LinkedHashSet<AnyQuery>(querySpecifications.size() + vacuousQueries.size());
@@ -58,6 +62,17 @@ public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAd
58 return allQueries; 62 return allQueries;
59 } 63 }
60 64
65 @Override
66 public <T> Query<T> getCanonicalQuery(Query<T> query) {
67 // We know that canonical forms of queries do not change output types.
68 @SuppressWarnings("unchecked")
69 var canonicalQuery = (Query<T>) canonicalQueryMap.get(query);
70 if (canonicalQuery == null) {
71 throw new IllegalArgumentException("Unknown query: " + query);
72 }
73 return canonicalQuery;
74 }
75
61 Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> getQuerySpecifications() { 76 Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> getQuerySpecifications() {
62 return querySpecifications; 77 return querySpecifications;
63 } 78 }
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 d51bc9fc..8110a98f 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
@@ -36,14 +36,12 @@ import tools.refinery.store.util.CycleDetectingMapper;
36 36
37import java.util.*; 37import java.util.*;
38import java.util.function.Function; 38import java.util.function.Function;
39import java.util.stream.Collectors;
40 39
41public class Dnf2PQuery { 40public class Dnf2PQuery {
42 private static final Object P_CONSTRAINT_LOCK = new Object(); 41 private static final Object P_CONSTRAINT_LOCK = new Object();
43 private final CycleDetectingMapper<Dnf, RawPQuery> mapper = new CycleDetectingMapper<>(Dnf::name, 42 private final CycleDetectingMapper<Dnf, RawPQuery> mapper = new CycleDetectingMapper<>(Dnf::name,
44 this::doTranslate); 43 this::doTranslate);
45 private final QueryWrapperFactory wrapperFactory = new QueryWrapperFactory(this); 44 private final QueryWrapperFactory wrapperFactory = new QueryWrapperFactory(this);
46 private final Map<Dnf, QueryEvaluationHint> hintOverrides = new LinkedHashMap<>();
47 private Function<Dnf, QueryEvaluationHint> computeHint = dnf -> new QueryEvaluationHint(null, 45 private Function<Dnf, QueryEvaluationHint> computeHint = dnf -> new QueryEvaluationHint(null,
48 (IQueryBackendFactory) null); 46 (IQueryBackendFactory) null);
49 47
@@ -59,30 +57,9 @@ public class Dnf2PQuery {
59 return wrapperFactory.getSymbolViews(); 57 return wrapperFactory.getSymbolViews();
60 } 58 }
61 59
62 public void hint(Dnf dnf, QueryEvaluationHint hint) {
63 hintOverrides.compute(dnf, (ignoredKey, existingHint) ->
64 existingHint == null ? hint : existingHint.overrideBy(hint));
65 }
66
67 private QueryEvaluationHint consumeHint(Dnf dnf) {
68 var defaultHint = computeHint.apply(dnf);
69 var existingHint = hintOverrides.remove(dnf);
70 return defaultHint.overrideBy(existingHint);
71 }
72
73 public void assertNoUnusedHints() {
74 if (hintOverrides.isEmpty()) {
75 return;
76 }
77 var unusedHints = hintOverrides.keySet().stream().map(Dnf::name).collect(Collectors.joining(", "));
78 throw new IllegalStateException(
79 "Unused query evaluation hints for %s. Hints must be set before a query is added to the engine"
80 .formatted(unusedHints));
81 }
82
83 private RawPQuery doTranslate(Dnf dnfQuery) { 60 private RawPQuery doTranslate(Dnf dnfQuery) {
84 var pQuery = new RawPQuery(dnfQuery.getUniqueName()); 61 var pQuery = new RawPQuery(dnfQuery.getUniqueName());
85 pQuery.setEvaluationHints(consumeHint(dnfQuery)); 62 pQuery.setEvaluationHints(computeHint.apply(dnfQuery));
86 63
87 Map<SymbolicParameter, PParameter> parameters = new HashMap<>(); 64 Map<SymbolicParameter, PParameter> parameters = new HashMap<>();
88 List<PParameter> parameterList = new ArrayList<>(); 65 List<PParameter> parameterList = new ArrayList<>();
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
index 6aae2ebe..3d2d5f83 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
@@ -98,6 +98,7 @@ class DiagonalQueryTest {
98 .build(); 98 .build();
99 99
100 var model = store.createEmptyModel(); 100 var model = store.createEmptyModel();
101
101 var personInterpretation = model.getInterpretation(person); 102 var personInterpretation = model.getInterpretation(person);
102 var symbolInterpretation = model.getInterpretation(symbol); 103 var symbolInterpretation = model.getInterpretation(symbol);
103 var queryEngine = model.getAdapter(ModelQueryAdapter.class); 104 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
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 be05b5e6..8ecbe11a 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
@@ -9,7 +9,9 @@ import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
9import org.junit.jupiter.api.Test; 9import org.junit.jupiter.api.Test;
10import tools.refinery.store.model.ModelStore; 10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.query.ModelQueryAdapter; 11import tools.refinery.store.query.ModelQueryAdapter;
12import tools.refinery.store.query.dnf.Dnf;
12import tools.refinery.store.query.dnf.Query; 13import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.term.ParameterDirection;
13import tools.refinery.store.query.term.Variable; 15import tools.refinery.store.query.term.Variable;
14import tools.refinery.store.query.viatra.tests.QueryEngineTest; 16import tools.refinery.store.query.viatra.tests.QueryEngineTest;
15import tools.refinery.store.query.view.AnySymbolView; 17import tools.refinery.store.query.view.AnySymbolView;
@@ -312,6 +314,53 @@ class QueryTest {
312 } 314 }
313 315
314 @QueryEngineTest 316 @QueryEngineTest
317 void patternCallInputArgumentTest(QueryEvaluationHint hint) {
318 var friendPredicate = Dnf.of("Friend", builder -> {
319 var p1 = builder.parameter("p1", ParameterDirection.IN);
320 var p2 = builder.parameter("p2", ParameterDirection.IN);
321 builder.clause(
322 personView.call(p1),
323 personView.call(p2),
324 friendMustView.call(p1, p2)
325 );
326 });
327 var predicate = Query.of("PositivePatternCall", (builder, p3, p4) -> builder.clause(
328 personView.call(p3),
329 personView.call(p4),
330 friendPredicate.call(p3, p4)
331 ));
332
333 var store = ModelStore.builder()
334 .symbols(person, friend)
335 .with(ViatraModelQueryAdapter.builder()
336 .defaultHint(hint)
337 .queries(predicate))
338 .build();
339
340 var model = store.createEmptyModel();
341 var personInterpretation = model.getInterpretation(person);
342 var friendInterpretation = model.getInterpretation(friend);
343 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
344 var predicateResultSet = queryEngine.getResultSet(predicate);
345
346 personInterpretation.put(Tuple.of(0), true);
347 personInterpretation.put(Tuple.of(1), true);
348 personInterpretation.put(Tuple.of(2), true);
349
350 friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE);
351 friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE);
352 friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE);
353
354 queryEngine.flushChanges();
355 assertResults(Map.of(
356 Tuple.of(0, 1), true,
357 Tuple.of(1, 0), true,
358 Tuple.of(1, 2), true,
359 Tuple.of(2, 1), false
360 ), predicateResultSet);
361 }
362
363 @QueryEngineTest
315 void negativeRelationViewTest(QueryEvaluationHint hint) { 364 void negativeRelationViewTest(QueryEvaluationHint hint) {
316 var predicate = Query.of("NegativePatternCall", (builder, p1, p2) -> builder.clause( 365 var predicate = Query.of("NegativePatternCall", (builder, p1, p2) -> builder.clause(
317 personView.call(p1), 366 personView.call(p1),
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 ca089a9d..5c1c4fc1 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
@@ -30,7 +30,7 @@ public final class QueryAssertions {
30 } 30 }
31 31
32 public static <T> void assertResults(Map<Tuple, T> expected, ResultSet<T> resultSet) { 32 public static <T> void assertResults(Map<Tuple, T> expected, ResultSet<T> resultSet) {
33 var defaultValue = resultSet.getQuery().defaultValue(); 33 var defaultValue = resultSet.getCanonicalQuery().defaultValue();
34 var filteredExpected = new LinkedHashMap<Tuple, T>(); 34 var filteredExpected = new LinkedHashMap<Tuple, T>();
35 var executables = new ArrayList<Executable>(); 35 var executables = new ArrayList<Executable>();
36 for (var entry : expected.entrySet()) { 36 for (var entry : expected.entrySet()) {