diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-11-27 21:11:39 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-12-09 00:07:38 +0100 |
commit | 3c1e93b7cb50d20abe08f1b95b8dc8d62ed4c38c (patch) | |
tree | 21f4c04e750614d9f60484a08ee5402452acaf01 /subprojects/store-query-viatra | |
parent | refactor: be more conservative w/preview features (diff) | |
download | refinery-3c1e93b7cb50d20abe08f1b95b8dc8d62ed4c38c.tar.gz refinery-3c1e93b7cb50d20abe08f1b95b8dc8d62ed4c38c.tar.zst refinery-3c1e93b7cb50d20abe08f1b95b8dc8d62ed4c38c.zip |
feat: add cardinality interval abstraction
Diffstat (limited to 'subprojects/store-query-viatra')
-rw-r--r-- | subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java | 97 | ||||
-rw-r--r-- | subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java (renamed from subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java) | 2 | ||||
-rw-r--r-- | subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java (renamed from subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java) | 2 | ||||
-rw-r--r-- | subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java | 50 | ||||
-rw-r--r-- | subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java | 87 |
5 files changed, 236 insertions, 2 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java new file mode 100644 index 00000000..ffd5f6de --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java | |||
@@ -0,0 +1,97 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; | ||
5 | import tools.refinery.store.model.representation.cardinality.FiniteUpperCardinality; | ||
6 | import tools.refinery.store.model.representation.cardinality.UnboundedUpperCardinality; | ||
7 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | ||
8 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | ||
9 | |||
10 | import java.util.stream.Stream; | ||
11 | |||
12 | public class UpperCardinalitySumAggregationOperator implements IMultisetAggregationOperator<UpperCardinality, | ||
13 | UpperCardinalitySumAggregationOperator.Accumulator, UpperCardinality> { | ||
14 | public static final UpperCardinalitySumAggregationOperator INSTANCE = new UpperCardinalitySumAggregationOperator(); | ||
15 | |||
16 | public static final BoundAggregator BOUND_AGGREGATOR = new BoundAggregator(INSTANCE, UpperCardinality.class, | ||
17 | UpperCardinality.class); | ||
18 | |||
19 | private UpperCardinalitySumAggregationOperator() { | ||
20 | // Singleton constructor. | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | public String getName() { | ||
25 | return "sum<UpperCardinality>"; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getShortDescription() { | ||
30 | return "%s computes the sum of finite or unbounded upper cardinalities".formatted(getName()); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Accumulator createNeutral() { | ||
35 | return new Accumulator(); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean isNeutral(Accumulator result) { | ||
40 | return result.sumFiniteUpperBounds == 0 && result.countUnbounded == 0; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public Accumulator update(Accumulator oldResult, UpperCardinality updateValue, boolean isInsertion) { | ||
45 | if (updateValue instanceof FiniteUpperCardinality finiteUpperCardinality) { | ||
46 | int finiteUpperBound = finiteUpperCardinality.finiteUpperBound(); | ||
47 | if (isInsertion) { | ||
48 | oldResult.sumFiniteUpperBounds += finiteUpperBound; | ||
49 | } else { | ||
50 | oldResult.sumFiniteUpperBounds -= finiteUpperBound; | ||
51 | } | ||
52 | } else if (updateValue instanceof UnboundedUpperCardinality) { | ||
53 | if (isInsertion) { | ||
54 | oldResult.countUnbounded += 1; | ||
55 | } else { | ||
56 | oldResult.countUnbounded -= 1; | ||
57 | } | ||
58 | } else { | ||
59 | throw new IllegalArgumentException("Unknown UpperCardinality: " + updateValue); | ||
60 | } | ||
61 | return oldResult; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public UpperCardinality getAggregate(Accumulator result) { | ||
66 | return result.countUnbounded > 0 ? UpperCardinalities.UNBOUNDED : | ||
67 | UpperCardinalities.valueOf(result.sumFiniteUpperBounds); | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public UpperCardinality aggregateStream(Stream<UpperCardinality> stream) { | ||
72 | var result = stream.collect(this::createNeutral, (accumulator, value) -> update(accumulator, value, true), | ||
73 | (left, right) -> new Accumulator(left.sumFiniteUpperBounds + right.sumFiniteUpperBounds, | ||
74 | left.countUnbounded + right.countUnbounded)); | ||
75 | return getAggregate(result); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public Accumulator clone(Accumulator original) { | ||
80 | return new Accumulator(original.sumFiniteUpperBounds, original.countUnbounded); | ||
81 | } | ||
82 | |||
83 | public static class Accumulator { | ||
84 | private int sumFiniteUpperBounds; | ||
85 | |||
86 | private int countUnbounded; | ||
87 | |||
88 | private Accumulator(int sumFiniteUpperBounds, int countUnbounded) { | ||
89 | this.sumFiniteUpperBounds = sumFiniteUpperBounds; | ||
90 | this.countUnbounded = countUnbounded; | ||
91 | } | ||
92 | |||
93 | private Accumulator() { | ||
94 | this(0, 0); | ||
95 | } | ||
96 | } | ||
97 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java index a7e09023..d18187e5 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java | |||
@@ -1,4 +1,4 @@ | |||
1 | package tools.refinery.store.query.viatra.tests; | 1 | package tools.refinery.store.query.viatra; |
2 | 2 | ||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.representation.Relation; |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java index 117edd3e..e8fa6ed1 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java | |||
@@ -1,4 +1,4 @@ | |||
1 | package tools.refinery.store.query.viatra.tests; | 1 | package tools.refinery.store.query.viatra; |
2 | 2 | ||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.representation.Relation; |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java new file mode 100644 index 00000000..07869050 --- /dev/null +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java | |||
@@ -0,0 +1,50 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | ||
2 | |||
3 | import org.junit.jupiter.params.ParameterizedTest; | ||
4 | import org.junit.jupiter.params.provider.Arguments; | ||
5 | import org.junit.jupiter.params.provider.MethodSource; | ||
6 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | ||
7 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | ||
8 | |||
9 | import java.util.stream.Stream; | ||
10 | |||
11 | import static org.hamcrest.MatcherAssert.assertThat; | ||
12 | import static org.hamcrest.Matchers.equalTo; | ||
13 | |||
14 | class UpperCardinalitySumAggregationOperatorStreamTest { | ||
15 | @ParameterizedTest | ||
16 | @MethodSource | ||
17 | void testStream(Stream<UpperCardinality> stream, UpperCardinality expected) { | ||
18 | var result = UpperCardinalitySumAggregationOperator.INSTANCE.aggregateStream(stream); | ||
19 | assertThat(result, equalTo(expected)); | ||
20 | } | ||
21 | |||
22 | static Stream<Arguments> testStream() { | ||
23 | return Stream.of( | ||
24 | Arguments.of(Stream.of(), UpperCardinalities.ZERO), | ||
25 | Arguments.of(Stream.of(UpperCardinality.of(3)), UpperCardinality.of(3)), | ||
26 | Arguments.of( | ||
27 | Stream.of( | ||
28 | UpperCardinality.of(2), | ||
29 | UpperCardinality.of(3) | ||
30 | ), | ||
31 | UpperCardinality.of(5) | ||
32 | ), | ||
33 | Arguments.of(Stream.of(UpperCardinalities.UNBOUNDED), UpperCardinalities.UNBOUNDED), | ||
34 | Arguments.of( | ||
35 | Stream.of( | ||
36 | UpperCardinalities.UNBOUNDED, | ||
37 | UpperCardinalities.UNBOUNDED | ||
38 | ), | ||
39 | UpperCardinalities.UNBOUNDED | ||
40 | ), | ||
41 | Arguments.of( | ||
42 | Stream.of( | ||
43 | UpperCardinalities.UNBOUNDED, | ||
44 | UpperCardinality.of(3) | ||
45 | ), | ||
46 | UpperCardinalities.UNBOUNDED | ||
47 | ) | ||
48 | ); | ||
49 | } | ||
50 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java new file mode 100644 index 00000000..afc4a2f3 --- /dev/null +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java | |||
@@ -0,0 +1,87 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | ||
2 | |||
3 | import org.junit.jupiter.api.BeforeEach; | ||
4 | import org.junit.jupiter.api.Test; | ||
5 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | ||
6 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | ||
7 | |||
8 | import static org.hamcrest.MatcherAssert.assertThat; | ||
9 | import static org.hamcrest.Matchers.equalTo; | ||
10 | |||
11 | class UpperCardinalitySumAggregationOperatorTest { | ||
12 | private UpperCardinalitySumAggregationOperator.Accumulator accumulator; | ||
13 | |||
14 | @BeforeEach | ||
15 | void beforeEach() { | ||
16 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.createNeutral(); | ||
17 | } | ||
18 | |||
19 | @Test | ||
20 | void emptyAggregationTest() { | ||
21 | assertResult(UpperCardinality.of(0)); | ||
22 | } | ||
23 | |||
24 | @Test | ||
25 | void singleBoundedTest() { | ||
26 | insert(UpperCardinality.of(3)); | ||
27 | assertResult(UpperCardinality.of(3)); | ||
28 | } | ||
29 | |||
30 | @Test | ||
31 | void multipleBoundedTest() { | ||
32 | insert(UpperCardinality.of(2)); | ||
33 | insert(UpperCardinality.of(3)); | ||
34 | assertResult(UpperCardinality.of(5)); | ||
35 | } | ||
36 | |||
37 | @Test | ||
38 | void singleUnboundedTest() { | ||
39 | insert(UpperCardinalities.UNBOUNDED); | ||
40 | assertResult(UpperCardinalities.UNBOUNDED); | ||
41 | } | ||
42 | |||
43 | @Test | ||
44 | void multipleUnboundedTest() { | ||
45 | insert(UpperCardinalities.UNBOUNDED); | ||
46 | insert(UpperCardinalities.UNBOUNDED); | ||
47 | assertResult(UpperCardinalities.UNBOUNDED); | ||
48 | } | ||
49 | |||
50 | @Test | ||
51 | void removeBoundedTest() { | ||
52 | insert(UpperCardinality.of(2)); | ||
53 | insert(UpperCardinality.of(3)); | ||
54 | remove(UpperCardinality.of(2)); | ||
55 | assertResult(UpperCardinality.of(3)); | ||
56 | } | ||
57 | |||
58 | @Test | ||
59 | void removeAllUnboundedTest() { | ||
60 | insert(UpperCardinalities.UNBOUNDED); | ||
61 | insert(UpperCardinality.of(3)); | ||
62 | remove(UpperCardinalities.UNBOUNDED); | ||
63 | assertResult(UpperCardinality.of(3)); | ||
64 | } | ||
65 | |||
66 | @Test | ||
67 | void removeSomeUnboundedTest() { | ||
68 | insert(UpperCardinalities.UNBOUNDED); | ||
69 | insert(UpperCardinalities.UNBOUNDED); | ||
70 | insert(UpperCardinality.of(3)); | ||
71 | remove(UpperCardinalities.UNBOUNDED); | ||
72 | assertResult(UpperCardinalities.UNBOUNDED); | ||
73 | } | ||
74 | |||
75 | private void insert(UpperCardinality value) { | ||
76 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.update(accumulator, value, true); | ||
77 | } | ||
78 | |||
79 | private void remove(UpperCardinality value) { | ||
80 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.update(accumulator, value, false); | ||
81 | } | ||
82 | |||
83 | private void assertResult(UpperCardinality expected) { | ||
84 | var result = UpperCardinalitySumAggregationOperator.INSTANCE.getAggregate(accumulator); | ||
85 | assertThat(result, equalTo(expected)); | ||
86 | } | ||
87 | } | ||