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