diff options
author | 2023-06-25 21:42:43 +0200 | |
---|---|---|
committer | 2023-06-29 02:23:00 +0200 | |
commit | 79a3fd092c79efc204d2980b07728258372871c4 (patch) | |
tree | e515ff637c1d1288281284d62d33175dd5d19f35 | |
parent | feat: ordered query ResultSet (diff) | |
download | refinery-79a3fd092c79efc204d2980b07728258372871c4.tar.gz refinery-79a3fd092c79efc204d2980b07728258372871c4.tar.zst refinery-79a3fd092c79efc204d2980b07728258372871c4.zip |
refactor: query equality and hash code
Allow computing hash codes up to the renaming of variables.
Also introduces CheckLiteral instead of AssumeLiteral for more straightforward
naming.
38 files changed, 481 insertions, 237 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CheckEvaluator.java index cf127291..5dde41be 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/CheckEvaluator.java | |||
@@ -8,8 +8,8 @@ package tools.refinery.store.query.viatra.internal.pquery; | |||
8 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; |
9 | import tools.refinery.store.query.term.Term; | 9 | import tools.refinery.store.query.term.Term; |
10 | 10 | ||
11 | class AssumptionEvaluator extends TermEvaluator<Boolean> { | 11 | class CheckEvaluator extends TermEvaluator<Boolean> { |
12 | public AssumptionEvaluator(Term<Boolean> term) { | 12 | public CheckEvaluator(Term<Boolean> term) { |
13 | super(term); | 13 | super(term); |
14 | } | 14 | } |
15 | 15 | ||
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 5b0ea61d..38fd017e 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 | |||
@@ -141,8 +141,8 @@ public class Dnf2PQuery { | |||
141 | translateConstantLiteral(constantLiteral, body); | 141 | translateConstantLiteral(constantLiteral, body); |
142 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { | 142 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { |
143 | translateAssignLiteral(assignLiteral, body); | 143 | translateAssignLiteral(assignLiteral, body); |
144 | } else if (literal instanceof AssumeLiteral assumeLiteral) { | 144 | } else if (literal instanceof CheckLiteral checkLiteral) { |
145 | translateAssumeLiteral(assumeLiteral, body); | 145 | translateCheckLiteral(checkLiteral, body); |
146 | } else if (literal instanceof CountLiteral countLiteral) { | 146 | } else if (literal instanceof CountLiteral countLiteral) { |
147 | translateCountLiteral(countLiteral, body); | 147 | translateCountLiteral(countLiteral, body); |
148 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { | 148 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { |
@@ -153,9 +153,9 @@ public class Dnf2PQuery { | |||
153 | } | 153 | } |
154 | 154 | ||
155 | private void translateEquivalenceLiteral(EquivalenceLiteral equivalenceLiteral, PBody body) { | 155 | private void translateEquivalenceLiteral(EquivalenceLiteral equivalenceLiteral, PBody body) { |
156 | PVariable varSource = body.getOrCreateVariableByName(equivalenceLiteral.left().getUniqueName()); | 156 | PVariable varSource = body.getOrCreateVariableByName(equivalenceLiteral.getLeft().getUniqueName()); |
157 | PVariable varTarget = body.getOrCreateVariableByName(equivalenceLiteral.right().getUniqueName()); | 157 | PVariable varTarget = body.getOrCreateVariableByName(equivalenceLiteral.getRight().getUniqueName()); |
158 | if (equivalenceLiteral.positive()) { | 158 | if (equivalenceLiteral.isPositive()) { |
159 | new Equality(body, varSource, varTarget); | 159 | new Equality(body, varSource, varTarget); |
160 | } else { | 160 | } else { |
161 | new Inequality(body, varSource, varTarget); | 161 | new Inequality(body, varSource, varTarget); |
@@ -212,13 +212,13 @@ public class Dnf2PQuery { | |||
212 | } | 212 | } |
213 | 213 | ||
214 | private void translateConstantLiteral(ConstantLiteral constantLiteral, PBody body) { | 214 | private void translateConstantLiteral(ConstantLiteral constantLiteral, PBody body) { |
215 | var variable = body.getOrCreateVariableByName(constantLiteral.variable().getUniqueName()); | 215 | var variable = body.getOrCreateVariableByName(constantLiteral.getVariable().getUniqueName()); |
216 | new ConstantValue(body, variable, constantLiteral.nodeId()); | 216 | new ConstantValue(body, variable, constantLiteral.getNodeId()); |
217 | } | 217 | } |
218 | 218 | ||
219 | private <T> void translateAssignLiteral(AssignLiteral<T> assignLiteral, PBody body) { | 219 | private <T> void translateAssignLiteral(AssignLiteral<T> assignLiteral, PBody body) { |
220 | var variable = body.getOrCreateVariableByName(assignLiteral.variable().getUniqueName()); | 220 | var variable = body.getOrCreateVariableByName(assignLiteral.getVariable().getUniqueName()); |
221 | var term = assignLiteral.term(); | 221 | var term = assignLiteral.getTerm(); |
222 | if (term instanceof ConstantTerm<T> constantTerm) { | 222 | if (term instanceof ConstantTerm<T> constantTerm) { |
223 | new ConstantValue(body, variable, constantTerm.getValue()); | 223 | new ConstantValue(body, variable, constantTerm.getValue()); |
224 | } else { | 224 | } else { |
@@ -227,8 +227,8 @@ public class Dnf2PQuery { | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | private void translateAssumeLiteral(AssumeLiteral assumeLiteral, PBody body) { | 230 | private void translateCheckLiteral(CheckLiteral checkLiteral, PBody body) { |
231 | var evaluator = new AssumptionEvaluator(assumeLiteral.term()); | 231 | var evaluator = new CheckEvaluator(checkLiteral.getTerm()); |
232 | new ExpressionEvaluation(body, evaluator, null); | 232 | new ExpressionEvaluation(body, evaluator, null); |
233 | } | 233 | } |
234 | 234 | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java index 258127e7..c4f877c5 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java | |||
@@ -29,7 +29,7 @@ import static org.hamcrest.Matchers.is; | |||
29 | import static org.hamcrest.Matchers.nullValue; | 29 | import static org.hamcrest.Matchers.nullValue; |
30 | import static org.junit.jupiter.api.Assertions.assertAll; | 30 | import static org.junit.jupiter.api.Assertions.assertAll; |
31 | import static org.junit.jupiter.api.Assertions.assertThrows; | 31 | import static org.junit.jupiter.api.Assertions.assertThrows; |
32 | import static tools.refinery.store.query.literal.Literals.assume; | 32 | import static tools.refinery.store.query.literal.Literals.check; |
33 | import static tools.refinery.store.query.term.int_.IntTerms.*; | 33 | import static tools.refinery.store.query.term.int_.IntTerms.*; |
34 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertNullableResults; | 34 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertNullableResults; |
35 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; | 35 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; |
@@ -390,7 +390,7 @@ class FunctionalQueryTest { | |||
390 | var query = Query.of("InvalidAssume", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( | 390 | var query = Query.of("InvalidAssume", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( |
391 | personView.call(p1), | 391 | personView.call(p1), |
392 | ageView.call(p1, x), | 392 | ageView.call(p1, x), |
393 | assume(lessEq(div(constant(120), x), constant(5))) | 393 | check(lessEq(div(constant(120), x), constant(5))) |
394 | ))); | 394 | ))); |
395 | 395 | ||
396 | var store = ModelStore.builder() | 396 | var store = ModelStore.builder() |
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 25bcb0dc..be05b5e6 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 | |||
@@ -23,7 +23,7 @@ import tools.refinery.store.tuple.Tuple; | |||
23 | import java.util.List; | 23 | import java.util.List; |
24 | import java.util.Map; | 24 | import java.util.Map; |
25 | 25 | ||
26 | import static tools.refinery.store.query.literal.Literals.assume; | 26 | import static tools.refinery.store.query.literal.Literals.check; |
27 | import static tools.refinery.store.query.literal.Literals.not; | 27 | import static tools.refinery.store.query.literal.Literals.not; |
28 | import static tools.refinery.store.query.term.int_.IntTerms.constant; | 28 | import static tools.refinery.store.query.term.int_.IntTerms.constant; |
29 | import static tools.refinery.store.query.term.int_.IntTerms.greaterEq; | 29 | import static tools.refinery.store.query.term.int_.IntTerms.greaterEq; |
@@ -652,7 +652,7 @@ class QueryTest { | |||
652 | var query = Query.of("Constraint", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( | 652 | var query = Query.of("Constraint", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( |
653 | personView.call(p1), | 653 | personView.call(p1), |
654 | ageView.call(p1, x), | 654 | ageView.call(p1, x), |
655 | assume(greaterEq(x, constant(18))) | 655 | check(greaterEq(x, constant(18))) |
656 | ))); | 656 | ))); |
657 | 657 | ||
658 | var store = ModelStore.builder() | 658 | var store = ModelStore.builder() |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java index b5e7092b..1a45c20a 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java | |||
@@ -67,13 +67,13 @@ class ClausePostProcessor { | |||
67 | for (var literal : literals) { | 67 | for (var literal : literals) { |
68 | if (isPositiveEquivalence(literal)) { | 68 | if (isPositiveEquivalence(literal)) { |
69 | var equivalenceLiteral = (EquivalenceLiteral) literal; | 69 | var equivalenceLiteral = (EquivalenceLiteral) literal; |
70 | mergeVariables(equivalenceLiteral.left(), equivalenceLiteral.right()); | 70 | mergeVariables(equivalenceLiteral.getLeft(), equivalenceLiteral.getRight()); |
71 | } | 71 | } |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | private static boolean isPositiveEquivalence(Literal literal) { | 75 | private static boolean isPositiveEquivalence(Literal literal) { |
76 | return literal instanceof EquivalenceLiteral equivalenceLiteral && equivalenceLiteral.positive(); | 76 | return literal instanceof EquivalenceLiteral equivalenceLiteral && equivalenceLiteral.isPositive(); |
77 | } | 77 | } |
78 | 78 | ||
79 | private void mergeVariables(NodeVariable left, NodeVariable right) { | 79 | private void mergeVariables(NodeVariable left, NodeVariable right) { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java index 50b245f7..7a3e2a1e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java | |||
@@ -6,9 +6,11 @@ | |||
6 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.literal.Reduction; | ||
10 | import tools.refinery.store.query.equality.DnfEqualityChecker; | 9 | import tools.refinery.store.query.equality.DnfEqualityChecker; |
11 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
11 | import tools.refinery.store.query.equality.SubstitutingLiteralEqualityHelper; | ||
12 | import tools.refinery.store.query.equality.SubstitutingLiteralHashCodeHelper; | ||
13 | import tools.refinery.store.query.literal.Reduction; | ||
12 | import tools.refinery.store.query.term.Parameter; | 14 | import tools.refinery.store.query.term.Parameter; |
13 | import tools.refinery.store.query.term.Variable; | 15 | import tools.refinery.store.query.term.Variable; |
14 | 16 | ||
@@ -129,7 +131,7 @@ public final class Dnf implements Constraint { | |||
129 | return false; | 131 | return false; |
130 | } | 132 | } |
131 | for (int i = 0; i < numClauses; i++) { | 133 | for (int i = 0; i < numClauses; i++) { |
132 | var literalEqualityHelper = new LiteralEqualityHelper(callEqualityChecker, symbolicParameters, | 134 | var literalEqualityHelper = new SubstitutingLiteralEqualityHelper(callEqualityChecker, symbolicParameters, |
133 | other.symbolicParameters); | 135 | other.symbolicParameters); |
134 | if (!clauses.get(i).equalsWithSubstitution(literalEqualityHelper, other.clauses.get(i))) { | 136 | if (!clauses.get(i).equalsWithSubstitution(literalEqualityHelper, other.clauses.get(i))) { |
135 | return false; | 137 | return false; |
@@ -146,6 +148,18 @@ public final class Dnf implements Constraint { | |||
146 | return false; | 148 | return false; |
147 | } | 149 | } |
148 | 150 | ||
151 | public int hashCodeWithSubstitution() { | ||
152 | var helper = new SubstitutingLiteralHashCodeHelper(); | ||
153 | int result = 0; | ||
154 | for (var symbolicParameter : symbolicParameters) { | ||
155 | result = result * 31 + symbolicParameter.hashCodeWithSubstitution(helper); | ||
156 | } | ||
157 | for (var clause : clauses) { | ||
158 | result = result * 31 + clause.hashCodeWithSubstitution(helper); | ||
159 | } | ||
160 | return result; | ||
161 | } | ||
162 | |||
149 | @Override | 163 | @Override |
150 | public String toString() { | 164 | public String toString() { |
151 | return "%s/%d".formatted(name(), arity()); | 165 | return "%s/%d".formatted(name(), arity()); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java index fdd0d47c..94327bad 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.literal.Literal; | 10 | import tools.refinery.store.query.literal.Literal; |
10 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
11 | 12 | ||
@@ -25,4 +26,12 @@ public record DnfClause(Set<Variable> positiveVariables, List<Literal> literals) | |||
25 | } | 26 | } |
26 | return true; | 27 | return true; |
27 | } | 28 | } |
29 | |||
30 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
31 | int result = 0; | ||
32 | for (var literal : literals) { | ||
33 | result = result * 31 + literal.hashCodeWithSubstitution(helper); | ||
34 | } | ||
35 | return result; | ||
36 | } | ||
28 | } | 37 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java index e0d3ba1f..1e96cf27 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
8 | import tools.refinery.store.query.term.Parameter; | 9 | import tools.refinery.store.query.term.Parameter; |
9 | import tools.refinery.store.query.term.ParameterDirection; | 10 | import tools.refinery.store.query.term.ParameterDirection; |
10 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
@@ -27,6 +28,10 @@ public final class SymbolicParameter extends Parameter { | |||
27 | return variable.isUnifiable(); | 28 | return variable.isUnifiable(); |
28 | } | 29 | } |
29 | 30 | ||
31 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
32 | return Objects.hash(super.hashCode(), helper.getVariableHashCode(variable)); | ||
33 | } | ||
34 | |||
30 | @Override | 35 | @Override |
31 | public String toString() { | 36 | public String toString() { |
32 | var direction = getDirection(); | 37 | var direction = getDirection(); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java index 1eeb5723..a212b3f5 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java | |||
@@ -38,7 +38,7 @@ public class DeepDnfEqualityChecker implements DnfEqualityChecker { | |||
38 | return false; | 38 | return false; |
39 | } | 39 | } |
40 | for (int i = 0; i < numClauses; i++) { | 40 | for (int i = 0; i < numClauses; i++) { |
41 | var literalEqualityHelper = new LiteralEqualityHelper(this, symbolicParameters, | 41 | var literalEqualityHelper = new SubstitutingLiteralEqualityHelper(this, symbolicParameters, |
42 | other.getSymbolicParameters()); | 42 | other.getSymbolicParameters()); |
43 | if (!equalsWithSubstitutionRaw(literalEqualityHelper, clauses.get(i), other.getClauses().get(i))) { | 43 | if (!equalsWithSubstitutionRaw(literalEqualityHelper, clauses.get(i), other.getClauses().get(i))) { |
44 | return false; | 44 | return false; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java index 4a8bee3b..e2cfd79b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java | |||
@@ -7,7 +7,11 @@ package tools.refinery.store.query.equality; | |||
7 | 7 | ||
8 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
9 | 9 | ||
10 | import java.util.Objects; | ||
11 | |||
10 | @FunctionalInterface | 12 | @FunctionalInterface |
11 | public interface DnfEqualityChecker { | 13 | public interface DnfEqualityChecker { |
14 | DnfEqualityChecker DEFAULT = Objects::equals; | ||
15 | |||
12 | boolean dnfEqual(Dnf left, Dnf right); | 16 | boolean dnfEqual(Dnf left, Dnf right); |
13 | } | 17 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java index 9315fb30..5abc76ce 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java | |||
@@ -6,49 +6,22 @@ | |||
6 | package tools.refinery.store.query.equality; | 6 | package tools.refinery.store.query.equality; |
7 | 7 | ||
8 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
9 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
10 | import tools.refinery.store.query.term.Variable; | 9 | import tools.refinery.store.query.term.Variable; |
11 | 10 | ||
12 | import java.util.HashMap; | 11 | import java.util.Objects; |
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | 12 | ||
16 | public class LiteralEqualityHelper { | 13 | public interface LiteralEqualityHelper extends DnfEqualityChecker { |
17 | private final DnfEqualityChecker dnfEqualityChecker; | 14 | LiteralEqualityHelper DEFAULT = new LiteralEqualityHelper() { |
18 | private final Map<Variable, Variable> leftToRight; | 15 | @Override |
19 | private final Map<Variable, Variable> rightToLeft; | 16 | public boolean variableEqual(Variable left, Variable right) { |
20 | 17 | return Objects.equals(left, right); | |
21 | public LiteralEqualityHelper(DnfEqualityChecker dnfEqualityChecker, List<SymbolicParameter> leftParameters, | ||
22 | List<SymbolicParameter> rightParameters) { | ||
23 | this.dnfEqualityChecker = dnfEqualityChecker; | ||
24 | var arity = leftParameters.size(); | ||
25 | if (arity != rightParameters.size()) { | ||
26 | throw new IllegalArgumentException("Parameter lists have unequal length"); | ||
27 | } | ||
28 | leftToRight = new HashMap<>(arity); | ||
29 | rightToLeft = new HashMap<>(arity); | ||
30 | for (int i = 0; i < arity; i++) { | ||
31 | if (!variableEqual(leftParameters.get(i).getVariable(), rightParameters.get(i).getVariable())) { | ||
32 | throw new IllegalArgumentException("Parameter lists cannot be unified: duplicate parameter " + i); | ||
33 | } | ||
34 | } | 18 | } |
35 | } | ||
36 | |||
37 | public boolean dnfEqual(Dnf left, Dnf right) { | ||
38 | return dnfEqualityChecker.dnfEqual(left, right); | ||
39 | } | ||
40 | 19 | ||
41 | public boolean variableEqual(Variable left, Variable right) { | 20 | @Override |
42 | if (checkMapping(leftToRight, left, right) && checkMapping(rightToLeft, right, left)) { | 21 | public boolean dnfEqual(Dnf left, Dnf right) { |
43 | leftToRight.put(left, right); | 22 | return DnfEqualityChecker.DEFAULT.dnfEqual(left, right); |
44 | rightToLeft.put(right, left); | ||
45 | return true; | ||
46 | } | 23 | } |
47 | return false; | 24 | }; |
48 | } | ||
49 | 25 | ||
50 | private static boolean checkMapping(Map<Variable, Variable> map, Variable key, Variable expectedValue) { | 26 | boolean variableEqual(Variable left, Variable right); |
51 | var currentValue = map.get(key); | ||
52 | return currentValue == null || currentValue.equals(expectedValue); | ||
53 | } | ||
54 | } | 27 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java new file mode 100644 index 00000000..5495160a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | import java.util.Objects; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface LiteralHashCodeHelper { | ||
14 | LiteralHashCodeHelper DEFAULT = Objects::hashCode; | ||
15 | |||
16 | int getVariableHashCode(Variable variable); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java new file mode 100644 index 00000000..50a79e07 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.HashMap; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | |||
16 | public class SubstitutingLiteralEqualityHelper implements LiteralEqualityHelper { | ||
17 | private final DnfEqualityChecker dnfEqualityChecker; | ||
18 | private final Map<Variable, Variable> leftToRight; | ||
19 | private final Map<Variable, Variable> rightToLeft; | ||
20 | |||
21 | public SubstitutingLiteralEqualityHelper(DnfEqualityChecker dnfEqualityChecker, | ||
22 | List<SymbolicParameter> leftParameters, | ||
23 | List<SymbolicParameter> rightParameters) { | ||
24 | this.dnfEqualityChecker = dnfEqualityChecker; | ||
25 | var arity = leftParameters.size(); | ||
26 | if (arity != rightParameters.size()) { | ||
27 | throw new IllegalArgumentException("Parameter lists have unequal length"); | ||
28 | } | ||
29 | leftToRight = new HashMap<>(arity); | ||
30 | rightToLeft = new HashMap<>(arity); | ||
31 | for (int i = 0; i < arity; i++) { | ||
32 | if (!variableEqual(leftParameters.get(i).getVariable(), rightParameters.get(i).getVariable())) { | ||
33 | throw new IllegalArgumentException("Parameter lists cannot be unified: duplicate parameter " + i); | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean dnfEqual(Dnf left, Dnf right) { | ||
40 | return dnfEqualityChecker.dnfEqual(left, right); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public boolean variableEqual(Variable left, Variable right) { | ||
45 | if (left.tryGetType().equals(right.tryGetType()) && | ||
46 | checkMapping(leftToRight, left, right) && | ||
47 | checkMapping(rightToLeft, right, left)) { | ||
48 | leftToRight.put(left, right); | ||
49 | rightToLeft.put(right, left); | ||
50 | return true; | ||
51 | } | ||
52 | return false; | ||
53 | } | ||
54 | |||
55 | private static boolean checkMapping(Map<Variable, Variable> map, Variable key, Variable expectedValue) { | ||
56 | var currentValue = map.get(key); | ||
57 | return currentValue == null || currentValue.equals(expectedValue); | ||
58 | } | ||
59 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java new file mode 100644 index 00000000..a40ecd58 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | import java.util.LinkedHashMap; | ||
11 | import java.util.Map; | ||
12 | |||
13 | public class SubstitutingLiteralHashCodeHelper implements LiteralHashCodeHelper { | ||
14 | private final Map<Variable, Integer> assignedHashCodes = new LinkedHashMap<>(); | ||
15 | |||
16 | // 0 is for {@code null}, so we start with 1. | ||
17 | private int next = 1; | ||
18 | |||
19 | @Override | ||
20 | public int getVariableHashCode(Variable variable) { | ||
21 | if (variable == null) { | ||
22 | return 0; | ||
23 | } | ||
24 | return assignedHashCodes.computeIfAbsent(variable, key -> { | ||
25 | int sequenceNumber = next; | ||
26 | next++; | ||
27 | return variable.hashCodeWithSubstitution(sequenceNumber); | ||
28 | }); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java index 8ef8e8b4..a355dc3b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java | |||
@@ -7,13 +7,14 @@ package tools.refinery.store.query.literal; | |||
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | 11 | import tools.refinery.store.query.substitution.Substitution; |
11 | import tools.refinery.store.query.term.ParameterDirection; | 12 | import tools.refinery.store.query.term.ParameterDirection; |
12 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
13 | 14 | ||
14 | import java.util.*; | 15 | import java.util.*; |
15 | 16 | ||
16 | public abstract class AbstractCallLiteral implements Literal { | 17 | public abstract class AbstractCallLiteral extends AbstractLiteral { |
17 | private final Constraint target; | 18 | private final Constraint target; |
18 | private final List<Variable> arguments; | 19 | private final List<Variable> arguments; |
19 | private final Set<Variable> inArguments; | 20 | private final Set<Variable> inArguments; |
@@ -112,7 +113,7 @@ public abstract class AbstractCallLiteral implements Literal { | |||
112 | 113 | ||
113 | @Override | 114 | @Override |
114 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | 115 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { |
115 | if (other == null || getClass() != other.getClass()) { | 116 | if (!super.equalsWithSubstitution(helper, other)) { |
116 | return false; | 117 | return false; |
117 | } | 118 | } |
118 | var otherCallLiteral = (AbstractCallLiteral) other; | 119 | var otherCallLiteral = (AbstractCallLiteral) other; |
@@ -129,15 +130,11 @@ public abstract class AbstractCallLiteral implements Literal { | |||
129 | } | 130 | } |
130 | 131 | ||
131 | @Override | 132 | @Override |
132 | public boolean equals(Object o) { | 133 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
133 | if (this == o) return true; | 134 | int result = super.hashCodeWithSubstitution(helper) * 31 + target.hashCode(); |
134 | if (o == null || getClass() != o.getClass()) return false; | 135 | for (var argument : arguments) { |
135 | AbstractCallLiteral that = (AbstractCallLiteral) o; | 136 | result = result * 31 + helper.getVariableHashCode(argument); |
136 | return target.equals(that.target) && arguments.equals(that.arguments); | 137 | } |
137 | } | 138 | return result; |
138 | |||
139 | @Override | ||
140 | public int hashCode() { | ||
141 | return Objects.hash(getClass(), target, arguments); | ||
142 | } | 139 | } |
143 | } | 140 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java new file mode 100644 index 00000000..7d3cabd7 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | |||
11 | public abstract class AbstractLiteral implements Literal { | ||
12 | @Override | ||
13 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
14 | return other != null && getClass() == other.getClass(); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
19 | return getClass().hashCode(); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public boolean equals(Object o) { | ||
24 | if (this == o) return true; | ||
25 | if (o == null || getClass() != o.getClass()) return false; | ||
26 | AbstractLiteral that = (AbstractLiteral) o; | ||
27 | return equalsWithSubstitution(LiteralEqualityHelper.DEFAULT, that); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public int hashCode() { | ||
32 | return hashCodeWithSubstitution(LiteralHashCodeHelper.DEFAULT); | ||
33 | } | ||
34 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java index 3a5eb5c7..615fd493 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java | |||
@@ -7,6 +7,7 @@ package tools.refinery.store.query.literal; | |||
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | 11 | import tools.refinery.store.query.substitution.Substitution; |
11 | import tools.refinery.store.query.term.*; | 12 | import tools.refinery.store.query.term.*; |
12 | 13 | ||
@@ -14,6 +15,8 @@ import java.util.List; | |||
14 | import java.util.Objects; | 15 | import java.util.Objects; |
15 | import java.util.Set; | 16 | import java.util.Set; |
16 | 17 | ||
18 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
19 | @SuppressWarnings("squid:S2160") | ||
17 | public class AggregationLiteral<R, T> extends AbstractCallLiteral { | 20 | public class AggregationLiteral<R, T> extends AbstractCallLiteral { |
18 | private final DataVariable<R> resultVariable; | 21 | private final DataVariable<R> resultVariable; |
19 | private final DataVariable<T> inputVariable; | 22 | private final DataVariable<T> inputVariable; |
@@ -100,18 +103,9 @@ public class AggregationLiteral<R, T> extends AbstractCallLiteral { | |||
100 | } | 103 | } |
101 | 104 | ||
102 | @Override | 105 | @Override |
103 | public boolean equals(Object o) { | 106 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
104 | if (this == o) return true; | 107 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(resultVariable), |
105 | if (o == null || getClass() != o.getClass()) return false; | 108 | helper.getVariableHashCode(inputVariable), aggregator); |
106 | if (!super.equals(o)) return false; | ||
107 | AggregationLiteral<?, ?> that = (AggregationLiteral<?, ?>) o; | ||
108 | return resultVariable.equals(that.resultVariable) && inputVariable.equals(that.inputVariable) && | ||
109 | aggregator.equals(that.aggregator); | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public int hashCode() { | ||
114 | return Objects.hash(super.hashCode(), resultVariable, inputVariable, aggregator); | ||
115 | } | 109 | } |
116 | 110 | ||
117 | @Override | 111 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java index dbf999a2..d8a4b494 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.DataVariable; | 11 | import tools.refinery.store.query.term.DataVariable; |
11 | import tools.refinery.store.query.term.Term; | 12 | import tools.refinery.store.query.term.Term; |
@@ -15,8 +16,11 @@ import java.util.Collections; | |||
15 | import java.util.Objects; | 16 | import java.util.Objects; |
16 | import java.util.Set; | 17 | import java.util.Set; |
17 | 18 | ||
18 | public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implements Literal { | 19 | public class AssignLiteral<T> extends AbstractLiteral { |
19 | public AssignLiteral { | 20 | private final DataVariable<T> variable; |
21 | private final Term<T> term; | ||
22 | |||
23 | public AssignLiteral(DataVariable<T> variable, Term<T> term) { | ||
20 | if (!term.getType().equals(variable.getType())) { | 24 | if (!term.getType().equals(variable.getType())) { |
21 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( | 25 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( |
22 | term, variable.getType().getName(), term.getType().getName())); | 26 | term, variable.getType().getName(), term.getType().getName())); |
@@ -26,6 +30,16 @@ public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implement | |||
26 | throw new IllegalArgumentException("Result variable %s must not appear in the term %s".formatted( | 30 | throw new IllegalArgumentException("Result variable %s must not appear in the term %s".formatted( |
27 | variable, term)); | 31 | variable, term)); |
28 | } | 32 | } |
33 | this.variable = variable; | ||
34 | this.term = term; | ||
35 | } | ||
36 | |||
37 | public DataVariable<T> getVariable() { | ||
38 | return variable; | ||
39 | } | ||
40 | |||
41 | public Term<T> getTerm() { | ||
42 | return term; | ||
29 | } | 43 | } |
30 | 44 | ||
31 | @Override | 45 | @Override |
@@ -53,27 +67,19 @@ public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implement | |||
53 | if (other == null || getClass() != other.getClass()) { | 67 | if (other == null || getClass() != other.getClass()) { |
54 | return false; | 68 | return false; |
55 | } | 69 | } |
56 | var otherLetLiteral = (AssignLiteral<?>) other; | 70 | var otherAssignLiteral = (AssignLiteral<?>) other; |
57 | return helper.variableEqual(variable, otherLetLiteral.variable) && term.equalsWithSubstitution(helper, | 71 | return helper.variableEqual(variable, otherAssignLiteral.variable) && |
58 | otherLetLiteral.term); | 72 | term.equalsWithSubstitution(helper, otherAssignLiteral.term); |
59 | } | ||
60 | |||
61 | @Override | ||
62 | public String toString() { | ||
63 | return "%s is (%s)".formatted(variable, term); | ||
64 | } | 73 | } |
65 | 74 | ||
66 | @Override | 75 | @Override |
67 | public boolean equals(Object obj) { | 76 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
68 | if (obj == this) return true; | 77 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(variable), |
69 | if (obj == null || obj.getClass() != this.getClass()) return false; | 78 | term.hashCodeWithSubstitution(helper)); |
70 | var that = (AssignLiteral<?>) obj; | ||
71 | return Objects.equals(this.variable, that.variable) && | ||
72 | Objects.equals(this.term, that.term); | ||
73 | } | 79 | } |
74 | 80 | ||
75 | @Override | 81 | @Override |
76 | public int hashCode() { | 82 | public String toString() { |
77 | return Objects.hash(getClass(), variable, term); | 83 | return "%s is (%s)".formatted(variable, term); |
78 | } | 84 | } |
79 | } | 85 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java index f312d202..6cd320da 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
11 | 12 | ||
@@ -53,6 +54,11 @@ public enum BooleanLiteral implements CanNegate<BooleanLiteral> { | |||
53 | } | 54 | } |
54 | 55 | ||
55 | @Override | 56 | @Override |
57 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
58 | return hashCode(); | ||
59 | } | ||
60 | |||
61 | @Override | ||
56 | public String toString() { | 62 | public String toString() { |
57 | return Boolean.toString(value); | 63 | return Boolean.toString(value); |
58 | } | 64 | } |
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 29772aee..a311dada 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 | |||
@@ -7,12 +7,15 @@ package tools.refinery.store.query.literal; | |||
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | 11 | import tools.refinery.store.query.substitution.Substitution; |
11 | import tools.refinery.store.query.term.ParameterDirection; | 12 | import tools.refinery.store.query.term.ParameterDirection; |
12 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
13 | 14 | ||
14 | import java.util.*; | 15 | import java.util.*; |
15 | 16 | ||
17 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
18 | @SuppressWarnings("squid:S2160") | ||
16 | public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> { | 19 | public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> { |
17 | private final CallPolarity polarity; | 20 | private final CallPolarity polarity; |
18 | 21 | ||
@@ -85,22 +88,13 @@ public final class CallLiteral extends AbstractCallLiteral implements CanNegate< | |||
85 | } | 88 | } |
86 | 89 | ||
87 | @Override | 90 | @Override |
88 | public CallLiteral negate() { | 91 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
89 | return new CallLiteral(polarity.negate(), getTarget(), getArguments()); | 92 | return Objects.hash(super.hashCodeWithSubstitution(helper), polarity); |
90 | } | 93 | } |
91 | 94 | ||
92 | @Override | 95 | @Override |
93 | public boolean equals(Object o) { | 96 | public CallLiteral negate() { |
94 | if (this == o) return true; | 97 | return new CallLiteral(polarity.negate(), getTarget(), getArguments()); |
95 | if (o == null || getClass() != o.getClass()) return false; | ||
96 | if (!super.equals(o)) return false; | ||
97 | CallLiteral that = (CallLiteral) o; | ||
98 | return polarity == that.polarity; | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public int hashCode() { | ||
103 | return Objects.hash(super.hashCode(), polarity); | ||
104 | } | 98 | } |
105 | 99 | ||
106 | @Override | 100 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CheckLiteral.java index 1ca04c77..1271183a 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CheckLiteral.java | |||
@@ -6,21 +6,31 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.ConstantTerm; | 11 | import tools.refinery.store.query.term.ConstantTerm; |
11 | import tools.refinery.store.query.term.Term; | 12 | import tools.refinery.store.query.term.Term; |
12 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
14 | import tools.refinery.store.query.term.bool.BoolNotTerm; | ||
15 | import tools.refinery.store.query.term.bool.BoolTerms; | ||
13 | 16 | ||
14 | import java.util.Collections; | 17 | import java.util.Collections; |
15 | import java.util.Objects; | 18 | import java.util.Objects; |
16 | import java.util.Set; | 19 | import java.util.Set; |
17 | 20 | ||
18 | public record AssumeLiteral(Term<Boolean> term) implements Literal { | 21 | public class CheckLiteral extends AbstractLiteral implements CanNegate<CheckLiteral> { |
19 | public AssumeLiteral { | 22 | private final Term<Boolean> term; |
23 | |||
24 | public CheckLiteral(Term<Boolean> term) { | ||
20 | if (!term.getType().equals(Boolean.class)) { | 25 | if (!term.getType().equals(Boolean.class)) { |
21 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( | 26 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( |
22 | term, Boolean.class.getName(), term.getType().getName())); | 27 | term, Boolean.class.getName(), term.getType().getName())); |
23 | } | 28 | } |
29 | this.term = term; | ||
30 | } | ||
31 | |||
32 | public Term<Boolean> getTerm() { | ||
33 | return term; | ||
24 | } | 34 | } |
25 | 35 | ||
26 | @Override | 36 | @Override |
@@ -38,10 +48,17 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal { | |||
38 | return Set.of(); | 48 | return Set.of(); |
39 | } | 49 | } |
40 | 50 | ||
41 | |||
42 | @Override | 51 | @Override |
43 | public Literal substitute(Substitution substitution) { | 52 | public Literal substitute(Substitution substitution) { |
44 | return new AssumeLiteral(term.substitute(substitution)); | 53 | return new CheckLiteral(term.substitute(substitution)); |
54 | } | ||
55 | |||
56 | @Override | ||
57 | public CheckLiteral negate() { | ||
58 | if (term instanceof BoolNotTerm notTerm) { | ||
59 | return new CheckLiteral(notTerm.getBody()); | ||
60 | } | ||
61 | return new CheckLiteral(BoolTerms.not(term)); | ||
45 | } | 62 | } |
46 | 63 | ||
47 | @Override | 64 | @Override |
@@ -49,11 +66,16 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal { | |||
49 | if (other == null || getClass() != other.getClass()) { | 66 | if (other == null || getClass() != other.getClass()) { |
50 | return false; | 67 | return false; |
51 | } | 68 | } |
52 | var otherAssumeLiteral = (AssumeLiteral) other; | 69 | var otherAssumeLiteral = (CheckLiteral) other; |
53 | return term.equalsWithSubstitution(helper, otherAssumeLiteral.term); | 70 | return term.equalsWithSubstitution(helper, otherAssumeLiteral.term); |
54 | } | 71 | } |
55 | 72 | ||
56 | @Override | 73 | @Override |
74 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
75 | return Objects.hash(super.hashCodeWithSubstitution(helper), term.hashCodeWithSubstitution(helper)); | ||
76 | } | ||
77 | |||
78 | @Override | ||
57 | public Literal reduce() { | 79 | public Literal reduce() { |
58 | if (term instanceof ConstantTerm<Boolean> constantTerm) { | 80 | if (term instanceof ConstantTerm<Boolean> constantTerm) { |
59 | // Return {@link BooleanLiteral#FALSE} for {@code false} or {@code null} literals. | 81 | // Return {@link BooleanLiteral#FALSE} for {@code false} or {@code null} literals. |
@@ -67,17 +89,4 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal { | |||
67 | public String toString() { | 89 | public String toString() { |
68 | return "(%s)".formatted(term); | 90 | return "(%s)".formatted(term); |
69 | } | 91 | } |
70 | |||
71 | @Override | ||
72 | public boolean equals(Object obj) { | ||
73 | if (obj == this) return true; | ||
74 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
75 | var that = (AssumeLiteral) obj; | ||
76 | return Objects.equals(this.term, that.term); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public int hashCode() { | ||
81 | return Objects.hash(getClass(), term); | ||
82 | } | ||
83 | } | 92 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java index 73545620..d83bd584 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.NodeVariable; | 11 | import tools.refinery.store.query.term.NodeVariable; |
11 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
@@ -13,7 +14,24 @@ import tools.refinery.store.query.term.Variable; | |||
13 | import java.util.Objects; | 14 | import java.util.Objects; |
14 | import java.util.Set; | 15 | import java.util.Set; |
15 | 16 | ||
16 | public record ConstantLiteral(NodeVariable variable, int nodeId) implements Literal { | 17 | public class ConstantLiteral extends AbstractLiteral { |
18 | private final NodeVariable variable; | ||
19 | private final int nodeId; | ||
20 | |||
21 | public ConstantLiteral(NodeVariable variable, int nodeId) { | ||
22 | this.variable = variable; | ||
23 | this.nodeId = nodeId; | ||
24 | } | ||
25 | |||
26 | public NodeVariable getVariable() { | ||
27 | return variable; | ||
28 | } | ||
29 | |||
30 | public int getNodeId() { | ||
31 | return nodeId; | ||
32 | } | ||
33 | |||
34 | |||
17 | @Override | 35 | @Override |
18 | public Set<Variable> getOutputVariables() { | 36 | public Set<Variable> getOutputVariables() { |
19 | return Set.of(variable); | 37 | return Set.of(variable); |
@@ -43,23 +61,13 @@ public record ConstantLiteral(NodeVariable variable, int nodeId) implements Lite | |||
43 | return helper.variableEqual(variable, otherConstantLiteral.variable) && nodeId == otherConstantLiteral.nodeId; | 61 | return helper.variableEqual(variable, otherConstantLiteral.variable) && nodeId == otherConstantLiteral.nodeId; |
44 | } | 62 | } |
45 | 63 | ||
46 | |||
47 | @Override | ||
48 | public String toString() { | ||
49 | return "%s === @Constant %d".formatted(variable, nodeId); | ||
50 | } | ||
51 | |||
52 | @Override | 64 | @Override |
53 | public boolean equals(Object obj) { | 65 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
54 | if (obj == this) return true; | 66 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(variable), nodeId); |
55 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
56 | var that = (ConstantLiteral) obj; | ||
57 | return Objects.equals(this.variable, that.variable) && | ||
58 | this.nodeId == that.nodeId; | ||
59 | } | 67 | } |
60 | 68 | ||
61 | @Override | 69 | @Override |
62 | public int hashCode() { | 70 | public String toString() { |
63 | return Objects.hash(getClass(), variable, nodeId); | 71 | return "%s === @Constant %d".formatted(variable, nodeId); |
64 | } | 72 | } |
65 | } | 73 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java index 4d4749c8..ac4b8788 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java | |||
@@ -7,6 +7,7 @@ package tools.refinery.store.query.literal; | |||
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | 11 | import tools.refinery.store.query.substitution.Substitution; |
11 | import tools.refinery.store.query.term.DataVariable; | 12 | import tools.refinery.store.query.term.DataVariable; |
12 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
@@ -16,6 +17,8 @@ import java.util.List; | |||
16 | import java.util.Objects; | 17 | import java.util.Objects; |
17 | import java.util.Set; | 18 | import java.util.Set; |
18 | 19 | ||
20 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
21 | @SuppressWarnings("squid:S2160") | ||
19 | public class CountLiteral extends AbstractCallLiteral { | 22 | public class CountLiteral extends AbstractCallLiteral { |
20 | private final DataVariable<Integer> resultVariable; | 23 | private final DataVariable<Integer> resultVariable; |
21 | 24 | ||
@@ -68,17 +71,8 @@ public class CountLiteral extends AbstractCallLiteral { | |||
68 | } | 71 | } |
69 | 72 | ||
70 | @Override | 73 | @Override |
71 | public boolean equals(Object o) { | 74 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
72 | if (this == o) return true; | 75 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(resultVariable)); |
73 | if (o == null || getClass() != o.getClass()) return false; | ||
74 | if (!super.equals(o)) return false; | ||
75 | CountLiteral that = (CountLiteral) o; | ||
76 | return resultVariable.equals(that.resultVariable); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public int hashCode() { | ||
81 | return Objects.hash(super.hashCode(), resultVariable); | ||
82 | } | 76 | } |
83 | 77 | ||
84 | @Override | 78 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java index 28ba7625..61b7344f 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.NodeVariable; | 11 | import tools.refinery.store.query.term.NodeVariable; |
11 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
@@ -13,8 +14,29 @@ import tools.refinery.store.query.term.Variable; | |||
13 | import java.util.Objects; | 14 | import java.util.Objects; |
14 | import java.util.Set; | 15 | import java.util.Set; |
15 | 16 | ||
16 | public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariable right) | 17 | public final class EquivalenceLiteral extends AbstractLiteral implements CanNegate<EquivalenceLiteral> { |
17 | implements CanNegate<EquivalenceLiteral> { | 18 | private final boolean positive; |
19 | private final NodeVariable left; | ||
20 | private final NodeVariable right; | ||
21 | |||
22 | public EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariable right) { | ||
23 | this.positive = positive; | ||
24 | this.left = left; | ||
25 | this.right = right; | ||
26 | } | ||
27 | |||
28 | public boolean isPositive() { | ||
29 | return positive; | ||
30 | } | ||
31 | |||
32 | public NodeVariable getLeft() { | ||
33 | return left; | ||
34 | } | ||
35 | |||
36 | public NodeVariable getRight() { | ||
37 | return right; | ||
38 | } | ||
39 | |||
18 | @Override | 40 | @Override |
19 | public Set<Variable> getOutputVariables() { | 41 | public Set<Variable> getOutputVariables() { |
20 | return Set.of(left); | 42 | return Set.of(left); |
@@ -55,27 +77,18 @@ public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariab | |||
55 | return false; | 77 | return false; |
56 | } | 78 | } |
57 | var otherEquivalenceLiteral = (EquivalenceLiteral) other; | 79 | var otherEquivalenceLiteral = (EquivalenceLiteral) other; |
58 | return helper.variableEqual(left, otherEquivalenceLiteral.left) && helper.variableEqual(right, | 80 | return helper.variableEqual(left, otherEquivalenceLiteral.left) && |
59 | otherEquivalenceLiteral.right); | 81 | helper.variableEqual(right, otherEquivalenceLiteral.right); |
60 | } | ||
61 | |||
62 | @Override | ||
63 | public String toString() { | ||
64 | return "%s %s %s".formatted(left, positive ? "===" : "!==", right); | ||
65 | } | 82 | } |
66 | 83 | ||
67 | @Override | 84 | @Override |
68 | public boolean equals(Object obj) { | 85 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
69 | if (obj == this) return true; | 86 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(left), |
70 | if (obj == null || obj.getClass() != this.getClass()) return false; | 87 | helper.getVariableHashCode(right)); |
71 | var that = (EquivalenceLiteral) obj; | ||
72 | return this.positive == that.positive && | ||
73 | Objects.equals(this.left, that.left) && | ||
74 | Objects.equals(this.right, that.right); | ||
75 | } | 88 | } |
76 | 89 | ||
77 | @Override | 90 | @Override |
78 | public int hashCode() { | 91 | public String toString() { |
79 | return Objects.hash(getClass(), positive, left, right); | 92 | return "%s %s %s".formatted(left, positive ? "===" : "!==", right); |
80 | } | 93 | } |
81 | } | 94 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java index ce6c11fe..cb16ab00 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
11 | 12 | ||
@@ -26,4 +27,6 @@ public interface Literal { | |||
26 | 27 | ||
27 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") | 28 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") |
28 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other); | 29 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other); |
30 | |||
31 | int hashCodeWithSubstitution(LiteralHashCodeHelper helper); | ||
29 | } | 32 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java index b3a87811..6056da45 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java | |||
@@ -16,7 +16,7 @@ public final class Literals { | |||
16 | return literal.negate(); | 16 | return literal.negate(); |
17 | } | 17 | } |
18 | 18 | ||
19 | public static AssumeLiteral assume(Term<Boolean> term) { | 19 | public static CheckLiteral check(Term<Boolean> term) { |
20 | return new AssumeLiteral(term); | 20 | return new CheckLiteral(term); |
21 | } | 21 | } |
22 | } | 22 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java index d0ae3c12..5cecc35b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | 10 | ||
10 | import java.util.Objects; | 11 | import java.util.Objects; |
11 | 12 | ||
@@ -17,13 +18,18 @@ public abstract class AbstractTerm<T> implements Term<T> { | |||
17 | } | 18 | } |
18 | 19 | ||
19 | @Override | 20 | @Override |
21 | public Class<T> getType() { | ||
22 | return type; | ||
23 | } | ||
24 | |||
25 | @Override | ||
20 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | 26 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { |
21 | return getClass().equals(other.getClass()) && type.equals(other.getType()); | 27 | return other != null && getClass() == other.getClass() && type.equals(other.getType()); |
22 | } | 28 | } |
23 | 29 | ||
24 | @Override | 30 | @Override |
25 | public Class<T> getType() { | 31 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { |
26 | return type; | 32 | return Objects.hash(getClass(), type); |
27 | } | 33 | } |
28 | 34 | ||
29 | @Override | 35 | @Override |
@@ -31,11 +37,11 @@ public abstract class AbstractTerm<T> implements Term<T> { | |||
31 | if (this == o) return true; | 37 | if (this == o) return true; |
32 | if (o == null || getClass() != o.getClass()) return false; | 38 | if (o == null || getClass() != o.getClass()) return false; |
33 | AbstractTerm<?> that = (AbstractTerm<?>) o; | 39 | AbstractTerm<?> that = (AbstractTerm<?>) o; |
34 | return type.equals(that.type); | 40 | return equalsWithSubstitution(LiteralEqualityHelper.DEFAULT, that); |
35 | } | 41 | } |
36 | 42 | ||
37 | @Override | 43 | @Override |
38 | public int hashCode() { | 44 | public int hashCode() { |
39 | return Objects.hash(getClass(), type); | 45 | return hashCodeWithSubstitution(LiteralHashCodeHelper.DEFAULT); |
40 | } | 46 | } |
41 | } | 47 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java index c12c0166..f136b68d 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | 11 | ||
11 | import java.util.Set; | 12 | import java.util.Set; |
@@ -17,5 +18,7 @@ public sealed interface AnyTerm permits AnyDataVariable, Term { | |||
17 | 18 | ||
18 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other); | 19 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other); |
19 | 20 | ||
21 | int hashCodeWithSubstitution(LiteralHashCodeHelper helper); | ||
22 | |||
20 | Set<AnyDataVariable> getInputVariables(); | 23 | Set<AnyDataVariable> getInputVariables(); |
21 | } | 24 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java index 8ad17839..09c86db6 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.valuation.Valuation; | 11 | import tools.refinery.store.query.valuation.Valuation; |
11 | 12 | ||
@@ -14,6 +15,8 @@ import java.util.HashSet; | |||
14 | import java.util.Objects; | 15 | import java.util.Objects; |
15 | import java.util.Set; | 16 | import java.util.Set; |
16 | 17 | ||
18 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
19 | @SuppressWarnings("squid:S2160") | ||
17 | public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { | 20 | public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { |
18 | private final Class<T1> leftType; | 21 | private final Class<T1> leftType; |
19 | private final Class<T2> rightType; | 22 | private final Class<T2> rightType; |
@@ -80,6 +83,12 @@ public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { | |||
80 | } | 83 | } |
81 | 84 | ||
82 | @Override | 85 | @Override |
86 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
87 | return Objects.hash(super.hashCodeWithSubstitution(helper), leftType.hashCode(), rightType.hashCode(), | ||
88 | left.hashCodeWithSubstitution(helper), right.hashCodeWithSubstitution(helper)); | ||
89 | } | ||
90 | |||
91 | @Override | ||
83 | public Term<R> substitute(Substitution substitution) { | 92 | public Term<R> substitute(Substitution substitution) { |
84 | return doSubstitute(substitution, left.substitute(substitution), right.substitute(substitution)); | 93 | return doSubstitute(substitution, left.substitute(substitution), right.substitute(substitution)); |
85 | } | 94 | } |
@@ -93,21 +102,4 @@ public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { | |||
93 | inputVariables.addAll(right.getInputVariables()); | 102 | inputVariables.addAll(right.getInputVariables()); |
94 | return Collections.unmodifiableSet(inputVariables); | 103 | return Collections.unmodifiableSet(inputVariables); |
95 | } | 104 | } |
96 | |||
97 | @Override | ||
98 | public boolean equals(Object o) { | ||
99 | if (this == o) return true; | ||
100 | if (o == null || getClass() != o.getClass()) return false; | ||
101 | if (!super.equals(o)) return false; | ||
102 | BinaryTerm<?, ?, ?> that = (BinaryTerm<?, ?, ?>) o; | ||
103 | return Objects.equals(leftType, that.leftType) && | ||
104 | Objects.equals(rightType, that.rightType) && | ||
105 | Objects.equals(left, that.left) && | ||
106 | Objects.equals(right, that.right); | ||
107 | } | ||
108 | |||
109 | @Override | ||
110 | public int hashCode() { | ||
111 | return Objects.hash(super.hashCode(), leftType, rightType, left, right); | ||
112 | } | ||
113 | } | 105 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java index 2f6c56d1..e722c84f 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java | |||
@@ -6,12 +6,15 @@ | |||
6 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.valuation.Valuation; | 11 | import tools.refinery.store.query.valuation.Valuation; |
11 | 12 | ||
12 | import java.util.Objects; | 13 | import java.util.Objects; |
13 | import java.util.Set; | 14 | import java.util.Set; |
14 | 15 | ||
16 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
17 | @SuppressWarnings("squid:S2160") | ||
15 | public final class ConstantTerm<T> extends AbstractTerm<T> { | 18 | public final class ConstantTerm<T> extends AbstractTerm<T> { |
16 | private final T value; | 19 | private final T value; |
17 | 20 | ||
@@ -47,6 +50,11 @@ public final class ConstantTerm<T> extends AbstractTerm<T> { | |||
47 | } | 50 | } |
48 | 51 | ||
49 | @Override | 52 | @Override |
53 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
54 | return Objects.hash(super.hashCodeWithSubstitution(helper), Objects.hash(value)); | ||
55 | } | ||
56 | |||
57 | @Override | ||
50 | public Set<AnyDataVariable> getInputVariables() { | 58 | public Set<AnyDataVariable> getInputVariables() { |
51 | return Set.of(); | 59 | return Set.of(); |
52 | } | 60 | } |
@@ -55,17 +63,4 @@ public final class ConstantTerm<T> extends AbstractTerm<T> { | |||
55 | public String toString() { | 63 | public String toString() { |
56 | return value.toString(); | 64 | return value.toString(); |
57 | } | 65 | } |
58 | |||
59 | @Override | ||
60 | public boolean equals(Object o) { | ||
61 | if (this == o) return true; | ||
62 | if (o == null || getClass() != o.getClass()) return false; | ||
63 | ConstantTerm<?> that = (ConstantTerm<?>) o; | ||
64 | return Objects.equals(value, that.value); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public int hashCode() { | ||
69 | return Objects.hash(value); | ||
70 | } | ||
71 | } | 66 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java index 00950360..e71c69ac 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java | |||
@@ -7,6 +7,7 @@ package tools.refinery.store.query.term; | |||
7 | 7 | ||
8 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.literal.Literal; | 11 | import tools.refinery.store.query.literal.Literal; |
11 | import tools.refinery.store.query.substitution.Substitution; | 12 | import tools.refinery.store.query.substitution.Substitution; |
12 | import tools.refinery.store.query.valuation.Valuation; | 13 | import tools.refinery.store.query.valuation.Valuation; |
@@ -62,6 +63,16 @@ public final class DataVariable<T> extends AnyDataVariable implements Term<T> { | |||
62 | return other instanceof DataVariable<?> dataVariable && helper.variableEqual(this, dataVariable); | 63 | return other instanceof DataVariable<?> dataVariable && helper.variableEqual(this, dataVariable); |
63 | } | 64 | } |
64 | 65 | ||
66 | @Override | ||
67 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
68 | return helper.getVariableHashCode(this); | ||
69 | } | ||
70 | |||
71 | @Override | ||
72 | public int hashCodeWithSubstitution(int sequenceNumber) { | ||
73 | return Objects.hash(type, sequenceNumber); | ||
74 | } | ||
75 | |||
65 | public Literal assign(AssignedValue<T> value) { | 76 | public Literal assign(AssignedValue<T> value) { |
66 | return value.toLiteral(this); | 77 | return value.toLiteral(this); |
67 | } | 78 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java index a2f3261f..d679908a 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java | |||
@@ -46,6 +46,11 @@ public final class NodeVariable extends Variable { | |||
46 | throw new IllegalStateException("%s is a node variable".formatted(this)); | 46 | throw new IllegalStateException("%s is a node variable".formatted(this)); |
47 | } | 47 | } |
48 | 48 | ||
49 | @Override | ||
50 | public int hashCodeWithSubstitution(int sequenceNumber) { | ||
51 | return sequenceNumber; | ||
52 | } | ||
53 | |||
49 | public ConstantLiteral isConstant(int value) { | 54 | public ConstantLiteral isConstant(int value) { |
50 | return new ConstantLiteral(this, value); | 55 | return new ConstantLiteral(this, value); |
51 | } | 56 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java index a46ebe31..6451ea00 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java | |||
@@ -6,12 +6,15 @@ | |||
6 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
7 | 7 | ||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.valuation.Valuation; | 11 | import tools.refinery.store.query.valuation.Valuation; |
11 | 12 | ||
12 | import java.util.Objects; | 13 | import java.util.Objects; |
13 | import java.util.Set; | 14 | import java.util.Set; |
14 | 15 | ||
16 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
17 | @SuppressWarnings("squid:S2160") | ||
15 | public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { | 18 | public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { |
16 | private final Class<T> bodyType; | 19 | private final Class<T> bodyType; |
17 | private final Term<T> body; | 20 | private final Term<T> body; |
@@ -52,6 +55,11 @@ public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { | |||
52 | } | 55 | } |
53 | 56 | ||
54 | @Override | 57 | @Override |
58 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
59 | return Objects.hash(super.hashCodeWithSubstitution(helper), bodyType, body.hashCodeWithSubstitution(helper)); | ||
60 | } | ||
61 | |||
62 | @Override | ||
55 | public Term<R> substitute(Substitution substitution) { | 63 | public Term<R> substitute(Substitution substitution) { |
56 | return doSubstitute(substitution, body.substitute(substitution)); | 64 | return doSubstitute(substitution, body.substitute(substitution)); |
57 | } | 65 | } |
@@ -62,18 +70,4 @@ public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { | |||
62 | public Set<AnyDataVariable> getInputVariables() { | 70 | public Set<AnyDataVariable> getInputVariables() { |
63 | return body.getInputVariables(); | 71 | return body.getInputVariables(); |
64 | } | 72 | } |
65 | |||
66 | @Override | ||
67 | public boolean equals(Object o) { | ||
68 | if (this == o) return true; | ||
69 | if (o == null || getClass() != o.getClass()) return false; | ||
70 | if (!super.equals(o)) return false; | ||
71 | UnaryTerm<?, ?> unaryTerm = (UnaryTerm<?, ?>) o; | ||
72 | return Objects.equals(bodyType, unaryTerm.bodyType) && Objects.equals(body, unaryTerm.body); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public int hashCode() { | ||
77 | return Objects.hash(super.hashCode(), bodyType, body); | ||
78 | } | ||
79 | } | 73 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java index a0268c8e..74384df3 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java | |||
@@ -48,6 +48,8 @@ public abstract sealed class Variable permits AnyDataVariable, NodeVariable { | |||
48 | 48 | ||
49 | public abstract <T> DataVariable<T> asDataVariable(Class<T> type); | 49 | public abstract <T> DataVariable<T> asDataVariable(Class<T> type); |
50 | 50 | ||
51 | public abstract int hashCodeWithSubstitution(int sequenceNumber); | ||
52 | |||
51 | @Override | 53 | @Override |
52 | public String toString() { | 54 | public String toString() { |
53 | return getName(); | 55 | return getName(); |
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java index e17496e3..9d9bf3c0 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java | |||
@@ -20,7 +20,7 @@ import tools.refinery.store.representation.Symbol; | |||
20 | import java.util.List; | 20 | import java.util.List; |
21 | 21 | ||
22 | import static org.hamcrest.MatcherAssert.assertThat; | 22 | import static org.hamcrest.MatcherAssert.assertThat; |
23 | import static tools.refinery.store.query.literal.Literals.assume; | 23 | import static tools.refinery.store.query.literal.Literals.check; |
24 | import static tools.refinery.store.query.literal.Literals.not; | 24 | import static tools.refinery.store.query.literal.Literals.not; |
25 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | 25 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; |
26 | 26 | ||
@@ -47,7 +47,7 @@ class DnfBuilderLiteralEliminationTest { | |||
47 | void eliminateTrueAssumptionTest() { | 47 | void eliminateTrueAssumptionTest() { |
48 | var actual = Dnf.builder() | 48 | var actual = Dnf.builder() |
49 | .parameters(p, q) | 49 | .parameters(p, q) |
50 | .clause(assume(BoolTerms.constant(true)), friendView.call(p, q)) | 50 | .clause(check(BoolTerms.constant(true)), friendView.call(p, q)) |
51 | .build(); | 51 | .build(); |
52 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); | 52 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); |
53 | 53 | ||
@@ -75,7 +75,7 @@ class DnfBuilderLiteralEliminationTest { | |||
75 | var actual = Dnf.builder() | 75 | var actual = Dnf.builder() |
76 | .parameters(p, q) | 76 | .parameters(p, q) |
77 | .clause(friendView.call(p, q)) | 77 | .clause(friendView.call(p, q)) |
78 | .clause(friendView.call(q, p), assume(BoolTerms.constant(value))) | 78 | .clause(friendView.call(q, p), check(BoolTerms.constant(value))) |
79 | .build(); | 79 | .build(); |
80 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); | 80 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); |
81 | 81 | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/HashCodeTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/HashCodeTest.java new file mode 100644 index 00000000..0c8eaeed --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/HashCodeTest.java | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | import tools.refinery.store.query.view.AnySymbolView; | ||
12 | import tools.refinery.store.query.view.KeyOnlyView; | ||
13 | import tools.refinery.store.representation.Symbol; | ||
14 | |||
15 | import static org.hamcrest.MatcherAssert.assertThat; | ||
16 | import static org.hamcrest.Matchers.is; | ||
17 | import static org.hamcrest.Matchers.not; | ||
18 | |||
19 | class HashCodeTest { | ||
20 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
21 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
22 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
23 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
24 | private static final NodeVariable p = Variable.of("p"); | ||
25 | private static final NodeVariable q = Variable.of("q"); | ||
26 | |||
27 | @Test | ||
28 | void flatEqualsTest() { | ||
29 | var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build(); | ||
30 | var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(p)).build(); | ||
31 | |||
32 | assertThat(actual.hashCodeWithSubstitution(), is(expected.hashCodeWithSubstitution())); | ||
33 | } | ||
34 | |||
35 | @Test | ||
36 | void flatNotEqualsTest() { | ||
37 | var expected = Dnf.builder("Expected").parameters(q).clause(friendView.call(q, q)).build(); | ||
38 | var actual = Dnf.builder("Actual").parameters(p).clause(friendView.call(p, q)).build(); | ||
39 | |||
40 | assertThat(actual.hashCodeWithSubstitution(), not(expected.hashCodeWithSubstitution())); | ||
41 | } | ||
42 | |||
43 | @Test | ||
44 | void deepEqualsTest() { | ||
45 | var expected2 = Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build(); | ||
46 | var expected = Dnf.builder("Expected").parameters(q).clause( | ||
47 | expected2.call(q) | ||
48 | ).build(); | ||
49 | var actual = Dnf.builder("Actual").parameters(q).clause( | ||
50 | expected2.call(q) | ||
51 | ).build(); | ||
52 | |||
53 | assertThat(actual.hashCodeWithSubstitution(), is(expected.hashCodeWithSubstitution())); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | void deepNotEqualsTest() { | ||
58 | var expected = Dnf.builder("Expected").parameters(q).clause( | ||
59 | Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q) | ||
60 | ).build(); | ||
61 | var actual = Dnf.builder("Actual").parameters(q).clause( | ||
62 | Dnf.builder("Actual2").parameters(p).clause(personView.call(p)).build().call(q) | ||
63 | ).build(); | ||
64 | |||
65 | assertThat(actual.hashCodeWithSubstitution(), not(expected.hashCodeWithSubstitution())); | ||
66 | } | ||
67 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java index c52d26b2..c509da4d 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java | |||
@@ -28,7 +28,7 @@ import static org.hamcrest.Matchers.hasItem; | |||
28 | import static org.hamcrest.Matchers.not; | 28 | import static org.hamcrest.Matchers.not; |
29 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | 29 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
30 | import static org.junit.jupiter.api.Assertions.assertThrows; | 30 | import static org.junit.jupiter.api.Assertions.assertThrows; |
31 | import static tools.refinery.store.query.literal.Literals.assume; | 31 | import static tools.refinery.store.query.literal.Literals.check; |
32 | import static tools.refinery.store.query.literal.Literals.not; | 32 | import static tools.refinery.store.query.literal.Literals.not; |
33 | import static tools.refinery.store.query.term.int_.IntTerms.*; | 33 | import static tools.refinery.store.query.term.int_.IntTerms.*; |
34 | 34 | ||
@@ -349,7 +349,7 @@ class VariableDirectionTest { | |||
349 | .clause( | 349 | .clause( |
350 | friendView.call(p, q), | 350 | friendView.call(p, q), |
351 | ageView.call(q, x), | 351 | ageView.call(q, x), |
352 | assume(greaterEq(x, y)) | 352 | check(greaterEq(x, y)) |
353 | ) | 353 | ) |
354 | .build(); | 354 | .build(); |
355 | 355 | ||
@@ -381,7 +381,7 @@ class VariableDirectionTest { | |||
381 | void boundPrivateDataVariableOutputTest(Literal literal) { | 381 | void boundPrivateDataVariableOutputTest(Literal literal) { |
382 | var dnfWithInput = Dnf.builder("WithInput") | 382 | var dnfWithInput = Dnf.builder("WithInput") |
383 | .parameter(x, ParameterDirection.IN) | 383 | .parameter(x, ParameterDirection.IN) |
384 | .clause(assume(greaterEq(x, constant(24)))) | 384 | .clause(check(greaterEq(x, constant(24)))) |
385 | .build(); | 385 | .build(); |
386 | var builder = Dnf.builder().clause(dnfWithInput.call(x), literal); | 386 | var builder = Dnf.builder().clause(dnfWithInput.call(x), literal); |
387 | var dnf = assertDoesNotThrow(builder::build); | 387 | var dnf = assertDoesNotThrow(builder::build); |
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java index 1cbc101a..1fae2492 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java | |||
@@ -9,8 +9,8 @@ import org.junit.jupiter.api.Assertions; | |||
9 | import org.junit.jupiter.params.ParameterizedTest; | 9 | import org.junit.jupiter.params.ParameterizedTest; |
10 | import org.junit.jupiter.params.provider.Arguments; | 10 | import org.junit.jupiter.params.provider.Arguments; |
11 | import org.junit.jupiter.params.provider.MethodSource; | 11 | import org.junit.jupiter.params.provider.MethodSource; |
12 | import tools.refinery.store.query.dnf.Dnf; | 12 | import tools.refinery.store.query.equality.DnfEqualityChecker; |
13 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 13 | import tools.refinery.store.query.equality.SubstitutingLiteralEqualityHelper; |
14 | import tools.refinery.store.query.substitution.Substitution; | 14 | import tools.refinery.store.query.substitution.Substitution; |
15 | import tools.refinery.store.query.term.bool.BoolTerms; | 15 | import tools.refinery.store.query.term.bool.BoolTerms; |
16 | import tools.refinery.store.query.term.int_.IntTerms; | 16 | import tools.refinery.store.query.term.int_.IntTerms; |
@@ -48,7 +48,7 @@ class TermSubstitutionTest { | |||
48 | void substitutionTest(AnyTerm term) { | 48 | void substitutionTest(AnyTerm term) { |
49 | var substitutedTerm1 = term.substitute(substitution); | 49 | var substitutedTerm1 = term.substitute(substitution); |
50 | Assertions.assertNotEquals(term, substitutedTerm1, "Original term is not equal to substituted term"); | 50 | Assertions.assertNotEquals(term, substitutedTerm1, "Original term is not equal to substituted term"); |
51 | var helper = new LiteralEqualityHelper(Dnf::equals, List.of(), List.of()); | 51 | var helper = new SubstitutingLiteralEqualityHelper(DnfEqualityChecker.DEFAULT, List.of(), List.of()); |
52 | Assertions.assertTrue(term.equalsWithSubstitution(helper, substitutedTerm1), "Terms are equal by helper"); | 52 | Assertions.assertTrue(term.equalsWithSubstitution(helper, substitutedTerm1), "Terms are equal by helper"); |
53 | // The {@link #substitution} is its own inverse. | 53 | // The {@link #substitution} is its own inverse. |
54 | var substitutedTerm2 = substitutedTerm1.substitute(substitution); | 54 | var substitutedTerm2 = substitutedTerm1.substitute(substitution); |