diff options
author | 2023-06-22 21:52:53 +0200 | |
---|---|---|
committer | 2023-06-22 22:03:13 +0200 | |
commit | f2ab0e12838efe5a23abb79fd7228f89dc3ba8ef (patch) | |
tree | a11fe1e4663563dfee094aae08fc03cbbab89839 /subprojects | |
parent | refactor: remove Rule (diff) | |
download | refinery-f2ab0e12838efe5a23abb79fd7228f89dc3ba8ef.tar.gz refinery-f2ab0e12838efe5a23abb79fd7228f89dc3ba8ef.tar.zst refinery-f2ab0e12838efe5a23abb79fd7228f89dc3ba8ef.zip |
fix: FilteredView default value
The filer can't return true for the default value, because tuples with default
value cannot be enumerated.
Diffstat (limited to 'subprojects')
10 files changed, 146 insertions, 22 deletions
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 297cdf04..25bcb0dc 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 | |||
@@ -572,6 +572,78 @@ class QueryTest { | |||
572 | ), predicateResultSet); | 572 | ), predicateResultSet); |
573 | } | 573 | } |
574 | 574 | ||
575 | @Test | ||
576 | void filteredIntegerViewTest() { | ||
577 | var distance = Symbol.of("distance", 2, Integer.class); | ||
578 | var nearView = new FilteredView<>(distance, value -> value < 2); | ||
579 | var farView = new FilteredView<>(distance, value -> value >= 5); | ||
580 | var dangerQuery = Query.of("danger", (builder, a1, a2) -> builder.clause((a3) -> List.of( | ||
581 | a1.notEquivalent(a2), | ||
582 | nearView.call(a1, a3), | ||
583 | nearView.call(a2, a3), | ||
584 | not(farView.call(a1, a2)) | ||
585 | ))); | ||
586 | var store = ModelStore.builder() | ||
587 | .symbols(distance) | ||
588 | .with(ViatraModelQueryAdapter.builder() | ||
589 | .queries(dangerQuery)) | ||
590 | .build(); | ||
591 | |||
592 | var model = store.createEmptyModel(); | ||
593 | var distanceInterpretation = model.getInterpretation(distance); | ||
594 | distanceInterpretation.put(Tuple.of(0, 1), 1); | ||
595 | distanceInterpretation.put(Tuple.of(1, 0), 1); | ||
596 | distanceInterpretation.put(Tuple.of(0, 2), 1); | ||
597 | distanceInterpretation.put(Tuple.of(2, 0), 1); | ||
598 | distanceInterpretation.put(Tuple.of(1, 2), 3); | ||
599 | distanceInterpretation.put(Tuple.of(2, 1), 3); | ||
600 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); | ||
601 | var dangerResultSet = queryEngine.getResultSet(dangerQuery); | ||
602 | queryEngine.flushChanges(); | ||
603 | assertResults(Map.of( | ||
604 | Tuple.of(0, 1), false, | ||
605 | Tuple.of(0, 2), false, | ||
606 | Tuple.of(1, 2), true, | ||
607 | Tuple.of(2, 1), true | ||
608 | ), dangerResultSet); | ||
609 | } | ||
610 | |||
611 | @Test | ||
612 | void filteredDoubleViewTest() { | ||
613 | var distance = Symbol.of("distance", 2, Double.class); | ||
614 | var nearView = new FilteredView<>(distance, value -> value < 2); | ||
615 | var farView = new FilteredView<>(distance, value -> value >= 5); | ||
616 | var dangerQuery = Query.of("danger", (builder, a1, a2) -> builder.clause((a3) -> List.of( | ||
617 | a1.notEquivalent(a2), | ||
618 | nearView.call(a1, a3), | ||
619 | nearView.call(a2, a3), | ||
620 | not(farView.call(a1, a2)) | ||
621 | ))); | ||
622 | var store = ModelStore.builder() | ||
623 | .symbols(distance) | ||
624 | .with(ViatraModelQueryAdapter.builder() | ||
625 | .queries(dangerQuery)) | ||
626 | .build(); | ||
627 | |||
628 | var model = store.createEmptyModel(); | ||
629 | var distanceInterpretation = model.getInterpretation(distance); | ||
630 | distanceInterpretation.put(Tuple.of(0, 1), 1.0); | ||
631 | distanceInterpretation.put(Tuple.of(1, 0), 1.0); | ||
632 | distanceInterpretation.put(Tuple.of(0, 2), 1.0); | ||
633 | distanceInterpretation.put(Tuple.of(2, 0), 1.0); | ||
634 | distanceInterpretation.put(Tuple.of(1, 2), 3.0); | ||
635 | distanceInterpretation.put(Tuple.of(2, 1), 3.0); | ||
636 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); | ||
637 | var dangerResultSet = queryEngine.getResultSet(dangerQuery); | ||
638 | queryEngine.flushChanges(); | ||
639 | assertResults(Map.of( | ||
640 | Tuple.of(0, 1), false, | ||
641 | Tuple.of(0, 2), false, | ||
642 | Tuple.of(1, 2), true, | ||
643 | Tuple.of(2, 1), true | ||
644 | ), dangerResultSet); | ||
645 | } | ||
646 | |||
575 | @QueryEngineTest | 647 | @QueryEngineTest |
576 | void assumeTest(QueryEvaluationHint hint) { | 648 | void assumeTest(QueryEvaluationHint hint) { |
577 | var age = Symbol.of("age", 1, Integer.class); | 649 | var age = Symbol.of("age", 1, Integer.class); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java index c1f9d688..fd37604e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java | |||
@@ -20,12 +20,10 @@ import java.util.stream.Collectors; | |||
20 | import java.util.stream.IntStream; | 20 | import java.util.stream.IntStream; |
21 | 21 | ||
22 | public abstract class AbstractFunctionView<T> extends SymbolView<T> { | 22 | public abstract class AbstractFunctionView<T> extends SymbolView<T> { |
23 | private final T defaultValue; | ||
24 | private final List<Parameter> parameters; | 23 | private final List<Parameter> parameters; |
25 | 24 | ||
26 | protected AbstractFunctionView(Symbol<T> symbol, String name, Parameter outParameter) { | 25 | protected AbstractFunctionView(Symbol<T> symbol, String name, Parameter outParameter) { |
27 | super(symbol, name); | 26 | super(symbol, name); |
28 | defaultValue = symbol.defaultValue(); | ||
29 | parameters = createParameters(symbol.arity(), outParameter); | 27 | parameters = createParameters(symbol.arity(), outParameter); |
30 | } | 28 | } |
31 | 29 | ||
@@ -46,16 +44,16 @@ public abstract class AbstractFunctionView<T> extends SymbolView<T> { | |||
46 | } | 44 | } |
47 | 45 | ||
48 | @Override | 46 | @Override |
49 | public final boolean filter(Tuple key, T value) { | 47 | protected boolean doFilter(Tuple key, T value) { |
50 | return !Objects.equals(defaultValue, value); | 48 | return true; |
51 | } | 49 | } |
52 | 50 | ||
53 | protected Object forwardMapValue(Tuple key, T value) { | 51 | protected Object forwardMapValue(T value) { |
54 | return value; | 52 | return value; |
55 | } | 53 | } |
56 | 54 | ||
57 | protected boolean valueEquals(Tuple key, T value, Object otherForwardMappedValue) { | 55 | protected boolean valueEquals(T value, Object otherForwardMappedValue) { |
58 | return Objects.equals(otherForwardMappedValue, forwardMapValue(key, value)); | 56 | return Objects.equals(otherForwardMappedValue, forwardMapValue(value)); |
59 | } | 57 | } |
60 | 58 | ||
61 | @Override | 59 | @Override |
@@ -65,7 +63,7 @@ public abstract class AbstractFunctionView<T> extends SymbolView<T> { | |||
65 | for (int i = 0; i < size; i++) { | 63 | for (int i = 0; i < size; i++) { |
66 | result[i] = Tuple.of(key.get(i)); | 64 | result[i] = Tuple.of(key.get(i)); |
67 | } | 65 | } |
68 | result[key.getSize()] = forwardMapValue(key, value); | 66 | result[key.getSize()] = forwardMapValue(value); |
69 | return result; | 67 | return result; |
70 | } | 68 | } |
71 | 69 | ||
@@ -81,7 +79,7 @@ public abstract class AbstractFunctionView<T> extends SymbolView<T> { | |||
81 | Tuple key = Tuple.of(content); | 79 | Tuple key = Tuple.of(content); |
82 | var valueInTuple = tuple[tuple.length - 1]; | 80 | var valueInTuple = tuple[tuple.length - 1]; |
83 | T valueInMap = model.getInterpretation(getSymbol()).get(key); | 81 | T valueInMap = model.getInterpretation(getSymbol()).get(key); |
84 | return valueEquals(key, valueInMap, valueInTuple); | 82 | return valueEquals(valueInMap, valueInTuple); |
85 | } | 83 | } |
86 | 84 | ||
87 | @Override | 85 | @Override |
@@ -95,12 +93,12 @@ public abstract class AbstractFunctionView<T> extends SymbolView<T> { | |||
95 | if (o == null || getClass() != o.getClass()) return false; | 93 | if (o == null || getClass() != o.getClass()) return false; |
96 | if (!super.equals(o)) return false; | 94 | if (!super.equals(o)) return false; |
97 | AbstractFunctionView<?> that = (AbstractFunctionView<?>) o; | 95 | AbstractFunctionView<?> that = (AbstractFunctionView<?>) o; |
98 | return Objects.equals(defaultValue, that.defaultValue) && Objects.equals(parameters, that.parameters); | 96 | return Objects.equals(parameters, that.parameters); |
99 | } | 97 | } |
100 | 98 | ||
101 | @Override | 99 | @Override |
102 | public int hashCode() { | 100 | public int hashCode() { |
103 | return Objects.hash(super.hashCode(), defaultValue, parameters); | 101 | return Objects.hash(super.hashCode(), parameters); |
104 | } | 102 | } |
105 | 103 | ||
106 | private static List<Parameter> createParameters(int symbolArity, Parameter outParameter) { | 104 | private static List<Parameter> createParameters(int symbolArity, Parameter outParameter) { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java index 922c7355..abae6e5c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java | |||
@@ -27,14 +27,16 @@ public class FilteredView<T> extends TuplePreservingView<T> { | |||
27 | 27 | ||
28 | public FilteredView(Symbol<T> symbol, String name, Predicate<T> predicate) { | 28 | public FilteredView(Symbol<T> symbol, String name, Predicate<T> predicate) { |
29 | this(symbol, name, (k, v) -> predicate.test(v)); | 29 | this(symbol, name, (k, v) -> predicate.test(v)); |
30 | validateDefaultValue(predicate); | ||
30 | } | 31 | } |
31 | 32 | ||
32 | public FilteredView(Symbol<T> symbol, Predicate<T> predicate) { | 33 | public FilteredView(Symbol<T> symbol, Predicate<T> predicate) { |
33 | this(symbol, (k, v) -> predicate.test(v)); | 34 | this(symbol, (k, v) -> predicate.test(v)); |
35 | validateDefaultValue(predicate); | ||
34 | } | 36 | } |
35 | 37 | ||
36 | @Override | 38 | @Override |
37 | public boolean filter(Tuple key, T value) { | 39 | protected boolean doFilter(Tuple key, T value) { |
38 | return this.predicate.test(key, value); | 40 | return this.predicate.test(key, value); |
39 | } | 41 | } |
40 | 42 | ||
@@ -51,4 +53,21 @@ public class FilteredView<T> extends TuplePreservingView<T> { | |||
51 | public int hashCode() { | 53 | public int hashCode() { |
52 | return Objects.hash(super.hashCode(), predicate); | 54 | return Objects.hash(super.hashCode(), predicate); |
53 | } | 55 | } |
56 | |||
57 | private void validateDefaultValue(Predicate<T> predicate) { | ||
58 | var defaultValue = getSymbol().defaultValue(); | ||
59 | boolean matchesDefaultValue = false; | ||
60 | try { | ||
61 | matchesDefaultValue = predicate.test(defaultValue); | ||
62 | } catch (NullPointerException e) { | ||
63 | if (defaultValue != null) { | ||
64 | throw e; | ||
65 | } | ||
66 | // The predicate doesn't need to handle the default value if it is null. | ||
67 | } | ||
68 | if (matchesDefaultValue) { | ||
69 | throw new IllegalArgumentException("Tuples with default value %s cannot be enumerated in %s" | ||
70 | .formatted(defaultValue, getSymbol())); | ||
71 | } | ||
72 | } | ||
54 | } | 73 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java index 26b717ee..c312330e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java | |||
@@ -15,7 +15,7 @@ public class ForbiddenView extends TuplePreservingView<TruthValue> { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | @Override | 17 | @Override |
18 | public boolean filter(Tuple key, TruthValue value) { | 18 | protected boolean doFilter(Tuple key, TruthValue value) { |
19 | return !value.may(); | 19 | return !value.may(); |
20 | } | 20 | } |
21 | } | 21 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java index 7e86f6e4..f0e4a61e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java | |||
@@ -21,8 +21,8 @@ public final class KeyOnlyView<T> extends TuplePreservingView<T> { | |||
21 | } | 21 | } |
22 | 22 | ||
23 | @Override | 23 | @Override |
24 | public boolean filter(Tuple key, T value) { | 24 | protected boolean doFilter(Tuple key, T value) { |
25 | return !Objects.equals(value, defaultValue); | 25 | return true; |
26 | } | 26 | } |
27 | 27 | ||
28 | @Override | 28 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java index e75a8171..c322e220 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java | |||
@@ -15,7 +15,7 @@ public class MayView extends TuplePreservingView<TruthValue> { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | @Override | 17 | @Override |
18 | public boolean filter(Tuple key, TruthValue value) { | 18 | protected boolean doFilter(Tuple key, TruthValue value) { |
19 | return value.may(); | 19 | return value.may(); |
20 | } | 20 | } |
21 | } | 21 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java index a48f8045..65bb4e4c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java | |||
@@ -15,7 +15,7 @@ public class MustView extends TuplePreservingView<TruthValue> { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | @Override | 17 | @Override |
18 | public boolean filter(Tuple key, TruthValue value) { | 18 | protected boolean doFilter(Tuple key, TruthValue value) { |
19 | return value.must(); | 19 | return value.must(); |
20 | } | 20 | } |
21 | } | 21 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java index 267a99d3..cd8bd56b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java | |||
@@ -21,7 +21,6 @@ import java.util.UUID; | |||
21 | */ | 21 | */ |
22 | public abstract non-sealed class SymbolView<T> implements AnySymbolView { | 22 | public abstract non-sealed class SymbolView<T> implements AnySymbolView { |
23 | private final Symbol<T> symbol; | 23 | private final Symbol<T> symbol; |
24 | |||
25 | private final String viewName; | 24 | private final String viewName; |
26 | 25 | ||
27 | protected SymbolView(Symbol<T> symbol, String viewName) { | 26 | protected SymbolView(Symbol<T> symbol, String viewName) { |
@@ -48,7 +47,11 @@ public abstract non-sealed class SymbolView<T> implements AnySymbolView { | |||
48 | return symbol.name() + "#" + viewName; | 47 | return symbol.name() + "#" + viewName; |
49 | } | 48 | } |
50 | 49 | ||
51 | public abstract boolean filter(Tuple key, T value); | 50 | public final boolean filter(Tuple key, T value) { |
51 | return !Objects.equals(symbol.defaultValue(), value) && doFilter(key, value); | ||
52 | } | ||
53 | |||
54 | protected abstract boolean doFilter(Tuple key, T value); | ||
52 | 55 | ||
53 | public abstract Object[] forwardMap(Tuple key, T value); | 56 | public abstract Object[] forwardMap(Tuple key, T value); |
54 | 57 | ||
@@ -77,6 +80,6 @@ public abstract non-sealed class SymbolView<T> implements AnySymbolView { | |||
77 | 80 | ||
78 | @Override | 81 | @Override |
79 | public int hashCode() { | 82 | public int hashCode() { |
80 | return Objects.hash(symbol, viewName); | 83 | return Objects.hash(getClass(), symbol, viewName); |
81 | } | 84 | } |
82 | } | 85 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java index ce2d6ff3..40de4644 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java | |||
@@ -9,6 +9,8 @@ import tools.refinery.store.reasoning.representation.PartialRelation; | |||
9 | import tools.refinery.store.query.view.TuplePreservingView; | 9 | import tools.refinery.store.query.view.TuplePreservingView; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | import java.util.Objects; | ||
13 | |||
12 | class InferredMayTypeView extends TuplePreservingView<InferredType> { | 14 | class InferredMayTypeView extends TuplePreservingView<InferredType> { |
13 | private final PartialRelation type; | 15 | private final PartialRelation type; |
14 | 16 | ||
@@ -18,7 +20,21 @@ class InferredMayTypeView extends TuplePreservingView<InferredType> { | |||
18 | } | 20 | } |
19 | 21 | ||
20 | @Override | 22 | @Override |
21 | public boolean filter(Tuple key, InferredType value) { | 23 | protected boolean doFilter(Tuple key, InferredType value) { |
22 | return value.mayConcreteTypes().contains(type); | 24 | return value.mayConcreteTypes().contains(type); |
23 | } | 25 | } |
26 | |||
27 | @Override | ||
28 | public boolean equals(Object o) { | ||
29 | if (this == o) return true; | ||
30 | if (o == null || getClass() != o.getClass()) return false; | ||
31 | if (!super.equals(o)) return false; | ||
32 | InferredMayTypeView that = (InferredMayTypeView) o; | ||
33 | return Objects.equals(type, that.type); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public int hashCode() { | ||
38 | return Objects.hash(super.hashCode(), type); | ||
39 | } | ||
24 | } | 40 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java index beda1796..1a121547 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java | |||
@@ -9,6 +9,8 @@ import tools.refinery.store.reasoning.representation.PartialRelation; | |||
9 | import tools.refinery.store.query.view.TuplePreservingView; | 9 | import tools.refinery.store.query.view.TuplePreservingView; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | import java.util.Objects; | ||
13 | |||
12 | class InferredMustTypeView extends TuplePreservingView<InferredType> { | 14 | class InferredMustTypeView extends TuplePreservingView<InferredType> { |
13 | private final PartialRelation type; | 15 | private final PartialRelation type; |
14 | 16 | ||
@@ -18,7 +20,21 @@ class InferredMustTypeView extends TuplePreservingView<InferredType> { | |||
18 | } | 20 | } |
19 | 21 | ||
20 | @Override | 22 | @Override |
21 | public boolean filter(Tuple key, InferredType value) { | 23 | protected boolean doFilter(Tuple key, InferredType value) { |
22 | return value.mustTypes().contains(type); | 24 | return value.mustTypes().contains(type); |
23 | } | 25 | } |
26 | |||
27 | @Override | ||
28 | public boolean equals(Object o) { | ||
29 | if (this == o) return true; | ||
30 | if (o == null || getClass() != o.getClass()) return false; | ||
31 | if (!super.equals(o)) return false; | ||
32 | InferredMustTypeView that = (InferredMustTypeView) o; | ||
33 | return Objects.equals(type, that.type); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public int hashCode() { | ||
38 | return Objects.hash(super.hashCode(), type); | ||
39 | } | ||
24 | } | 40 | } |