aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java')
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java105
1 files changed, 37 insertions, 68 deletions
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java
index 091b4e04..78fae7f5 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java
@@ -1,109 +1,78 @@
1package tools.refinery.store.query.literal; 1package tools.refinery.store.query.literal;
2 2
3import tools.refinery.store.query.RelationLike; 3import tools.refinery.store.query.Constraint;
4import tools.refinery.store.query.Variable;
5import tools.refinery.store.query.equality.LiteralEqualityHelper; 4import tools.refinery.store.query.equality.LiteralEqualityHelper;
6import tools.refinery.store.query.substitution.Substitution; 5import tools.refinery.store.query.substitution.Substitution;
6import tools.refinery.store.query.term.NodeSort;
7import tools.refinery.store.query.term.Variable;
7 8
8import java.util.List; 9import java.util.List;
9import java.util.Objects; 10import java.util.Objects;
10import java.util.Set; 11import java.util.Set;
11 12
12public abstract class CallLiteral<T extends RelationLike> implements Literal { 13public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> {
13 private final CallPolarity polarity; 14 private final CallPolarity polarity;
14 private final T target;
15 private final List<Variable> arguments;
16 15
17 protected CallLiteral(CallPolarity polarity, T target, List<Variable> arguments) { 16 public CallLiteral(CallPolarity polarity, Constraint target, List<Variable> arguments) {
18 if (arguments.size() != target.arity()) { 17 super(target, arguments);
19 throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(), 18 if (polarity.isTransitive()) {
20 target.arity(), arguments.size())); 19 if (target.arity() != 2) {
21 } 20 throw new IllegalArgumentException("Transitive closures can only take binary relations");
22 if (polarity.isTransitive() && target.arity() != 2) { 21 }
23 throw new IllegalArgumentException("Transitive closures can only take binary relations"); 22 var sorts = target.getSorts();
23 if (!sorts.get(0).equals(NodeSort.INSTANCE) || !sorts.get(1).equals(NodeSort.INSTANCE)) {
24 throw new IllegalArgumentException("Transitive closures can only be computed over nodes");
25 }
24 } 26 }
25 this.polarity = polarity; 27 this.polarity = polarity;
26 this.target = target;
27 this.arguments = arguments;
28 } 28 }
29 29
30 public CallPolarity getPolarity() { 30 public CallPolarity getPolarity() {
31 return polarity; 31 return polarity;
32 } 32 }
33 33
34 public abstract Class<T> getTargetType();
35
36 public T getTarget() {
37 return target;
38 }
39
40 public List<Variable> getArguments() {
41 return arguments;
42 }
43
44 @Override 34 @Override
45 public void collectAllVariables(Set<Variable> variables) { 35 public Set<Variable> getBoundVariables() {
46 if (polarity.isPositive()) { 36 return polarity.isPositive() ? Set.copyOf(getArguments()) : Set.of();
47 variables.addAll(arguments);
48 }
49 } 37 }
50 38
51 protected List<Variable> substituteArguments(Substitution substitution) { 39 @Override
52 return arguments.stream().map(substitution::getSubstitute).toList(); 40 protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) {
41 return new CallLiteral(polarity, getTarget(), substitutedArguments);
53 } 42 }
54 43
55 /** 44 @Override
56 * Compares the target of this call literal with another object. 45 public LiteralReduction getReduction() {
57 * 46 var reduction = getTarget().getReduction();
58 * @param helper Equality helper for comparing {@link Variable} and {@link tools.refinery.store.query.Dnf} 47 return polarity.isPositive() ? reduction : reduction.negate();
59 * instances.
60 * @param otherTarget The object to compare the target to.
61 * @return {@code true} if {@code otherTarget} is equal to the return value of {@link #getTarget()} according to
62 * {@code helper}, {@code false} otherwise.
63 */
64 protected boolean targetEquals(LiteralEqualityHelper helper, T otherTarget) {
65 return target.equals(otherTarget);
66 } 48 }
67 49
68 @Override 50 @Override
69 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { 51 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) {
70 if (other.getClass() != getClass()) { 52 if (!super.equalsWithSubstitution(helper, other)) {
71 return false; 53 return false;
72 } 54 }
73 var otherCallLiteral = (CallLiteral<?>) other; 55 var otherCallLiteral = (CallLiteral) other;
74 if (getTargetType() != otherCallLiteral.getTargetType() || polarity != otherCallLiteral.polarity) { 56 return polarity.equals(otherCallLiteral.polarity);
75 return false; 57 }
76 } 58
77 var arity = arguments.size(); 59 @Override
78 if (arity != otherCallLiteral.arguments.size()) { 60 public CallLiteral negate() {
79 return false; 61 return new CallLiteral(polarity.negate(), getTarget(), getArguments());
80 }
81 for (int i = 0; i < arity; i++) {
82 if (!helper.variableEqual(arguments.get(i), otherCallLiteral.arguments.get(i))) {
83 return false;
84 }
85 }
86 @SuppressWarnings("unchecked")
87 var otherTarget = (T) otherCallLiteral.target;
88 return targetEquals(helper, otherTarget);
89 } 62 }
90 63
91 @Override 64 @Override
92 public boolean equals(Object o) { 65 public boolean equals(Object o) {
93 if (this == o) return true; 66 if (this == o) return true;
94 if (o == null || getClass() != o.getClass()) return false; 67 if (o == null || getClass() != o.getClass()) return false;
95 CallLiteral<?> callAtom = (CallLiteral<?>) o; 68 if (!super.equals(o)) return false;
96 return polarity == callAtom.polarity && Objects.equals(target, callAtom.target) && 69 CallLiteral that = (CallLiteral) o;
97 Objects.equals(arguments, callAtom.arguments); 70 return polarity == that.polarity;
98 } 71 }
99 72
100 @Override 73 @Override
101 public int hashCode() { 74 public int hashCode() {
102 return Objects.hash(polarity, target, arguments); 75 return Objects.hash(super.hashCode(), polarity);
103 }
104
105 protected String targetToString() {
106 return "@%s %s".formatted(getTargetType().getSimpleName(), target.name());
107 } 76 }
108 77
109 @Override 78 @Override
@@ -112,12 +81,12 @@ public abstract class CallLiteral<T extends RelationLike> implements Literal {
112 if (!polarity.isPositive()) { 81 if (!polarity.isPositive()) {
113 builder.append("!("); 82 builder.append("!(");
114 } 83 }
115 builder.append(targetToString()); 84 builder.append(getTarget().toReferenceString());
116 if (polarity.isTransitive()) { 85 if (polarity.isTransitive()) {
117 builder.append("+"); 86 builder.append("+");
118 } 87 }
119 builder.append("("); 88 builder.append("(");
120 var argumentIterator = arguments.iterator(); 89 var argumentIterator = getArguments().iterator();
121 if (argumentIterator.hasNext()) { 90 if (argumentIterator.hasNext()) {
122 builder.append(argumentIterator.next()); 91 builder.append(argumentIterator.next());
123 while (argumentIterator.hasNext()) { 92 while (argumentIterator.hasNext()) {