aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-01-29 02:06:57 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-01-29 02:06:57 +0100
commit1d87633ef1dcf924f27949ff4dc2fedb4a8b67ef (patch)
treeee5cfb52db47c10de7e86bb44651e815526acb0b /subprojects/store-query-viatra
parentrefactor: Model store and query API (diff)
downloadrefinery-1d87633ef1dcf924f27949ff4dc2fedb4a8b67ef.tar.gz
refinery-1d87633ef1dcf924f27949ff4dc2fedb4a8b67ef.tar.zst
refinery-1d87633ef1dcf924f27949ff4dc2fedb4a8b67ef.zip
feat: negative and transitive RelationViewAtom
Use PVisibility.EMBEDDED helper patterns to avoid superfluous production nodes in the Rete net.
Diffstat (limited to 'subprojects/store-query-viatra')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java47
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java8
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java124
3 files changed, 170 insertions, 9 deletions
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 2b5618d2..eb815588 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
@@ -12,10 +12,12 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.Consta
12import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; 12import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
13import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; 13import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
14import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; 14import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
15import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility;
15import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; 16import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
16import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 17import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
17import tools.refinery.store.query.DNF; 18import tools.refinery.store.query.DNF;
18import tools.refinery.store.query.DNFAnd; 19import tools.refinery.store.query.DNFAnd;
20import tools.refinery.store.query.DNFUtils;
19import tools.refinery.store.query.Variable; 21import tools.refinery.store.query.Variable;
20import tools.refinery.store.query.atom.*; 22import tools.refinery.store.query.atom.*;
21import tools.refinery.store.query.view.AnyRelationView; 23import tools.refinery.store.query.view.AnyRelationView;
@@ -124,8 +126,19 @@ public class DNF2PQuery {
124 } 126 }
125 127
126 private void translateRelationViewAtom(RelationViewAtom relationViewAtom, PBody body) { 128 private void translateRelationViewAtom(RelationViewAtom relationViewAtom, PBody body) {
127 new TypeConstraint(body, translateSubstitution(relationViewAtom.getSubstitution(), body), 129 var substitution = translateSubstitution(relationViewAtom.getSubstitution(), body);
128 wrapView(relationViewAtom.getTarget())); 130 var polarity = relationViewAtom.getPolarity();
131 var relationView = relationViewAtom.getTarget();
132 if (polarity == CallPolarity.POSITIVE) {
133 new TypeConstraint(body, substitution, wrapView(relationView));
134 } else {
135 var embeddedPQuery = translateEmbeddedRelationViewPQuery(relationView);
136 switch (polarity) {
137 case TRANSITIVE -> new BinaryTransitiveClosure(body, substitution, embeddedPQuery);
138 case NEGATIVE -> new NegativePatternCall(body, substitution, embeddedPQuery);
139 default -> throw new IllegalArgumentException("Unknown polarity: " + polarity);
140 }
141 }
129 } 142 }
130 143
131 private static Tuple translateSubstitution(List<Variable> substitution, PBody body) { 144 private static Tuple translateSubstitution(List<Variable> substitution, PBody body) {
@@ -138,16 +151,36 @@ public class DNF2PQuery {
138 return Tuples.flatTupleOf(variables); 151 return Tuples.flatTupleOf(variables);
139 } 152 }
140 153
154 private RawPQuery translateEmbeddedRelationViewPQuery(AnyRelationView relationView) {
155 var embeddedPQuery = new RawPQuery(DNFUtils.generateUniqueName(relationView.name()), PVisibility.EMBEDDED);
156 var body = new PBody(embeddedPQuery);
157 int arity = relationView.arity();
158 var parameters = new ArrayList<PParameter>(arity);
159 var arguments = new Object[arity];
160 var symbolicParameters = new ArrayList<ExportedParameter>(arity);
161 for (int i = 0; i < arity; i++) {
162 var parameterName = "p" + i;
163 var parameter = new PParameter(parameterName);
164 parameters.add(parameter);
165 var variable = body.getOrCreateVariableByName(parameterName);
166 arguments[i] = variable;
167 symbolicParameters.add(new ExportedParameter(body, variable, parameter));
168 }
169 embeddedPQuery.setParameters(parameters);
170 body.setSymbolicParameters(symbolicParameters);
171 var argumentTuple = Tuples.flatTupleOf(arguments);
172 new TypeConstraint(body, argumentTuple, wrapView(relationView));
173 embeddedPQuery.addBody(body);
174 return embeddedPQuery;
175 }
176
141 private RelationViewWrapper wrapView(AnyRelationView relationView) { 177 private RelationViewWrapper wrapView(AnyRelationView relationView) {
142 return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); 178 return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new);
143 } 179 }
144 180
145 private void translateCallAtom(CallAtom<?> callAtom, PBody body) { 181 private void translateCallAtom(DNFCallAtom callAtom, PBody body) {
146 if (!(callAtom.getTarget() instanceof DNF target)) {
147 throw new IllegalArgumentException("Only calls to DNF are supported");
148 }
149 var variablesTuple = translateSubstitution(callAtom.getSubstitution(), body); 182 var variablesTuple = translateSubstitution(callAtom.getSubstitution(), body);
150 var translatedReferred = translate(target); 183 var translatedReferred = translate(callAtom.getTarget());
151 var polarity = callAtom.getPolarity(); 184 var polarity = callAtom.getPolarity();
152 switch (polarity) { 185 switch (polarity) {
153 case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred); 186 case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred);
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java
index 5d0b9e82..830495b2 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java
@@ -18,11 +18,15 @@ public class RawPQuery extends BasePQuery {
18 private List<PParameter> parameters; 18 private List<PParameter> parameters;
19 private final LinkedHashSet<PBody> bodies = new LinkedHashSet<>(); 19 private final LinkedHashSet<PBody> bodies = new LinkedHashSet<>();
20 20
21 public RawPQuery(String name) { 21 public RawPQuery(String name, PVisibility visibility) {
22 super(PVisibility.PUBLIC); 22 super(visibility);
23 fullyQualifiedName = name; 23 fullyQualifiedName = name;
24 } 24 }
25 25
26 public RawPQuery(String name) {
27 this(name, PVisibility.PUBLIC);
28 }
29
26 @Override 30 @Override
27 public String getFullyQualifiedName() { 31 public String getFullyQualifiedName() {
28 return fullyQualifiedName; 32 return fullyQualifiedName;
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 72e8d7e5..ba0abca0 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
@@ -391,6 +391,48 @@ class QueryTest {
391 } 391 }
392 392
393 @Test 393 @Test
394 void negativeRelationViewTest() {
395 var person = new Symbol<>("Person", 1, Boolean.class, false);
396 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);
397 var personView = new KeyOnlyRelationView<>(person);
398 var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must);
399
400 var p1 = new Variable("p1");
401 var p2 = new Variable("p2");
402 var predicate = DNF.builder("NegativePatternCall")
403 .parameters(p1, p2)
404 .clause(
405 new RelationViewAtom(personView, p1),
406 new RelationViewAtom(personView, p2),
407 new RelationViewAtom(false, friendMustView, p1, p2)
408 )
409 .build();
410
411 var store = ModelStore.builder()
412 .symbols(person, friend)
413 .with(ViatraModelQuery.ADAPTER)
414 .queries(predicate)
415 .build();
416
417 var model = store.createModel();
418 var personInterpretation = model.getInterpretation(person);
419 var friendInterpretation = model.getInterpretation(friend);
420 var queryEngine = model.getAdapter(ModelQuery.ADAPTER);
421 var predicateResultSet = queryEngine.getResultSet(predicate);
422
423 personInterpretation.put(Tuple.of(0), true);
424 personInterpretation.put(Tuple.of(1), true);
425 personInterpretation.put(Tuple.of(2), true);
426
427 friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE);
428 friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE);
429 friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE);
430
431 queryEngine.flushChanges();
432 assertEquals(6, predicateResultSet.countResults());
433 }
434
435 @Test
394 void negativePatternCallTest() { 436 void negativePatternCallTest() {
395 var person = new Symbol<>("Person", 1, Boolean.class, false); 437 var person = new Symbol<>("Person", 1, Boolean.class, false);
396 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); 438 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);
@@ -444,6 +486,47 @@ class QueryTest {
444 } 486 }
445 487
446 @Test 488 @Test
489 void negativeRelationViewWithQuantificationTest() {
490 var person = new Symbol<>("Person", 1, Boolean.class, false);
491 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);
492 var personView = new KeyOnlyRelationView<>(person);
493 var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must);
494
495 var p1 = new Variable("p1");
496 var p2 = new Variable("p2");
497
498 var predicate = DNF.builder("Count")
499 .parameters(p1)
500 .clause(
501 new RelationViewAtom(personView, p1),
502 new RelationViewAtom(false, friendMustView, p1, p2)
503 )
504 .build();
505
506 var store = ModelStore.builder()
507 .symbols(person, friend)
508 .with(ViatraModelQuery.ADAPTER)
509 .queries(predicate)
510 .build();
511
512 var model = store.createModel();
513 var personInterpretation = model.getInterpretation(person);
514 var friendInterpretation = model.getInterpretation(friend);
515 var queryEngine = model.getAdapter(ModelQuery.ADAPTER);
516 var predicateResultSet = queryEngine.getResultSet(predicate);
517
518 personInterpretation.put(Tuple.of(0), true);
519 personInterpretation.put(Tuple.of(1), true);
520 personInterpretation.put(Tuple.of(2), true);
521
522 friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE);
523 friendInterpretation.put(Tuple.of(0, 2), TruthValue.TRUE);
524
525 queryEngine.flushChanges();
526 assertEquals(2, predicateResultSet.countResults());
527 }
528
529 @Test
447 void negativeWithQuantificationTest() { 530 void negativeWithQuantificationTest() {
448 var person = new Symbol<>("Person", 1, Boolean.class, false); 531 var person = new Symbol<>("Person", 1, Boolean.class, false);
449 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); 532 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);
@@ -494,6 +577,47 @@ class QueryTest {
494 } 577 }
495 578
496 @Test 579 @Test
580 void transitiveRelationViewTest() {
581 var person = new Symbol<>("Person", 1, Boolean.class, false);
582 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);
583 var personView = new KeyOnlyRelationView<>(person);
584 var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must);
585
586 var p1 = new Variable("p1");
587 var p2 = new Variable("p2");
588 var predicate = DNF.builder("TransitivePatternCall")
589 .parameters(p1, p2)
590 .clause(
591 new RelationViewAtom(personView, p1),
592 new RelationViewAtom(personView, p2),
593 new RelationViewAtom(CallPolarity.TRANSITIVE, friendMustView, p1, p2)
594 )
595 .build();
596
597 var store = ModelStore.builder()
598 .symbols(person, friend)
599 .with(ViatraModelQuery.ADAPTER)
600 .queries(predicate)
601 .build();
602
603 var model = store.createModel();
604 var personInterpretation = model.getInterpretation(person);
605 var friendInterpretation = model.getInterpretation(friend);
606 var queryEngine = model.getAdapter(ModelQuery.ADAPTER);
607 var predicateResultSet = queryEngine.getResultSet(predicate);
608
609 personInterpretation.put(Tuple.of(0), true);
610 personInterpretation.put(Tuple.of(1), true);
611 personInterpretation.put(Tuple.of(2), true);
612
613 friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE);
614 friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE);
615
616 queryEngine.flushChanges();
617 assertEquals(3, predicateResultSet.countResults());
618 }
619
620 @Test
497 void transitivePatternCallTest() { 621 void transitivePatternCallTest() {
498 var person = new Symbol<>("Person", 1, Boolean.class, false); 622 var person = new Symbol<>("Person", 1, Boolean.class, false);
499 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); 623 var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE);