diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-01-29 02:06:57 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-01-29 02:06:57 +0100 |
commit | 1d87633ef1dcf924f27949ff4dc2fedb4a8b67ef (patch) | |
tree | ee5cfb52db47c10de7e86bb44651e815526acb0b /subprojects | |
parent | refactor: Model store and query API (diff) | |
download | refinery-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')
6 files changed, 210 insertions, 69 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 | |||
12 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | 12 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; |
13 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; | 13 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; |
14 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 14 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; | ||
15 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | 16 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; |
16 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 17 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
17 | import tools.refinery.store.query.DNF; | 18 | import tools.refinery.store.query.DNF; |
18 | import tools.refinery.store.query.DNFAnd; | 19 | import tools.refinery.store.query.DNFAnd; |
20 | import tools.refinery.store.query.DNFUtils; | ||
19 | import tools.refinery.store.query.Variable; | 21 | import tools.refinery.store.query.Variable; |
20 | import tools.refinery.store.query.atom.*; | 22 | import tools.refinery.store.query.atom.*; |
21 | import tools.refinery.store.query.view.AnyRelationView; | 23 | import 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); |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java deleted file mode 100644 index af6a8f5a..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.representation.SymbolLike; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Set; | ||
8 | |||
9 | public abstract class AbstractSubstitutionAtom<T extends SymbolLike> implements DNFAtom { | ||
10 | private final T target; | ||
11 | |||
12 | private final List<Variable> substitution; | ||
13 | |||
14 | protected AbstractSubstitutionAtom(T target, List<Variable> substitution) { | ||
15 | if (substitution.size() != target.arity()) { | ||
16 | throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(), | ||
17 | target.arity(), substitution.size())); | ||
18 | } | ||
19 | this.target = target; | ||
20 | this.substitution = substitution; | ||
21 | } | ||
22 | |||
23 | public T getTarget() { | ||
24 | return target; | ||
25 | } | ||
26 | |||
27 | public List<Variable> getSubstitution() { | ||
28 | return substitution; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public void collectAllVariables(Set<Variable> variables) { | ||
33 | variables.addAll(substitution); | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java index 2e855246..6de5cd08 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java | |||
@@ -1,21 +1,28 @@ | |||
1 | package tools.refinery.store.query.atom; | 1 | package tools.refinery.store.query.atom; |
2 | 2 | ||
3 | import tools.refinery.store.representation.SymbolLike; | ||
4 | import tools.refinery.store.query.Variable; | 3 | import tools.refinery.store.query.Variable; |
4 | import tools.refinery.store.representation.SymbolLike; | ||
5 | 5 | ||
6 | import java.util.List; | 6 | import java.util.List; |
7 | import java.util.Objects; | 7 | import java.util.Objects; |
8 | import java.util.Set; | 8 | import java.util.Set; |
9 | 9 | ||
10 | public abstract class CallAtom<T extends SymbolLike> extends AbstractSubstitutionAtom<T> { | 10 | public abstract class CallAtom<T extends SymbolLike> implements DNFAtom { |
11 | private final CallPolarity polarity; | 11 | private final CallPolarity polarity; |
12 | private final T target; | ||
13 | private final List<Variable> substitution; | ||
12 | 14 | ||
13 | protected CallAtom(CallPolarity polarity, T target, List<Variable> substitution) { | 15 | protected CallAtom(CallPolarity polarity, T target, List<Variable> substitution) { |
14 | super(target, substitution); | 16 | if (substitution.size() != target.arity()) { |
17 | throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(), | ||
18 | target.arity(), substitution.size())); | ||
19 | } | ||
15 | if (polarity.isTransitive() && target.arity() != 2) { | 20 | if (polarity.isTransitive() && target.arity() != 2) { |
16 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); | 21 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); |
17 | } | 22 | } |
18 | this.polarity = polarity; | 23 | this.polarity = polarity; |
24 | this.target = target; | ||
25 | this.substitution = substitution; | ||
19 | } | 26 | } |
20 | 27 | ||
21 | protected CallAtom(CallPolarity polarity, T target, Variable... substitution) { | 28 | protected CallAtom(CallPolarity polarity, T target, Variable... substitution) { |
@@ -42,10 +49,18 @@ public abstract class CallAtom<T extends SymbolLike> extends AbstractSubstitutio | |||
42 | return polarity; | 49 | return polarity; |
43 | } | 50 | } |
44 | 51 | ||
52 | public T getTarget() { | ||
53 | return target; | ||
54 | } | ||
55 | |||
56 | public List<Variable> getSubstitution() { | ||
57 | return substitution; | ||
58 | } | ||
59 | |||
45 | @Override | 60 | @Override |
46 | public void collectAllVariables(Set<Variable> variables) { | 61 | public void collectAllVariables(Set<Variable> variables) { |
47 | if (polarity.isPositive()) { | 62 | if (polarity.isPositive()) { |
48 | super.collectAllVariables(variables); | 63 | variables.addAll(substitution); |
49 | } | 64 | } |
50 | } | 65 | } |
51 | 66 | ||
@@ -53,14 +68,13 @@ public abstract class CallAtom<T extends SymbolLike> extends AbstractSubstitutio | |||
53 | public boolean equals(Object o) { | 68 | public boolean equals(Object o) { |
54 | if (this == o) return true; | 69 | if (this == o) return true; |
55 | if (o == null || getClass() != o.getClass()) return false; | 70 | if (o == null || getClass() != o.getClass()) return false; |
56 | CallAtom<?> that = (CallAtom<?>) o; | 71 | CallAtom<?> callAtom = (CallAtom<?>) o; |
57 | return Objects.equals(polarity, that.polarity) | 72 | return polarity == callAtom.polarity && Objects.equals(target, callAtom.target) && Objects.equals(substitution |
58 | && Objects.equals(getTarget(), that.getTarget()) | 73 | , callAtom.substitution); |
59 | && Objects.equals(getSubstitution(), that.getSubstitution()); | ||
60 | } | 74 | } |
61 | 75 | ||
62 | @Override | 76 | @Override |
63 | public int hashCode() { | 77 | public int hashCode() { |
64 | return Objects.hash(polarity, getTarget(), getSubstitution()); | 78 | return Objects.hash(polarity, target, substitution); |
65 | } | 79 | } |
66 | } | 80 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java index cf836541..a2b176c4 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java | |||
@@ -4,28 +4,29 @@ import tools.refinery.store.query.Variable; | |||
4 | import tools.refinery.store.query.view.AnyRelationView; | 4 | import tools.refinery.store.query.view.AnyRelationView; |
5 | 5 | ||
6 | import java.util.List; | 6 | import java.util.List; |
7 | import java.util.Objects; | ||
8 | 7 | ||
9 | public final class RelationViewAtom extends AbstractSubstitutionAtom<AnyRelationView> { | 8 | public final class RelationViewAtom extends CallAtom<AnyRelationView> { |
10 | public RelationViewAtom(AnyRelationView target, List<Variable> substitution) { | 9 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) { |
11 | super(target, substitution); | 10 | super(polarity, target, substitution); |
12 | } | 11 | } |
13 | 12 | ||
14 | public RelationViewAtom(AnyRelationView target, Variable... substitution) { | 13 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, Variable... substitution) { |
15 | this(target, List.of(substitution)); | 14 | super(polarity, target, substitution); |
16 | } | 15 | } |
17 | 16 | ||
18 | @Override | 17 | public RelationViewAtom(boolean positive, AnyRelationView target, List<Variable> substitution) { |
19 | public boolean equals(Object o) { | 18 | super(positive, target, substitution); |
20 | if (this == o) return true; | ||
21 | if (o == null || getClass() != o.getClass()) return false; | ||
22 | RelationViewAtom relationViewAtom = (RelationViewAtom) o; | ||
23 | return Objects.equals(getTarget(), relationViewAtom.getTarget()) | ||
24 | && Objects.equals(getSubstitution(), relationViewAtom.getSubstitution()); | ||
25 | } | 19 | } |
26 | 20 | ||
27 | @Override | 21 | public RelationViewAtom(boolean positive, AnyRelationView target, Variable... substitution) { |
28 | public int hashCode() { | 22 | super(positive, target, substitution); |
29 | return Objects.hash(getTarget(), getSubstitution()); | 23 | } |
24 | |||
25 | public RelationViewAtom(AnyRelationView target, List<Variable> substitution) { | ||
26 | super(target, substitution); | ||
27 | } | ||
28 | |||
29 | public RelationViewAtom(AnyRelationView target, Variable... substitution) { | ||
30 | super(target, substitution); | ||
30 | } | 31 | } |
31 | } | 32 | } |