diff options
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.java | 105 |
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 @@ | |||
1 | package tools.refinery.store.query.literal; | 1 | package tools.refinery.store.query.literal; |
2 | 2 | ||
3 | import tools.refinery.store.query.RelationLike; | 3 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.Variable; | ||
5 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
6 | import tools.refinery.store.query.substitution.Substitution; | 5 | import tools.refinery.store.query.substitution.Substitution; |
6 | import tools.refinery.store.query.term.NodeSort; | ||
7 | import tools.refinery.store.query.term.Variable; | ||
7 | 8 | ||
8 | import java.util.List; | 9 | import java.util.List; |
9 | import java.util.Objects; | 10 | import java.util.Objects; |
10 | import java.util.Set; | 11 | import java.util.Set; |
11 | 12 | ||
12 | public abstract class CallLiteral<T extends RelationLike> implements Literal { | 13 | public 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()) { |