diff options
author | 2023-08-13 22:23:38 +0200 | |
---|---|---|
committer | 2023-08-13 22:23:38 +0200 | |
commit | 9639e80f72f62940baaaf465f818e9f7ce3e265f (patch) | |
tree | 50f17fc9fa10f141cff5229515be091317c8816f /subprojects/store-reasoning/src/test/java/tools | |
parent | refactor: partial model initialzer unique table (diff) | |
download | refinery-9639e80f72f62940baaaf465f818e9f7ce3e265f.tar.gz refinery-9639e80f72f62940baaaf465f818e9f7ce3e265f.tar.zst refinery-9639e80f72f62940baaaf465f818e9f7ce3e265f.zip |
feat: metamodel translator
Diffstat (limited to 'subprojects/store-reasoning/src/test/java/tools')
-rw-r--r-- | subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/PartialModelTest.java | 2 | ||||
-rw-r--r-- | subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java | 108 | ||||
-rw-r--r-- | subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/CandidateCountTest.java | 321 | ||||
-rw-r--r-- | subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/PartialCountTest.java (renamed from subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/ConcreteCountTest.java) | 27 |
4 files changed, 442 insertions, 16 deletions
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/PartialModelTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/PartialModelTest.java index b2188f5d..77560a68 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/PartialModelTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/PartialModelTest.java | |||
@@ -49,7 +49,7 @@ class PartialModelTest { | |||
49 | .symbol(personStorage)) | 49 | .symbol(personStorage)) |
50 | .with(PartialRelationTranslator.of(friend) | 50 | .with(PartialRelationTranslator.of(friend) |
51 | .symbol(friendStorage) | 51 | .symbol(friendStorage) |
52 | .may(Query.of("mayPerson", (builder, p1, p2) -> builder.clause( | 52 | .may(Query.of("mayFriend", (builder, p1, p2) -> builder.clause( |
53 | may(person.call(p1)), | 53 | may(person.call(p1)), |
54 | may(person.call(p2)), | 54 | may(person.call(p2)), |
55 | not(must(EQUALS_SYMBOL.call(p1, p2))), | 55 | not(must(EQUALS_SYMBOL.call(p1, p2))), |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java new file mode 100644 index 00000000..9e74cf02 --- /dev/null +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java | |||
@@ -0,0 +1,108 @@ | |||
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.reasoning.translator.metamodel; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.model.ModelStore; | ||
10 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; | ||
11 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
12 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
13 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
14 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
15 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
16 | import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; | ||
17 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | ||
18 | import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity; | ||
19 | import tools.refinery.store.representation.TruthValue; | ||
20 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | ||
21 | import tools.refinery.store.tuple.Tuple; | ||
22 | |||
23 | import static org.hamcrest.MatcherAssert.assertThat; | ||
24 | import static org.hamcrest.Matchers.is; | ||
25 | |||
26 | class MetamodelTest { | ||
27 | private final PartialRelation person = new PartialRelation("Person", 1); | ||
28 | private final PartialRelation student = new PartialRelation("Student", 1); | ||
29 | private final PartialRelation teacher = new PartialRelation("Teacher", 1); | ||
30 | private final PartialRelation university = new PartialRelation("University", 1); | ||
31 | private final PartialRelation course = new PartialRelation("Course", 1); | ||
32 | private final PartialRelation courses = new PartialRelation("courses", 2); | ||
33 | private final PartialRelation location = new PartialRelation("location", 2); | ||
34 | private final PartialRelation lecturer = new PartialRelation("lecturer", 2); | ||
35 | private final PartialRelation invalidLecturerCount = new PartialRelation("invalidLecturerCount", 1); | ||
36 | private final PartialRelation enrolledStudents = new PartialRelation("enrolledStudents", 2); | ||
37 | private final PartialRelation invalidStudentCount = new PartialRelation("invalidStudentCount", 1); | ||
38 | |||
39 | @Test | ||
40 | void metamodelTest() { | ||
41 | var metamodel = Metamodel.builder() | ||
42 | .type(person, true) | ||
43 | .type(student, person) | ||
44 | .type(teacher, person) | ||
45 | .type(university) | ||
46 | .type(course) | ||
47 | .reference(courses, university, true, course, location) | ||
48 | .reference(location, course, university, courses) | ||
49 | .reference(lecturer, course, | ||
50 | ConstrainedMultiplicity.of(CardinalityIntervals.ONE, invalidLecturerCount), teacher) | ||
51 | .reference(enrolledStudents, course, | ||
52 | ConstrainedMultiplicity.of(CardinalityIntervals.SOME, invalidStudentCount), student) | ||
53 | .build(); | ||
54 | |||
55 | var store = ModelStore.builder() | ||
56 | .with(ViatraModelQueryAdapter.builder()) | ||
57 | .with(ReasoningAdapter.builder()) | ||
58 | .with(new MultiObjectTranslator()) | ||
59 | .with(new MetamodelTranslator(metamodel)) | ||
60 | .build(); | ||
61 | |||
62 | var seed = ModelSeed.builder(5) | ||
63 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
64 | .reducedValue(CardinalityIntervals.ONE) | ||
65 | .put(Tuple.of(1), CardinalityIntervals.SET) | ||
66 | .put(Tuple.of(4), CardinalityIntervals.SET)) | ||
67 | .seed(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, builder -> builder | ||
68 | .reducedValue(TruthValue.UNKNOWN)) | ||
69 | .seed(ContainmentHierarchyTranslator.CONTAINS_SYMBOL, builder -> builder | ||
70 | .reducedValue(TruthValue.UNKNOWN)) | ||
71 | .seed(person, builder -> builder.reducedValue(TruthValue.UNKNOWN)) | ||
72 | .seed(student, builder -> builder.reducedValue(TruthValue.UNKNOWN)) | ||
73 | .seed(teacher, builder -> builder.reducedValue(TruthValue.UNKNOWN)) | ||
74 | .seed(university, builder -> builder | ||
75 | .reducedValue(TruthValue.UNKNOWN) | ||
76 | .put(Tuple.of(0), TruthValue.TRUE)) | ||
77 | .seed(course, builder -> builder | ||
78 | .reducedValue(TruthValue.UNKNOWN) | ||
79 | .put(Tuple.of(2), TruthValue.TRUE)) | ||
80 | .seed(courses, builder -> builder.reducedValue(TruthValue.UNKNOWN)) | ||
81 | .seed(location, builder -> builder | ||
82 | .reducedValue(TruthValue.UNKNOWN) | ||
83 | .put(Tuple.of(1, 0), TruthValue.TRUE)) | ||
84 | .seed(lecturer, builder -> builder | ||
85 | .reducedValue(TruthValue.FALSE) | ||
86 | .put(Tuple.of(1, 3), TruthValue.TRUE)) | ||
87 | .seed(enrolledStudents, builder -> builder.reducedValue(TruthValue.UNKNOWN)) | ||
88 | .build(); | ||
89 | |||
90 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(seed); | ||
91 | var reasoningAdapter = model.getAdapter(ReasoningAdapter.class); | ||
92 | |||
93 | var coursesInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.PARTIAL, courses); | ||
94 | assertThat(coursesInterpretation.get(Tuple.of(0, 1)), is(TruthValue.TRUE)); | ||
95 | assertThat(coursesInterpretation.get(Tuple.of(0, 2)), is(TruthValue.UNKNOWN)); | ||
96 | assertThat(coursesInterpretation.get(Tuple.of(0, 3)), is(TruthValue.FALSE)); | ||
97 | |||
98 | var invalidLecturerCountInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.PARTIAL, | ||
99 | invalidLecturerCount); | ||
100 | assertThat(invalidLecturerCountInterpretation.get(Tuple.of(1)), is(TruthValue.FALSE)); | ||
101 | assertThat(invalidLecturerCountInterpretation.get(Tuple.of(2)), is(TruthValue.ERROR)); | ||
102 | |||
103 | var enrolledStudentsInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.PARTIAL, | ||
104 | enrolledStudents); | ||
105 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 3)), is(TruthValue.FALSE)); | ||
106 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 4)), is(TruthValue.UNKNOWN)); | ||
107 | } | ||
108 | } | ||
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/CandidateCountTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/CandidateCountTest.java new file mode 100644 index 00000000..28391ec7 --- /dev/null +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/CandidateCountTest.java | |||
@@ -0,0 +1,321 @@ | |||
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.reasoning.translator.multiobject; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.model.ModelStore; | ||
10 | import tools.refinery.store.query.ModelQueryAdapter; | ||
11 | import tools.refinery.store.query.dnf.Query; | ||
12 | import tools.refinery.store.query.resultset.ResultSet; | ||
13 | import tools.refinery.store.query.term.Variable; | ||
14 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; | ||
15 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
16 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
17 | import tools.refinery.store.reasoning.literal.CountCandidateLowerBoundLiteral; | ||
18 | import tools.refinery.store.reasoning.literal.CountCandidateUpperBoundLiteral; | ||
19 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
20 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
21 | import tools.refinery.store.reasoning.translator.PartialRelationTranslator; | ||
22 | import tools.refinery.store.representation.Symbol; | ||
23 | import tools.refinery.store.representation.TruthValue; | ||
24 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | ||
25 | import tools.refinery.store.tuple.Tuple; | ||
26 | |||
27 | import java.util.List; | ||
28 | |||
29 | import static org.hamcrest.MatcherAssert.assertThat; | ||
30 | import static org.hamcrest.Matchers.is; | ||
31 | import static tools.refinery.store.query.literal.Literals.not; | ||
32 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; | ||
33 | |||
34 | class CandidateCountTest { | ||
35 | private static final PartialRelation person = new PartialRelation("Person", 1); | ||
36 | private static final PartialRelation friend = new PartialRelation("friend", 2); | ||
37 | |||
38 | @Test | ||
39 | void lowerBoundZeroTest() { | ||
40 | var query = Query.of("LowerBound", Integer.class, (builder, p1, p2, output) -> builder.clause( | ||
41 | must(person.call(p1)), | ||
42 | must(person.call(p2)), | ||
43 | new CountCandidateLowerBoundLiteral(output, friend, List.of(p1, p2)) | ||
44 | )); | ||
45 | |||
46 | var modelSeed = ModelSeed.builder(2) | ||
47 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
48 | .put(Tuple.of(0), CardinalityIntervals.atLeast(3)) | ||
49 | .put(Tuple.of(1), CardinalityIntervals.atMost(7))) | ||
50 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
51 | .seed(friend, builder -> builder | ||
52 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
53 | .put(Tuple.of(1, 0), TruthValue.UNKNOWN) | ||
54 | .put(Tuple.of(1, 1), TruthValue.ERROR)) | ||
55 | .build(); | ||
56 | |||
57 | var resultSet = getResultSet(query, modelSeed); | ||
58 | assertThat(resultSet.get(Tuple.of(0, 0)), is(0)); | ||
59 | assertThat(resultSet.get(Tuple.of(0, 1)), is(1)); | ||
60 | assertThat(resultSet.get(Tuple.of(1, 0)), is(0)); | ||
61 | assertThat(resultSet.get(Tuple.of(1, 1)), is(1)); | ||
62 | } | ||
63 | |||
64 | @Test | ||
65 | void upperBoundZeroTest() { | ||
66 | var query = Query.of("UpperBound", Integer.class, (builder, p1, p2, output) -> builder.clause( | ||
67 | must(person.call(p1)), | ||
68 | must(person.call(p2)), | ||
69 | new CountCandidateUpperBoundLiteral(output, friend, List.of(p1, p2)) | ||
70 | )); | ||
71 | |||
72 | var modelSeed = ModelSeed.builder(2) | ||
73 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
74 | .put(Tuple.of(0), CardinalityIntervals.atLeast(3)) | ||
75 | .put(Tuple.of(1), CardinalityIntervals.atMost(7))) | ||
76 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
77 | .seed(friend, builder -> builder | ||
78 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
79 | .put(Tuple.of(1, 0), TruthValue.UNKNOWN) | ||
80 | .put(Tuple.of(1, 1), TruthValue.ERROR)) | ||
81 | .build(); | ||
82 | |||
83 | var resultSet = getResultSet(query, modelSeed); | ||
84 | assertThat(resultSet.get(Tuple.of(0, 0)), is(0)); | ||
85 | assertThat(resultSet.get(Tuple.of(0, 1)), is(1)); | ||
86 | assertThat(resultSet.get(Tuple.of(1, 0)), is(0)); | ||
87 | assertThat(resultSet.get(Tuple.of(1, 1)), is(1)); | ||
88 | } | ||
89 | |||
90 | @Test | ||
91 | void lowerBoundOneTest() { | ||
92 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( | ||
93 | must(person.call(p1)), | ||
94 | new CountCandidateLowerBoundLiteral(output, friend, List.of(p1, Variable.of())) | ||
95 | )); | ||
96 | |||
97 | var modelSeed = ModelSeed.builder(4) | ||
98 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
99 | .reducedValue(CardinalityIntervals.ONE) | ||
100 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
101 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
102 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
103 | .seed(friend, builder -> builder | ||
104 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
105 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
106 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
107 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
108 | .put(Tuple.of(1, 2), TruthValue.UNKNOWN) | ||
109 | .put(Tuple.of(1, 3), TruthValue.UNKNOWN) | ||
110 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
111 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
112 | .build(); | ||
113 | |||
114 | var resultSet = getResultSet(query, modelSeed); | ||
115 | assertThat(resultSet.get(Tuple.of(0)), is(2)); | ||
116 | assertThat(resultSet.get(Tuple.of(1)), is(1)); | ||
117 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
118 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
119 | } | ||
120 | |||
121 | @Test | ||
122 | void upperBoundOneTest() { | ||
123 | var query = Query.of("UpperBound", Integer.class, (builder, p1, output) -> builder.clause( | ||
124 | must(person.call(p1)), | ||
125 | new CountCandidateUpperBoundLiteral(output, friend, List.of(p1, Variable.of())) | ||
126 | )); | ||
127 | |||
128 | var modelSeed = ModelSeed.builder(4) | ||
129 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
130 | .reducedValue(CardinalityIntervals.ONE) | ||
131 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
132 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
133 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
134 | .seed(friend, builder -> builder | ||
135 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
136 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
137 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
138 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
139 | .put(Tuple.of(1, 2), TruthValue.UNKNOWN) | ||
140 | .put(Tuple.of(1, 3), TruthValue.UNKNOWN) | ||
141 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
142 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
143 | .build(); | ||
144 | |||
145 | var resultSet = getResultSet(query, modelSeed); | ||
146 | assertThat(resultSet.get(Tuple.of(0)), is(2)); | ||
147 | assertThat(resultSet.get(Tuple.of(1)), is(1)); | ||
148 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
149 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
150 | } | ||
151 | |||
152 | @Test | ||
153 | void lowerBoundTwoTest() { | ||
154 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3) -> builder.clause( | ||
155 | friend.call(p1, p2), | ||
156 | friend.call(p1, p3), | ||
157 | friend.call(p2, p3) | ||
158 | )); | ||
159 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( | ||
160 | must(person.call(p1)), | ||
161 | new CountCandidateLowerBoundLiteral(output, subQuery.getDnf(), | ||
162 | List.of(p1, Variable.of(), Variable.of())) | ||
163 | )); | ||
164 | |||
165 | var modelSeed = ModelSeed.builder(4) | ||
166 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
167 | .reducedValue(CardinalityIntervals.ONE) | ||
168 | .put(Tuple.of(0), CardinalityIntervals.between(5, 9)) | ||
169 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
170 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
171 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
172 | .seed(friend, builder -> builder | ||
173 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
174 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
175 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
176 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
177 | .put(Tuple.of(1, 2), TruthValue.TRUE) | ||
178 | .put(Tuple.of(1, 3), TruthValue.TRUE) | ||
179 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
180 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
181 | .build(); | ||
182 | |||
183 | var resultSet = getResultSet(query, modelSeed); | ||
184 | assertThat(resultSet.get(Tuple.of(0)), is(1)); | ||
185 | assertThat(resultSet.get(Tuple.of(1)), is(1)); | ||
186 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
187 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
188 | } | ||
189 | |||
190 | @Test | ||
191 | void upperBoundTwoTest() { | ||
192 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3) -> builder.clause( | ||
193 | friend.call(p1, p2), | ||
194 | friend.call(p1, p3), | ||
195 | friend.call(p2, p3) | ||
196 | )); | ||
197 | var query = Query.of("UpperBound", Integer.class, (builder, p1, output) -> builder.clause( | ||
198 | must(person.call(p1)), | ||
199 | new CountCandidateUpperBoundLiteral(output, subQuery.getDnf(), | ||
200 | List.of(p1, Variable.of(), Variable.of())) | ||
201 | )); | ||
202 | |||
203 | var modelSeed = ModelSeed.builder(4) | ||
204 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
205 | .reducedValue(CardinalityIntervals.ONE) | ||
206 | .put(Tuple.of(0), CardinalityIntervals.between(5, 9)) | ||
207 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
208 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
209 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
210 | .seed(friend, builder -> builder | ||
211 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
212 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
213 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
214 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
215 | .put(Tuple.of(1, 2), TruthValue.UNKNOWN) | ||
216 | .put(Tuple.of(1, 3), TruthValue.UNKNOWN) | ||
217 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
218 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
219 | .build(); | ||
220 | |||
221 | var resultSet = getResultSet(query, modelSeed); | ||
222 | assertThat(resultSet.get(Tuple.of(0)), is(0)); | ||
223 | assertThat(resultSet.get(Tuple.of(1)), is(0)); | ||
224 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
225 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
226 | } | ||
227 | |||
228 | @Test | ||
229 | void lowerBoundDiagonalTest() { | ||
230 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3) -> builder.clause( | ||
231 | friend.call(p1, p2), | ||
232 | friend.call(p1, p3), | ||
233 | not(friend.call(p2, p3)) | ||
234 | )); | ||
235 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause(v1 -> List.of( | ||
236 | must(person.call(p1)), | ||
237 | new CountCandidateLowerBoundLiteral(output, subQuery.getDnf(), List.of(p1, v1, v1)) | ||
238 | ))); | ||
239 | |||
240 | var modelSeed = ModelSeed.builder(4) | ||
241 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
242 | .reducedValue(CardinalityIntervals.ONE) | ||
243 | .put(Tuple.of(0), CardinalityIntervals.between(5, 9)) | ||
244 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
245 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
246 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
247 | .seed(friend, builder -> builder | ||
248 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
249 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
250 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
251 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
252 | .put(Tuple.of(1, 2), TruthValue.UNKNOWN) | ||
253 | .put(Tuple.of(1, 3), TruthValue.UNKNOWN) | ||
254 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
255 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
256 | .build(); | ||
257 | |||
258 | var resultSet = getResultSet(query, modelSeed); | ||
259 | assertThat(resultSet.get(Tuple.of(0)), is(2)); | ||
260 | assertThat(resultSet.get(Tuple.of(1)), is(1)); | ||
261 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
262 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
263 | } | ||
264 | |||
265 | @Test | ||
266 | void upperBoundDiagonalTest() { | ||
267 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3) -> builder.clause( | ||
268 | friend.call(p1, p2), | ||
269 | friend.call(p1, p3), | ||
270 | not(friend.call(p2, p3)) | ||
271 | )); | ||
272 | var query = Query.of("UpperBound", Integer.class, (builder, p1, output) -> builder | ||
273 | .clause(v1 -> List.of( | ||
274 | must(person.call(p1)), | ||
275 | new CountCandidateUpperBoundLiteral(output, subQuery.getDnf(), List.of(p1, v1, v1)) | ||
276 | ))); | ||
277 | |||
278 | var modelSeed = ModelSeed.builder(4) | ||
279 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
280 | .reducedValue(CardinalityIntervals.ONE) | ||
281 | .put(Tuple.of(0), CardinalityIntervals.between(5, 9)) | ||
282 | .put(Tuple.of(1), CardinalityIntervals.atLeast(3)) | ||
283 | .put(Tuple.of(2), CardinalityIntervals.atMost(7))) | ||
284 | .seed(person, builder -> builder.reducedValue(TruthValue.TRUE)) | ||
285 | .seed(friend, builder -> builder | ||
286 | .put(Tuple.of(0, 1), TruthValue.TRUE) | ||
287 | .put(Tuple.of(0, 2), TruthValue.TRUE) | ||
288 | .put(Tuple.of(0, 3), TruthValue.TRUE) | ||
289 | .put(Tuple.of(1, 0), TruthValue.TRUE) | ||
290 | .put(Tuple.of(1, 2), TruthValue.UNKNOWN) | ||
291 | .put(Tuple.of(1, 3), TruthValue.UNKNOWN) | ||
292 | .put(Tuple.of(2, 0), TruthValue.TRUE) | ||
293 | .put(Tuple.of(2, 1), TruthValue.ERROR)) | ||
294 | .build(); | ||
295 | |||
296 | var resultSet = getResultSet(query, modelSeed); | ||
297 | assertThat(resultSet.get(Tuple.of(0)), is(2)); | ||
298 | assertThat(resultSet.get(Tuple.of(1)), is(1)); | ||
299 | assertThat(resultSet.get(Tuple.of(2)), is(2)); | ||
300 | assertThat(resultSet.get(Tuple.of(3)), is(0)); | ||
301 | } | ||
302 | |||
303 | private static <T> ResultSet<T> getResultSet(Query<T> query, ModelSeed modelSeed) { | ||
304 | var personStorage = Symbol.of("Person", 1, TruthValue.class, TruthValue.FALSE); | ||
305 | var friendStorage = Symbol.of("friend", 2, TruthValue.class, TruthValue.FALSE); | ||
306 | |||
307 | var store = ModelStore.builder() | ||
308 | .with(ViatraModelQueryAdapter.builder() | ||
309 | .query(query)) | ||
310 | .with(ReasoningAdapter.builder()) | ||
311 | .with(new MultiObjectTranslator()) | ||
312 | .with(PartialRelationTranslator.of(person) | ||
313 | .symbol(personStorage)) | ||
314 | .with(PartialRelationTranslator.of(friend) | ||
315 | .symbol(friendStorage)) | ||
316 | .build(); | ||
317 | |||
318 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); | ||
319 | return model.getAdapter(ModelQueryAdapter.class).getResultSet(query); | ||
320 | } | ||
321 | } | ||
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/ConcreteCountTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/PartialCountTest.java index 21111d7c..64230cf6 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/ConcreteCountTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/multiobject/PartialCountTest.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning.translator.multiobject; |
7 | 7 | ||
8 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
9 | import tools.refinery.store.model.ModelStore; | 9 | import tools.refinery.store.model.ModelStore; |
@@ -12,13 +12,13 @@ import tools.refinery.store.query.dnf.Query; | |||
12 | import tools.refinery.store.query.resultset.ResultSet; | 12 | import tools.refinery.store.query.resultset.ResultSet; |
13 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
14 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; | 14 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; |
15 | import tools.refinery.store.reasoning.literal.Concreteness; | 15 | import tools.refinery.store.reasoning.ReasoningAdapter; |
16 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
16 | import tools.refinery.store.reasoning.literal.CountLowerBoundLiteral; | 17 | import tools.refinery.store.reasoning.literal.CountLowerBoundLiteral; |
17 | import tools.refinery.store.reasoning.literal.CountUpperBoundLiteral; | 18 | import tools.refinery.store.reasoning.literal.CountUpperBoundLiteral; |
18 | import tools.refinery.store.reasoning.representation.PartialRelation; | 19 | import tools.refinery.store.reasoning.representation.PartialRelation; |
19 | import tools.refinery.store.reasoning.seed.ModelSeed; | 20 | import tools.refinery.store.reasoning.seed.ModelSeed; |
20 | import tools.refinery.store.reasoning.translator.PartialRelationTranslator; | 21 | import tools.refinery.store.reasoning.translator.PartialRelationTranslator; |
21 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | ||
22 | import tools.refinery.store.representation.Symbol; | 22 | import tools.refinery.store.representation.Symbol; |
23 | import tools.refinery.store.representation.TruthValue; | 23 | import tools.refinery.store.representation.TruthValue; |
24 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | 24 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; |
@@ -33,7 +33,7 @@ import static org.hamcrest.Matchers.is; | |||
33 | import static tools.refinery.store.query.literal.Literals.not; | 33 | import static tools.refinery.store.query.literal.Literals.not; |
34 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; | 34 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; |
35 | 35 | ||
36 | class ConcreteCountTest { | 36 | class PartialCountTest { |
37 | private static final PartialRelation person = new PartialRelation("Person", 1); | 37 | private static final PartialRelation person = new PartialRelation("Person", 1); |
38 | private static final PartialRelation friend = new PartialRelation("friend", 2); | 38 | private static final PartialRelation friend = new PartialRelation("friend", 2); |
39 | 39 | ||
@@ -42,7 +42,7 @@ class ConcreteCountTest { | |||
42 | var query = Query.of("LowerBound", Integer.class, (builder, p1, p2, output) -> builder.clause( | 42 | var query = Query.of("LowerBound", Integer.class, (builder, p1, p2, output) -> builder.clause( |
43 | must(person.call(p1)), | 43 | must(person.call(p1)), |
44 | must(person.call(p2)), | 44 | must(person.call(p2)), |
45 | new CountLowerBoundLiteral(output, Concreteness.PARTIAL, friend, List.of(p1, p2)) | 45 | new CountLowerBoundLiteral(output, friend, List.of(p1, p2)) |
46 | )); | 46 | )); |
47 | 47 | ||
48 | var modelSeed = ModelSeed.builder(2) | 48 | var modelSeed = ModelSeed.builder(2) |
@@ -68,7 +68,7 @@ class ConcreteCountTest { | |||
68 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, p2, output) -> builder.clause( | 68 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, p2, output) -> builder.clause( |
69 | must(person.call(p1)), | 69 | must(person.call(p1)), |
70 | must(person.call(p2)), | 70 | must(person.call(p2)), |
71 | new CountUpperBoundLiteral(output, Concreteness.PARTIAL, friend, List.of(p1, p2)) | 71 | new CountUpperBoundLiteral(output, friend, List.of(p1, p2)) |
72 | )); | 72 | )); |
73 | 73 | ||
74 | var modelSeed = ModelSeed.builder(2) | 74 | var modelSeed = ModelSeed.builder(2) |
@@ -93,7 +93,7 @@ class ConcreteCountTest { | |||
93 | void lowerBoundOneTest() { | 93 | void lowerBoundOneTest() { |
94 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( | 94 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( |
95 | must(person.call(p1)), | 95 | must(person.call(p1)), |
96 | new CountLowerBoundLiteral(output, Concreteness.PARTIAL, friend, List.of(p1, Variable.of())) | 96 | new CountLowerBoundLiteral(output, friend, List.of(p1, Variable.of())) |
97 | )); | 97 | )); |
98 | 98 | ||
99 | var modelSeed = ModelSeed.builder(4) | 99 | var modelSeed = ModelSeed.builder(4) |
@@ -124,7 +124,7 @@ class ConcreteCountTest { | |||
124 | void upperBoundOneTest() { | 124 | void upperBoundOneTest() { |
125 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder.clause( | 125 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder.clause( |
126 | must(person.call(p1)), | 126 | must(person.call(p1)), |
127 | new CountUpperBoundLiteral(output, Concreteness.PARTIAL, friend, List.of(p1, Variable.of())) | 127 | new CountUpperBoundLiteral(output, friend, List.of(p1, Variable.of())) |
128 | )); | 128 | )); |
129 | 129 | ||
130 | var modelSeed = ModelSeed.builder(4) | 130 | var modelSeed = ModelSeed.builder(4) |
@@ -160,8 +160,7 @@ class ConcreteCountTest { | |||
160 | )); | 160 | )); |
161 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( | 161 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause( |
162 | must(person.call(p1)), | 162 | must(person.call(p1)), |
163 | new CountLowerBoundLiteral(output, Concreteness.PARTIAL, subQuery.getDnf(), | 163 | new CountLowerBoundLiteral(output, subQuery.getDnf(), List.of(p1, Variable.of(), Variable.of())) |
164 | List.of(p1, Variable.of(), Variable.of())) | ||
165 | )); | 164 | )); |
166 | 165 | ||
167 | var modelSeed = ModelSeed.builder(4) | 166 | var modelSeed = ModelSeed.builder(4) |
@@ -198,8 +197,7 @@ class ConcreteCountTest { | |||
198 | )); | 197 | )); |
199 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder.clause( | 198 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder.clause( |
200 | must(person.call(p1)), | 199 | must(person.call(p1)), |
201 | new CountUpperBoundLiteral(output, Concreteness.PARTIAL, subQuery.getDnf(), | 200 | new CountUpperBoundLiteral(output, subQuery.getDnf(), List.of(p1, Variable.of(), Variable.of())) |
202 | List.of(p1, Variable.of(), Variable.of())) | ||
203 | )); | 201 | )); |
204 | 202 | ||
205 | var modelSeed = ModelSeed.builder(4) | 203 | var modelSeed = ModelSeed.builder(4) |
@@ -236,7 +234,7 @@ class ConcreteCountTest { | |||
236 | )); | 234 | )); |
237 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause(v1 -> List.of( | 235 | var query = Query.of("LowerBound", Integer.class, (builder, p1, output) -> builder.clause(v1 -> List.of( |
238 | must(person.call(p1)), | 236 | must(person.call(p1)), |
239 | new CountLowerBoundLiteral(output, Concreteness.PARTIAL, subQuery.getDnf(), List.of(p1, v1, v1)) | 237 | new CountLowerBoundLiteral(output, subQuery.getDnf(), List.of(p1, v1, v1)) |
240 | ))); | 238 | ))); |
241 | 239 | ||
242 | var modelSeed = ModelSeed.builder(4) | 240 | var modelSeed = ModelSeed.builder(4) |
@@ -274,8 +272,7 @@ class ConcreteCountTest { | |||
274 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder | 272 | var query = Query.of("UpperBound", UpperCardinality.class, (builder, p1, output) -> builder |
275 | .clause(v1 -> List.of( | 273 | .clause(v1 -> List.of( |
276 | must(person.call(p1)), | 274 | must(person.call(p1)), |
277 | new CountUpperBoundLiteral(output, Concreteness.PARTIAL, subQuery.getDnf(), | 275 | new CountUpperBoundLiteral(output, subQuery.getDnf(), List.of(p1, v1, v1)) |
278 | List.of(p1, v1, v1)) | ||
279 | ))); | 276 | ))); |
280 | 277 | ||
281 | var modelSeed = ModelSeed.builder(4) | 278 | var modelSeed = ModelSeed.builder(4) |