aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/test/java/tools
diff options
context:
space:
mode:
authorLibravatar Oszkár Semeráth <semerath@mit.bme.hu>2023-08-04 13:47:41 +0200
committerLibravatar GitHub <noreply@github.com>2023-08-04 13:47:41 +0200
commit51d34144a2fb42e94e8d960586e1bdb229754546 (patch)
treeccfb5eae5741888b8c2be8b662779833fe5411ec /subprojects/store-dse/src/test/java/tools
parentMerge pull request #31 from OszkarSemerath/datastructure (diff)
parentAdd missing copyright headers (diff)
downloadrefinery-51d34144a2fb42e94e8d960586e1bdb229754546.tar.gz
refinery-51d34144a2fb42e94e8d960586e1bdb229754546.tar.zst
refinery-51d34144a2fb42e94e8d960586e1bdb229754546.zip
Merge pull request #32 from nagilooh/design-space-exploration
Design-space exploration
Diffstat (limited to 'subprojects/store-dse/src/test/java/tools')
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java279
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java122
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java476
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java408
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java57
5 files changed, 1342 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java
new file mode 100644
index 00000000..4bdb05ec
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java
@@ -0,0 +1,279 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import org.junit.jupiter.api.Test;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query;
12import tools.refinery.store.query.dnf.RelationalQuery;
13import tools.refinery.store.dse.internal.TransformationRule;
14import tools.refinery.store.dse.strategy.BestFirstStrategy;
15import tools.refinery.store.dse.strategy.DepthFirstStrategy;
16import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
17import tools.refinery.store.query.view.AnySymbolView;
18import tools.refinery.store.query.view.KeyOnlyView;
19import tools.refinery.store.representation.Symbol;
20import tools.refinery.store.tuple.Tuple;
21import tools.refinery.visualization.ModelVisualizerAdapter;
22import tools.refinery.visualization.internal.FileFormat;
23
24import java.util.List;
25
26import static tools.refinery.store.query.literal.Literals.not;
27
28public class CRAExamplesTest {
29 private static final Symbol<String> name = Symbol.of("Name", 1, String.class);
30
31// private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
32 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
33// private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
34 private static final Symbol<Boolean> attribute = Symbol.of("Attribute", 1);
35 private static final Symbol<Boolean> method = Symbol.of("Method", 1);
36
37// private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
38 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
39 private static final Symbol<Boolean> dataDependency = Symbol.of("DataDependency", 2);
40 private static final Symbol<Boolean> functionalDependency = Symbol.of("FunctionalDependency", 2);
41
42 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
43 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
44
45// private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
46 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
47// private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
48 private static final AnySymbolView attributeView = new KeyOnlyView<>(attribute);
49 private static final AnySymbolView methodView = new KeyOnlyView<>(method);
50// private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
51 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
52 private static final AnySymbolView dataDependencyView = new KeyOnlyView<>(dataDependency);
53 private static final AnySymbolView functionalDependencyView = new KeyOnlyView<>(functionalDependency);
54 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
55 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
56
57 /*Example Transformation rules*/
58 private static final RelationalQuery feature = Query.of("Feature",
59 (builder, f) -> builder.clause(
60 attributeView.call(f))
61 .clause(
62 methodView.call(f))
63 );
64
65 private static final RelationalQuery assignFeaturePreconditionHelper = Query.of("AssignFeaturePreconditionHelper",
66 (builder, c, f) -> builder.clause(
67 classElementView.call(c),
68// classesView.call(model, c),
69 encapsulatesView.call(c, f)
70 ));
71
72 private static final RelationalQuery assignFeaturePrecondition = Query.of("AssignFeaturePrecondition",
73 (builder, f, c1) -> builder.clause((c2) -> List.of(
74// classModelView.call(model),
75 feature.call(f),
76 classElementView.call(c1),
77// featuresView.call(model, f),
78 not(assignFeaturePreconditionHelper.call(c2, f)),
79 not(encapsulatesView.call(c1, f))
80 )));
81
82 private static final RelationalQuery deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
83 (builder, c) -> builder.clause((f) -> List.of(
84// classModelView.call(model),
85 classElementView.call(c),
86// featuresView.call(model, f),
87 not(encapsulatesView.call(c, f))
88 )));
89
90 private static final RelationalQuery createClassPreconditionHelper = Query.of("CreateClassPreconditionHelper",
91 (builder, f, c) -> builder.clause(
92 classElementView.call(c),
93// classesView.call(model, c),
94 encapsulatesView.call(c, f)
95 ));
96
97 private static final RelationalQuery createClassPrecondition = Query.of("CreateClassPrecondition",
98 (builder, f) -> builder.clause((c) -> List.of(
99// classModelView.call(model),
100 feature.call(f),
101 not(createClassPreconditionHelper.call(f, c))
102 )));
103
104 private static final RelationalQuery moveFeaturePrecondition = Query.of("MoveFeature",
105 (builder, c1, c2, f) -> builder.clause(
106// classModelView.call(model),
107 classElementView.call(c1),
108 classElementView.call(c2),
109 c1.notEquivalent(c2),
110 feature.call(f),
111// classesView.call(model, c1),
112// classesView.call(model, c2),
113// featuresView.call(model, f),
114 encapsulatesView.call(c1, f)
115 ));
116
117 private static final TransformationRule assignFeatureRule = new TransformationRule("AssignFeature",
118 assignFeaturePrecondition,
119 (model) -> {
120// var isEncapsulatedByInterpretation = model.getInterpretation(isEncapsulatedBy);
121 var encapsulatesInterpretation = model.getInterpretation(encapsulates);
122 return ((Tuple activation) -> {
123 var feature = activation.get(0);
124 var classElement = activation.get(1);
125
126// isEncapsulatedByInterpretation.put(Tuple.of(feature, classElement), true);
127 encapsulatesInterpretation.put(Tuple.of(classElement, feature), true);
128 });
129 });
130
131 private static final TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
132 deleteEmptyClassPrecondition,
133 (model) -> {
134// var classesInterpretation = model.getInterpretation(classes);
135 var classElementInterpretation = model.getInterpretation(classElement);
136 return ((Tuple activation) -> {
137 // TODO: can we move dseAdapter outside?
138 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
139// var modelElement = activation.get(0);
140 var classElement = activation.get(0);
141
142// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
143 classElementInterpretation.put(Tuple.of(classElement), false);
144 dseAdapter.deleteObject(Tuple.of(classElement));
145 });
146 });
147
148 private static final TransformationRule createClassRule = new TransformationRule("CreateClass",
149 createClassPrecondition,
150 (model) -> {
151 var classElementInterpretation = model.getInterpretation(classElement);
152// var classesInterpretation = model.getInterpretation(classes);
153 var encapsulatesInterpretation = model.getInterpretation(encapsulates);
154 return ((Tuple activation) -> {
155 // TODO: can we move dseAdapter outside?
156 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
157// var modelElement = activation.get(0);
158 var feature = activation.get(0);
159
160 var newClassElement = dseAdapter.createObject();
161 var newClassElementId = newClassElement.get(0);
162 classElementInterpretation.put(newClassElement, true);
163// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
164 encapsulatesInterpretation.put(Tuple.of(newClassElementId, feature), true);
165 });
166 });
167
168 private static final TransformationRule moveFeatureRule = new TransformationRule("MoveFeature",
169 moveFeaturePrecondition,
170 (model) -> {
171 var encapsulatesInterpretation = model.getInterpretation(encapsulates);
172 return ((Tuple activation) -> {
173 var classElement1 = activation.get(0);
174 var classElement2 = activation.get(1);
175 var feature = activation.get(2);
176
177 encapsulatesInterpretation.put(Tuple.of(classElement1, feature), false);
178 encapsulatesInterpretation.put(Tuple.of(classElement2, feature), true);
179 });
180 });
181
182 @Test
183 void craTest() {
184 var store = ModelStore.builder()
185 .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency,
186 functionalDependency, name)
187 .with(ViatraModelQueryAdapter.builder()
188 .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition,
189 deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition,
190 moveFeaturePrecondition))
191 .with(ModelVisualizerAdapter.builder())
192 .with(DesignSpaceExplorationAdapter.builder()
193 .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule)
194// .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled()
195 .strategy(new BestFirstStrategy(6).continueIfHardObjectivesFulfilled()
196// .goOnOnlyIfFitnessIsBetter()
197 ))
198 .build();
199
200 var model = store.createEmptyModel();
201 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
202// dseAdapter.setRandom(1);
203 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
204
205// var modelInterpretation = model.getInterpretation(classModel);
206 var nameInterpretation = model.getInterpretation(name);
207 var methodInterpretation = model.getInterpretation(method);
208 var attributeInterpretation = model.getInterpretation(attribute);
209 var dataDependencyInterpretation = model.getInterpretation(dataDependency);
210 var functionalDependencyInterpretation = model.getInterpretation(functionalDependency);
211
212// var modelElement = dseAdapter.createObject();
213 var method1 = dseAdapter.createObject();
214 var method1Id = method1.get(0);
215 var method2 = dseAdapter.createObject();
216 var method2Id = method2.get(0);
217 var method3 = dseAdapter.createObject();
218 var method3Id = method3.get(0);
219 var method4 = dseAdapter.createObject();
220 var method4Id = method4.get(0);
221 var attribute1 = dseAdapter.createObject();
222 var attribute1Id = attribute1.get(0);
223 var attribute2 = dseAdapter.createObject();
224 var attribute2Id = attribute2.get(0);
225 var attribute3 = dseAdapter.createObject();
226 var attribute3Id = attribute3.get(0);
227 var attribute4 = dseAdapter.createObject();
228 var attribute4Id = attribute4.get(0);
229 var attribute5 = dseAdapter.createObject();
230 var attribute5Id = attribute5.get(0);
231
232 nameInterpretation.put(method1, "M1");
233 nameInterpretation.put(method2, "M2");
234 nameInterpretation.put(method3, "M3");
235 nameInterpretation.put(method4, "M4");
236 nameInterpretation.put(attribute1, "A1");
237 nameInterpretation.put(attribute2, "A2");
238 nameInterpretation.put(attribute3, "A3");
239 nameInterpretation.put(attribute4, "A4");
240 nameInterpretation.put(attribute5, "A5");
241
242
243
244// modelInterpretation.put(modelElement, true);
245 methodInterpretation.put(method1, true);
246 methodInterpretation.put(method2, true);
247 methodInterpretation.put(method3, true);
248 methodInterpretation.put(method4, true);
249 attributeInterpretation.put(attribute1, true);
250 attributeInterpretation.put(attribute2, true);
251 attributeInterpretation.put(attribute3, true);
252 attributeInterpretation.put(attribute4, true);
253 attributeInterpretation.put(attribute5, true);
254
255 dataDependencyInterpretation.put(Tuple.of(method1Id, attribute1Id), true);
256 dataDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true);
257 dataDependencyInterpretation.put(Tuple.of(method2Id, attribute2Id), true);
258 dataDependencyInterpretation.put(Tuple.of(method3Id, attribute3Id), true);
259 dataDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true);
260 dataDependencyInterpretation.put(Tuple.of(method4Id, attribute3Id), true);
261 dataDependencyInterpretation.put(Tuple.of(method4Id, attribute5Id), true);
262
263 functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true);
264 functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute4Id), true);
265 functionalDependencyInterpretation.put(Tuple.of(method2Id, attribute1Id), true);
266 functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute1Id), true);
267 functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true);
268 functionalDependencyInterpretation.put(Tuple.of(method4Id, attribute2Id), true);
269
270 queryEngine.flushChanges();
271
272 var states = dseAdapter.explore();
273 System.out.println("states size: " + states.size());
274 System.out.println("states: " + states);
275 var visualizer = model.getAdapter(ModelVisualizerAdapter.class);
276 visualizer.renderDesignSpace("test_output", FileFormat.SVG);
277 }
278
279}
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java
new file mode 100644
index 00000000..101a5362
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java
@@ -0,0 +1,122 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import org.junit.jupiter.api.Test;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query;
12import tools.refinery.store.dse.internal.TransformationRule;
13import tools.refinery.store.dse.strategy.BestFirstStrategy;
14import tools.refinery.store.dse.strategy.DepthFirstStrategy;
15import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
16import tools.refinery.store.query.view.AnySymbolView;
17import tools.refinery.store.query.view.KeyOnlyView;
18import tools.refinery.store.representation.Symbol;
19import tools.refinery.store.tuple.Tuple;
20import tools.refinery.visualization.ModelVisualizerAdapter;
21import tools.refinery.visualization.internal.FileFormat;
22
23public class DebugTest {
24 private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
25 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
26 private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
27
28 private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
29 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
30
31 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
32 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
33
34 private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
35 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
36 private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
37 private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
38 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
39 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
40 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
41
42
43 @Test
44 void BFSTest() {
45 var createClassPrecondition = Query.of("CreateClassPrecondition",
46 (builder, model) -> builder.clause(
47 classModelView.call(model)
48 ));
49
50 var createClassRule = new TransformationRule("CreateClass",
51 createClassPrecondition,
52 (model) -> {
53 var classesInterpretation = model.getInterpretation(classes);
54 var classElementInterpretation = model.getInterpretation(classElement);
55 return ((Tuple activation) -> {
56 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
57 var modelElement = activation.get(0);
58
59 var newClassElement = dseAdapter.createObject();
60 var newClassElementId = newClassElement.get(0);
61
62 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
63 classElementInterpretation.put(Tuple.of(newClassElementId), true);
64 });
65 });
66
67 var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
68 (builder, model) -> builder.clause(
69 classModelView.call(model)
70 ));
71
72 var createFeatureRule = new TransformationRule("CreateFeature",
73 createFeaturePrecondition,
74 (model) -> {
75 var featuresInterpretation = model.getInterpretation(features);
76 var featureInterpretation = model.getInterpretation(feature);
77 return ((Tuple activation) -> {
78 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
79 var modelElement = activation.get(0);
80
81 var newClassElement = dseAdapter.createObject();
82 var newClassElementId = newClassElement.get(0);
83
84 featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
85 featureInterpretation.put(Tuple.of(newClassElementId), true);
86 });
87 });
88
89 var store = ModelStore.builder()
90 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
91 .with(ViatraModelQueryAdapter.builder()
92 .queries(createClassPrecondition, createFeaturePrecondition))
93 .with(ModelVisualizerAdapter.builder())
94 .with(DesignSpaceExplorationAdapter.builder()
95 .transformations(createClassRule, createFeatureRule)
96 .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled()
97// .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled()
98// .goOnOnlyIfFitnessIsBetter()
99 ))
100 .build();
101
102 var model = store.createEmptyModel();
103 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
104// dseAdapter.setRandom(1);
105 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
106
107 var modelElementInterpretation = model.getInterpretation(classModel);
108 var classElementInterpretation = model.getInterpretation(classElement);
109 var modelElement = dseAdapter.createObject();
110 modelElementInterpretation.put(modelElement, true);
111 classElementInterpretation.put(modelElement, true);
112 queryEngine.flushChanges();
113
114
115 var states = dseAdapter.explore();
116 var visualizer = model.getAdapter(ModelVisualizerAdapter.class);
117 visualizer.renderDesignSpace("test_output", FileFormat.SVG);
118 System.out.println("states size: " + states.size());
119 System.out.println("states: " + states);
120
121 }
122}
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java
new file mode 100644
index 00000000..f4644407
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java
@@ -0,0 +1,476 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import org.junit.jupiter.api.Test;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query;
12import tools.refinery.store.dse.internal.TransformationRule;
13import tools.refinery.store.dse.strategy.BestFirstStrategy;
14import tools.refinery.store.dse.strategy.DepthFirstStrategy;
15import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
16import tools.refinery.store.query.view.AnySymbolView;
17import tools.refinery.store.query.view.KeyOnlyView;
18import tools.refinery.store.representation.Symbol;
19import tools.refinery.store.tuple.Tuple;
20import tools.refinery.visualization.ModelVisualizerAdapter;
21
22import static org.junit.jupiter.api.Assertions.assertEquals;
23
24public class DesignSpaceExplorationTest {
25// private static final Symbol<Boolean> namedElement = Symbol.of("NamedElement", 1);
26// private static final Symbol<Boolean> attribute = Symbol.of("Attribute", 1);
27// private static final Symbol<Boolean> method = Symbol.of("Method", 1);
28// private static final Symbol<Boolean> dataDependency = Symbol.of("DataDependency", 2);
29// private static final Symbol<Boolean> functionalDependency = Symbol.of("FunctionalDependency", 2);
30
31 private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
32 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
33 private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
34
35 private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
36 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
37
38 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
39 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
40
41 private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
42 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
43 private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
44 private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
45 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
46 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
47 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
48
49 @Test
50 void createObjectTest() {
51 var store = ModelStore.builder()
52 .with(ViatraModelQueryAdapter.builder())
53 .with(DesignSpaceExplorationAdapter.builder())
54 .build();
55
56 var model = store.createEmptyModel();
57 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
58
59 assertEquals(0, dseAdapter.getModelSize());
60
61 var newModel = dseAdapter.createObject();
62 var newModelId = newModel.get(0);
63 var newClass1 = dseAdapter.createObject();
64 var newClass1Id = newClass1.get(0);
65 var newClass2 = dseAdapter.createObject();
66 var newClass2Id = newClass2.get(0);
67 var newField = dseAdapter.createObject();
68 var newFieldId = newField.get(0);
69
70 assertEquals(0, newModelId);
71 assertEquals(1, newClass1Id);
72 assertEquals(2, newClass2Id);
73 assertEquals(3, newFieldId);
74 assertEquals(4, dseAdapter.getModelSize());
75 }
76
77 @Test
78 void deleteMiddleObjectTest() {
79 var store = ModelStore.builder()
80 .with(ViatraModelQueryAdapter.builder())
81 .with(DesignSpaceExplorationAdapter.builder())
82 .build();
83
84 var model = store.createEmptyModel();
85 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
86
87 assertEquals(0, dseAdapter.getModelSize());
88
89 var newObject0 = dseAdapter.createObject();
90 var newObject0Id = newObject0.get(0);
91 var newObject1 = dseAdapter.createObject();
92 var newObject1Id = newObject1.get(0);
93 var newObject2 = dseAdapter.createObject();
94 var newObject2Id = newObject2.get(0);
95 var newObject3 = dseAdapter.createObject();
96 var newObject3Id = newObject3.get(0);
97
98 assertEquals(0, newObject0Id);
99 assertEquals(1, newObject1Id);
100 assertEquals(2, newObject2Id);
101 assertEquals(3, newObject3Id);
102 assertEquals(4, dseAdapter.getModelSize());
103
104 dseAdapter.deleteObject(newObject1);
105 assertEquals(4, dseAdapter.getModelSize());
106
107 var newObject4 = dseAdapter.createObject();
108 var newObject4Id = newObject4.get(0);
109 assertEquals(4, newObject4Id);
110 assertEquals(5, dseAdapter.getModelSize());
111
112 dseAdapter.deleteObject(newObject4);
113 assertEquals(5, dseAdapter.getModelSize());
114 }
115
116 @Test
117 void DFSTrivialTest() {
118 var store = ModelStore.builder()
119 .symbols(classModel)
120 .with(ViatraModelQueryAdapter.builder())
121 .with(ModelVisualizerAdapter.builder())
122 .with(DesignSpaceExplorationAdapter.builder()
123 .strategy(new DepthFirstStrategy(0)))
124 .build();
125
126 var model = store.createEmptyModel();
127 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
128
129 var states = dseAdapter.explore();
130 assertEquals(1, states.size());
131 }
132
133 @Test
134 void DFSOneRuleTest() {
135 var createClassPrecondition = Query.of("CreateClassPrecondition",
136 (builder, model) -> builder.clause(
137 classModelView.call(model)
138 ));
139
140 var createClassRule = new TransformationRule("CreateClass",
141 createClassPrecondition,
142 (model) -> {
143 var classesInterpretation = model.getInterpretation(classes);
144 var classElementInterpretation = model.getInterpretation(classElement);
145 return ((Tuple activation) -> {
146 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
147 var modelElement = activation.get(0);
148
149 var newClassElement = dseAdapter.createObject();
150 var newClassElementId = newClassElement.get(0);
151
152 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
153 classElementInterpretation.put(Tuple.of(newClassElementId), true);
154 });
155 });
156
157 var store = ModelStore.builder()
158 .symbols(classModel, classElement, classes)
159 .with(ViatraModelQueryAdapter.builder()
160 .queries(createClassPrecondition))
161 .with(ModelVisualizerAdapter.builder())
162 .with(DesignSpaceExplorationAdapter.builder()
163 .transformations(createClassRule)
164 .strategy(new DepthFirstStrategy(4)
165 ))
166 .build();
167
168 var model = store.createEmptyModel();
169 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
170 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
171
172 var modelElementInterpretation = model.getInterpretation(classModel);
173 modelElementInterpretation.put(dseAdapter.createObject(), true);
174 queryEngine.flushChanges();
175
176 var states = dseAdapter.explore();
177 assertEquals(1, states.size());
178 }
179
180 @Test
181 void DFSContinueTest() {
182 var createClassPrecondition = Query.of("CreateClassPrecondition",
183 (builder, model) -> builder.clause(
184 classModelView.call(model)
185 ));
186
187 var createClassRule = new TransformationRule("CreateClass",
188 createClassPrecondition,
189 (model) -> {
190 var classesInterpretation = model.getInterpretation(classes);
191 var classElementInterpretation = model.getInterpretation(classElement);
192 return ((Tuple activation) -> {
193 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
194 var modelElement = activation.get(0);
195
196 var newClassElement = dseAdapter.createObject();
197 var newClassElementId = newClassElement.get(0);
198
199 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
200 classElementInterpretation.put(Tuple.of(newClassElementId), true);
201 });
202 });
203
204 var store = ModelStore.builder()
205 .symbols(classModel, classElement, classes)
206 .with(ViatraModelQueryAdapter.builder()
207 .queries(createClassPrecondition))
208 .with(ModelVisualizerAdapter.builder())
209 .with(DesignSpaceExplorationAdapter.builder()
210 .transformations(createClassRule)
211 .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled()
212 ))
213 .build();
214
215 var model = store.createEmptyModel();
216 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
217 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
218
219 var modelElementInterpretation = model.getInterpretation(classModel);
220 modelElementInterpretation.put(dseAdapter.createObject(), true);
221 queryEngine.flushChanges();
222
223 var states = dseAdapter.explore();
224 assertEquals(5, states.size());
225 }
226
227 @Test
228 void DFSCompletenessTest() {
229 var createClassPrecondition = Query.of("CreateClassPrecondition",
230 (builder, model) -> builder.clause(
231 classModelView.call(model)
232 ));
233
234 var createClassRule = new TransformationRule("CreateClass",
235 createClassPrecondition,
236 (model) -> {
237 var classesInterpretation = model.getInterpretation(classes);
238 var classElementInterpretation = model.getInterpretation(classElement);
239 return ((Tuple activation) -> {
240 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
241 var modelElement = activation.get(0);
242
243 var newClassElement = dseAdapter.createObject();
244 var newClassElementId = newClassElement.get(0);
245
246 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
247 classElementInterpretation.put(Tuple.of(newClassElementId), true);
248 });
249 });
250
251 var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
252 (builder, model) -> builder.clause(
253 classModelView.call(model)
254 ));
255
256 var createFeatureRule = new TransformationRule("CreateFeature",
257 createFeaturePrecondition,
258 (model) -> {
259 var featuresInterpretation = model.getInterpretation(features);
260 var featureInterpretation = model.getInterpretation(feature);
261 return ((Tuple activation) -> {
262 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
263 var modelElement = activation.get(0);
264
265 var newClassElement = dseAdapter.createObject();
266 var newClassElementId = newClassElement.get(0);
267
268 featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
269 featureInterpretation.put(Tuple.of(newClassElementId), true);
270 });
271 });
272
273 var store = ModelStore.builder()
274 .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
275 .with(ViatraModelQueryAdapter.builder()
276 .queries(createClassPrecondition, createFeaturePrecondition))
277 .with(ModelVisualizerAdapter.builder())
278 .with(DesignSpaceExplorationAdapter.builder()
279 .transformations(createClassRule, createFeatureRule)
280 .strategy(new DepthFirstStrategy(10).continueIfHardObjectivesFulfilled()
281 ))
282 .build();
283
284 var model = store.createEmptyModel();
285 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
286 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
287
288 var modelElementInterpretation = model.getInterpretation(classModel);
289 modelElementInterpretation.put(dseAdapter.createObject(), true);
290 queryEngine.flushChanges();
291
292 var states = dseAdapter.explore();
293 assertEquals(2047, states.size());
294 }
295
296 @Test
297 void BFSTrivialTest() {
298 var store = ModelStore.builder()
299 .symbols(classModel)
300 .with(ViatraModelQueryAdapter.builder())
301 .with(ModelVisualizerAdapter.builder())
302 .with(DesignSpaceExplorationAdapter.builder()
303 .strategy(new BestFirstStrategy(0)))
304 .build();
305
306 var model = store.createEmptyModel();
307 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
308
309 var states = dseAdapter.explore();
310 assertEquals(1, states.size());
311 }
312
313 @Test
314 void BFSOneRuleTest() {
315 var createClassPrecondition = Query.of("CreateClassPrecondition",
316 (builder, model) -> builder.clause(
317 classModelView.call(model)
318 ));
319
320 var createClassRule = new TransformationRule("CreateClass",
321 createClassPrecondition,
322 (model) -> {
323 var classesInterpretation = model.getInterpretation(classes);
324 var classElementInterpretation = model.getInterpretation(classElement);
325 return ((Tuple activation) -> {
326 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
327 var modelElement = activation.get(0);
328
329 var newClassElement = dseAdapter.createObject();
330 var newClassElementId = newClassElement.get(0);
331
332 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
333 classElementInterpretation.put(Tuple.of(newClassElementId), true);
334 });
335 });
336
337 var store = ModelStore.builder()
338 .symbols(classModel, classElement, classes)
339 .with(ViatraModelQueryAdapter.builder()
340 .queries(createClassPrecondition))
341 .with(ModelVisualizerAdapter.builder())
342 .with(DesignSpaceExplorationAdapter.builder()
343 .transformations(createClassRule)
344 .strategy(new BestFirstStrategy(4)
345 ))
346 .build();
347
348 var model = store.createEmptyModel();
349 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
350 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
351
352 var modelElementInterpretation = model.getInterpretation(classModel);
353 modelElementInterpretation.put(dseAdapter.createObject(), true);
354 queryEngine.flushChanges();
355
356 var states = dseAdapter.explore();
357 assertEquals(1, states.size());
358 }
359
360 @Test
361 void BFSContinueTest() {
362 var createClassPrecondition = Query.of("CreateClassPrecondition",
363 (builder, model) -> builder.clause(
364 classModelView.call(model)
365 ));
366
367 var createClassRule = new TransformationRule("CreateClass",
368 createClassPrecondition,
369 (model) -> {
370 var classesInterpretation = model.getInterpretation(classes);
371 var classElementInterpretation = model.getInterpretation(classElement);
372 return ((Tuple activation) -> {
373 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
374 var modelElement = activation.get(0);
375
376 var newClassElement = dseAdapter.createObject();
377 var newClassElementId = newClassElement.get(0);
378
379 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
380 classElementInterpretation.put(Tuple.of(newClassElementId), true);
381 });
382 });
383
384 var store = ModelStore.builder()
385 .symbols(classModel, classElement, classes)
386 .with(ViatraModelQueryAdapter.builder()
387 .queries(createClassPrecondition))
388 .with(ModelVisualizerAdapter.builder())
389 .with(DesignSpaceExplorationAdapter.builder()
390 .transformations(createClassRule)
391 .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled()
392 ))
393 .build();
394
395 var model = store.createEmptyModel();
396 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
397 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
398
399 var modelElementInterpretation = model.getInterpretation(classModel);
400 modelElementInterpretation.put(dseAdapter.createObject(), true);
401 queryEngine.flushChanges();
402
403 var states = dseAdapter.explore();
404 assertEquals(5, states.size());
405 }
406
407 @Test
408 void BFSCompletenessTest() {
409 var createClassPrecondition = Query.of("CreateClassPrecondition",
410 (builder, model) -> builder.clause(
411 classModelView.call(model)
412 ));
413
414 var createClassRule = new TransformationRule("CreateClass",
415 createClassPrecondition,
416 (model) -> {
417 var classesInterpretation = model.getInterpretation(classes);
418 var classElementInterpretation = model.getInterpretation(classElement);
419 return ((Tuple activation) -> {
420 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
421 var modelElement = activation.get(0);
422
423 var newClassElement = dseAdapter.createObject();
424 var newClassElementId = newClassElement.get(0);
425
426 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
427 classElementInterpretation.put(Tuple.of(newClassElementId), true);
428 });
429 });
430
431 var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
432 (builder, model) -> builder.clause(
433 classModelView.call(model)
434 ));
435
436 var createFeatureRule = new TransformationRule("CreateFeature",
437 createFeaturePrecondition,
438 (model) -> {
439 var featuresInterpretation = model.getInterpretation(features);
440 var featureInterpretation = model.getInterpretation(feature);
441 return ((Tuple activation) -> {
442 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
443 var modelElement = activation.get(0);
444
445 var newClassElement = dseAdapter.createObject();
446 var newClassElementId = newClassElement.get(0);
447
448 featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
449 featureInterpretation.put(Tuple.of(newClassElementId), true);
450 });
451 });
452
453 var store = ModelStore.builder()
454 .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
455 .with(ViatraModelQueryAdapter.builder()
456 .queries(createClassPrecondition, createFeaturePrecondition))
457 .with(ModelVisualizerAdapter.builder())
458 .with(DesignSpaceExplorationAdapter.builder()
459 .transformations(createClassRule, createFeatureRule)
460 .strategy(new BestFirstStrategy(10).continueIfHardObjectivesFulfilled()
461 ))
462 .build();
463
464 var model = store.createEmptyModel();
465 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
466 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
467
468 var modelElementInterpretation = model.getInterpretation(classModel);
469 modelElementInterpretation.put(dseAdapter.createObject(), true);
470 queryEngine.flushChanges();
471
472 var states = dseAdapter.explore();
473 assertEquals(2047, states.size());
474 }
475
476}
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java
new file mode 100644
index 00000000..312bcebd
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java
@@ -0,0 +1,408 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import org.junit.jupiter.api.Test;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query;
12import tools.refinery.store.dse.internal.TransformationRule;
13import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
14import tools.refinery.store.query.view.AnySymbolView;
15import tools.refinery.store.query.view.KeyOnlyView;
16import tools.refinery.store.representation.Symbol;
17import tools.refinery.store.tuple.Tuple;
18
19import java.util.List;
20import java.util.Map;
21
22import static org.junit.jupiter.api.Assertions.assertEquals;
23import static tools.refinery.store.query.literal.Literals.not;
24import static tools.refinery.store.dse.tests.QueryAssertions.assertResults;
25
26public class TransformationRuleTest {
27
28 private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
29 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
30 private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
31
32 private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
33 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
34
35 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
36 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
37
38 private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
39 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
40 private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
41 private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
42 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
43 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
44 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
45
46 @Test
47 void activationsTest() {
48 var assignFeaturePreconditionHelper = Query.of("AssignFeaturePreconditionHelper",
49 (builder, model, c, f) -> builder.clause(
50 classElementView.call(c),
51 classesView.call(model, c),
52 encapsulatesView.call(c, f)
53 ));
54
55 var assignFeaturePrecondition = Query.of("AssignFeaturePrecondition", (builder, c2, f)
56 -> builder.clause((model, c1) -> List.of(
57 classModelView.call(model),
58 featureView.call(f),
59 classElementView.call(c2),
60 featuresView.call(model, f),
61 classesView.call(model, c1),
62 not(assignFeaturePreconditionHelper.call(model, c2, f)),
63 not(encapsulatesView.call(c2, f))
64 )));
65
66 var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
67 (builder, model, c) -> builder.clause((f) -> List.of(
68 classModelView.call(model),
69 classElementView.call(c),
70 featuresView.call(model, f),
71 not(encapsulatesView.call(c, f))
72 )));
73
74 TransformationRule assignFeatureRule = new TransformationRule("AssignFeature",
75 assignFeaturePrecondition,
76 (model) -> {
77 var isEncapsulatedByInterpretation = model.getInterpretation(isEncapsulatedBy);
78 return ((Tuple activation) -> {
79 var feature = activation.get(0);
80 var classElement = activation.get(1);
81
82 isEncapsulatedByInterpretation.put(Tuple.of(feature, classElement), true);
83 });
84 });
85
86 TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
87 deleteEmptyClassPrecondition,
88 (model) -> {
89 var classesInterpretation = model.getInterpretation(classes);
90 var classElementInterpretation = model.getInterpretation(classElement);
91 return ((Tuple activation) -> {
92 var modelElement = activation.get(0);
93 var classElement = activation.get(1);
94
95 classesInterpretation.put(Tuple.of(modelElement, classElement), false);
96 classElementInterpretation.put(Tuple.of(classElement), false);
97 });
98 });
99
100
101 var store = ModelStore.builder()
102 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
103 .with(ViatraModelQueryAdapter.builder()
104 .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper,
105 deleteEmptyClassPrecondition))
106 .with(DesignSpaceExplorationAdapter.builder())
107 .build();
108
109 var model = store.createEmptyModel();
110 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
111 assignFeatureRule.prepare(model, queryEngine);
112 deleteEmptyClassRule.prepare(model, queryEngine);
113
114 var classModelInterpretation = model.getInterpretation(classModel);
115 var classElementInterpretation = model.getInterpretation(classElement);
116 var featureInterpretation = model.getInterpretation(feature);
117 var featuresInterpretation = model.getInterpretation(features);
118 var classesInterpretation = model.getInterpretation(classes);
119
120 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
121 var newModel = dseAdapter.createObject();
122 var newModelId = newModel.get(0);
123 var newClass1 = dseAdapter.createObject();
124 var newClass1Id = newClass1.get(0);
125 var newClass2 = dseAdapter.createObject();
126 var newClass2Id = newClass2.get(0);
127 var newField = dseAdapter.createObject();
128 var newFieldId = newField.get(0);
129
130 classModelInterpretation.put(newModel, true);
131 classElementInterpretation.put(newClass1, true);
132 classElementInterpretation.put(newClass2, true);
133 featureInterpretation.put(newField, true);
134 classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
135 classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
136 featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
137
138 queryEngine.flushChanges();
139
140 var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsSets();
141 var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsSets();
142
143 assertResults(Map.of(
144 Tuple.of(newClass1Id, newFieldId), true,
145 Tuple.of(newClass2Id, newFieldId), true
146 ), assignFeatureRuleActivations);
147
148 assertResults(Map.of(
149 Tuple.of(newModelId, newClass1Id), true,
150 Tuple.of(newModelId, newClass2Id), true
151 ), deleteEmptyClassRuleActivations);
152 }
153
154 @Test
155 void randomActivationTest() {
156 var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
157 (builder, model, c) -> builder.clause((f) -> List.of(
158 classModelView.call(model),
159 classElementView.call(c),
160 featuresView.call(model, f),
161 not(encapsulatesView.call(c, f))
162 )));
163
164 TransformationRule deleteEmptyClassRule0 = new TransformationRule("DeleteEmptyClass0",
165 deleteEmptyClassPrecondition,
166 (model) -> {
167 var classesInterpretation = model.getInterpretation(classes);
168 var classElementInterpretation = model.getInterpretation(classElement);
169 return ((Tuple activation) -> {
170 var modelElement = activation.get(0);
171 var classElement = activation.get(1);
172
173 classesInterpretation.put(Tuple.of(modelElement, classElement), false);
174 classElementInterpretation.put(Tuple.of(classElement), false);
175 });
176 },
177 0L);
178
179 TransformationRule deleteEmptyClassRule1 = new TransformationRule("DeleteEmptyClass1",
180 deleteEmptyClassPrecondition,
181 (model) -> {
182 var classesInterpretation = model.getInterpretation(classes);
183 var classElementInterpretation = model.getInterpretation(classElement);
184 return ((Tuple activation) -> {
185 var modelElement = activation.get(0);
186 var classElement = activation.get(1);
187
188 classesInterpretation.put(Tuple.of(modelElement, classElement), false);
189 classElementInterpretation.put(Tuple.of(classElement), false);
190 });
191 },
192 78634L);
193
194 var store = ModelStore.builder()
195 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
196 .with(ViatraModelQueryAdapter.builder()
197 .queries(deleteEmptyClassPrecondition))
198 .with(DesignSpaceExplorationAdapter.builder())
199 .build();
200
201 var model = store.createEmptyModel();
202 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
203 deleteEmptyClassRule0.prepare(model, queryEngine);
204 deleteEmptyClassRule1.prepare(model, queryEngine);
205
206 var classModelInterpretation = model.getInterpretation(classModel);
207 var classElementInterpretation = model.getInterpretation(classElement);
208 var featureInterpretation = model.getInterpretation(feature);
209 var featuresInterpretation = model.getInterpretation(features);
210 var classesInterpretation = model.getInterpretation(classes);
211
212 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
213 var newModel = dseAdapter.createObject();
214 var newModelId = newModel.get(0);
215 var newClass1 = dseAdapter.createObject();
216 var newClass1Id = newClass1.get(0);
217 var newClass2 = dseAdapter.createObject();
218 var newClass2Id = newClass2.get(0);
219 var newField = dseAdapter.createObject();
220 var newFieldId = newField.get(0);
221
222 classModelInterpretation.put(newModel, true);
223 classElementInterpretation.put(newClass1, true);
224 classElementInterpretation.put(newClass2, true);
225 featureInterpretation.put(newField, true);
226 classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
227 classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
228 featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
229
230 queryEngine.flushChanges();
231
232
233 var activation0 = deleteEmptyClassRule0.getRandomActivation().activation();
234 var activation1 = deleteEmptyClassRule1.getRandomActivation().activation();
235
236 assertResults(Map.of(
237 Tuple.of(newModelId, newClass1Id), true,
238 Tuple.of(newModelId, newClass2Id), true
239 ), deleteEmptyClassRule0.getAllActivationsAsSets());
240
241 assertResults(Map.of(
242 Tuple.of(newModelId, newClass1Id), true,
243 Tuple.of(newModelId, newClass2Id), true
244 ), deleteEmptyClassRule1.getAllActivationsAsSets());
245
246 assertEquals(Tuple.of(newModelId, newClass2Id), activation0);
247 assertEquals(Tuple.of(newModelId, newClass1Id), activation1);
248
249 }
250
251 @Test
252 void fireTest() {
253 var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
254 (builder, model, c) -> builder.clause((f) -> List.of(
255 classModelView.call(model),
256 classElementView.call(c),
257 featuresView.call(model, f),
258 not(encapsulatesView.call(c, f))
259 )));
260
261 TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
262 deleteEmptyClassPrecondition,
263 (model) -> {
264 var classesInterpretation = model.getInterpretation(classes);
265 var classElementInterpretation = model.getInterpretation(classElement);
266 return ((Tuple activation) -> {
267 var modelElement = activation.get(0);
268 var classElement = activation.get(1);
269
270 classesInterpretation.put(Tuple.of(modelElement, classElement), false);
271 classElementInterpretation.put(Tuple.of(classElement), false);
272 });
273 });
274
275 var store = ModelStore.builder()
276 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
277 .with(ViatraModelQueryAdapter.builder()
278 .queries(deleteEmptyClassPrecondition))
279 .with(DesignSpaceExplorationAdapter.builder())
280 .build();
281
282 var model = store.createEmptyModel();
283 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
284 deleteEmptyClassRule.prepare(model, queryEngine);
285
286 var classModelInterpretation = model.getInterpretation(classModel);
287 var classElementInterpretation = model.getInterpretation(classElement);
288 var featureInterpretation = model.getInterpretation(feature);
289 var featuresInterpretation = model.getInterpretation(features);
290 var classesInterpretation = model.getInterpretation(classes);
291
292 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
293 var newModel = dseAdapter.createObject();
294 var newModelId = newModel.get(0);
295 var newClass1 = dseAdapter.createObject();
296 var newClass1Id = newClass1.get(0);
297 var newClass2 = dseAdapter.createObject();
298 var newClass2Id = newClass2.get(0);
299 var newField = dseAdapter.createObject();
300 var newFieldId = newField.get(0);
301
302 classModelInterpretation.put(newModel, true);
303 classElementInterpretation.put(newClass1, true);
304 classElementInterpretation.put(newClass2, true);
305 featureInterpretation.put(newField, true);
306 classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
307 classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
308 featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
309
310 queryEngine.flushChanges();
311
312 assertResults(Map.of(
313 Tuple.of(newModelId, newClass1Id), true,
314 Tuple.of(newModelId, newClass2Id), true
315 ), deleteEmptyClassRule.getAllActivationsAsSets());
316
317
318 deleteEmptyClassRule.fireActivation(Tuple.of(0, 1));
319
320 assertResults(Map.of(
321 Tuple.of(newModelId, newClass1Id), false,
322 Tuple.of(newModelId, newClass2Id), true
323 ), deleteEmptyClassRule.getAllActivationsAsSets());
324 }
325
326 @Test
327 void randomFireTest() {
328 var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
329 (builder, model, c) -> builder.clause((f) -> List.of(
330 classModelView.call(model),
331 classElementView.call(c),
332 featuresView.call(model, f),
333 not(encapsulatesView.call(c, f))
334 )));
335
336 TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass0",
337 deleteEmptyClassPrecondition,
338 (model) -> {
339 var classesInterpretation = model.getInterpretation(classes);
340 var classElementInterpretation = model.getInterpretation(classElement);
341 return ((Tuple activation) -> {
342 var modelElement = activation.get(0);
343 var classElement = activation.get(1);
344
345 classesInterpretation.put(Tuple.of(modelElement, classElement), false);
346 classElementInterpretation.put(Tuple.of(classElement), false);
347 });
348 },
349 0L);
350
351 var store = ModelStore.builder()
352 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
353 .with(ViatraModelQueryAdapter.builder()
354 .queries(deleteEmptyClassPrecondition))
355 .with(DesignSpaceExplorationAdapter.builder())
356 .build();
357
358 var model = store.createEmptyModel();
359 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
360 deleteEmptyClassRule.prepare(model, queryEngine);
361
362 var classModelInterpretation = model.getInterpretation(classModel);
363 var classElementInterpretation = model.getInterpretation(classElement);
364 var featureInterpretation = model.getInterpretation(feature);
365 var featuresInterpretation = model.getInterpretation(features);
366 var classesInterpretation = model.getInterpretation(classes);
367
368 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
369 var newModel = dseAdapter.createObject();
370 var newModelId = newModel.get(0);
371 var newClass1 = dseAdapter.createObject();
372 var newClass1Id = newClass1.get(0);
373 var newClass2 = dseAdapter.createObject();
374 var newClass2Id = newClass2.get(0);
375 var newField = dseAdapter.createObject();
376 var newFieldId = newField.get(0);
377
378 classModelInterpretation.put(newModel, true);
379 classElementInterpretation.put(newClass1, true);
380 classElementInterpretation.put(newClass2, true);
381 featureInterpretation.put(newField, true);
382 classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
383 classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
384 featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
385
386 queryEngine.flushChanges();
387
388 assertResults(Map.of(
389 Tuple.of(newModelId, newClass1Id), true,
390 Tuple.of(newModelId, newClass2Id), true
391 ), deleteEmptyClassRule.getAllActivationsAsSets());
392
393 deleteEmptyClassRule.fireRandomActivation();
394
395 assertResults(Map.of(
396 Tuple.of(newModelId, newClass1Id), true,
397 Tuple.of(newModelId, newClass2Id), false
398 ), deleteEmptyClassRule.getAllActivationsAsSets());
399
400 deleteEmptyClassRule.fireRandomActivation();
401
402 assertResults(Map.of(
403 Tuple.of(newModelId, newClass1Id), false,
404 Tuple.of(newModelId, newClass2Id), false
405 ), deleteEmptyClassRule.getAllActivationsAsSets());
406
407 }
408}
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java
new file mode 100644
index 00000000..be514eaf
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java
@@ -0,0 +1,57 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.tests;
7
8import org.junit.jupiter.api.function.Executable;
9import tools.refinery.store.query.resultset.ResultSet;
10import tools.refinery.store.tuple.Tuple;
11
12import java.util.*;
13
14import static org.hamcrest.MatcherAssert.assertThat;
15import static org.hamcrest.Matchers.is;
16import static org.hamcrest.Matchers.nullValue;
17import static org.junit.jupiter.api.Assertions.assertAll;
18
19public final class QueryAssertions {
20 private QueryAssertions() {
21 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
22 }
23
24 public static <T> void assertNullableResults(Map<Tuple, Optional<T>> expected, ResultSet<T> resultSet) {
25 var nullableValuesMap = new LinkedHashMap<Tuple, T>(expected.size());
26 for (var entry : expected.entrySet()) {
27 nullableValuesMap.put(entry.getKey(), entry.getValue().orElse(null));
28 }
29 assertResults(nullableValuesMap, resultSet);
30 }
31
32 public static <T> void assertResults(Map<Tuple, T> expected, ResultSet<T> resultSet) {
33 var defaultValue = resultSet.getQuery().defaultValue();
34 var filteredExpected = new LinkedHashMap<Tuple, T>();
35 var executables = new ArrayList<Executable>();
36 for (var entry : expected.entrySet()) {
37 var key = entry.getKey();
38 var value = entry.getValue();
39 if (!Objects.equals(value, defaultValue)) {
40 filteredExpected.put(key, value);
41 }
42 executables.add(() -> assertThat("value for key " + key,resultSet.get(key), is(value)));
43 }
44 executables.add(() -> assertThat("results size", resultSet.size(), is(filteredExpected.size())));
45
46 var actual = new LinkedHashMap<Tuple, T>();
47 var cursor = resultSet.getAll();
48 while (cursor.move()) {
49 var key = cursor.getKey();
50 var previous = actual.put(key, cursor.getValue());
51 assertThat("duplicate value for key " + key, previous, nullValue());
52 }
53 executables.add(() -> assertThat("results cursor", actual, is(filteredExpected)));
54
55 assertAll(executables);
56 }
57}