aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse
diff options
context:
space:
mode:
authorLibravatar Attila Ficsor <ficsorattila96@gmail.com>2023-08-08 13:57:19 +0200
committerLibravatar Attila Ficsor <ficsorattila96@gmail.com>2023-08-08 14:33:16 +0200
commit1f853e4590d7f235bf8a63fa017fc92369a80a5a (patch)
treebd586d45d473b68a8d26fba2808e0489ab469217 /subprojects/store-dse
parentImprove performance of best first earch (diff)
downloadrefinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.tar.gz
refinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.tar.zst
refinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.zip
Refactor search strategy to improve readability
Diffstat (limited to 'subprojects/store-dse')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java2
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java10
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java29
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java55
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java4
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java4
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java168
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java13
8 files changed, 201 insertions, 84 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java
index 409fe8a6..c60a4410 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java
@@ -7,7 +7,7 @@ package tools.refinery.store.dse;
7 7
8public interface Strategy { 8public interface Strategy {
9 9
10 void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); 10 void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter);
11 11
12 void explore(); 12 void explore();
13} 13}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
index 008b2dab..04bba885 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
@@ -52,10 +52,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
52 52
53 private final Map<Version, Fitness> fitnessCache = new HashMap<>(); 53 private final Map<Version, Fitness> fitnessCache = new HashMap<>();
54 54
55 public List<Version> getTrajectory() {
56 return new ArrayList<>(trajectory);
57 }
58
59 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { 55 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) {
60 this.model = model; 56 this.model = model;
61 this.storeAdapter = storeAdapter; 57 this.storeAdapter = storeAdapter;
@@ -75,11 +71,16 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
75 objectives = storeAdapter.getObjectives(); 71 objectives = storeAdapter.getObjectives();
76 statesAndTraversedActivations = new HashMap<>(); 72 statesAndTraversedActivations = new HashMap<>();
77 strategy = storeAdapter.getStrategy(); 73 strategy = storeAdapter.getStrategy();
74 strategy.initialize(this);
78 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); 75 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null);
79 isVisualizationEnabled = modelVisualizerAdapter != null; 76 isVisualizationEnabled = modelVisualizerAdapter != null;
80 77
81 } 78 }
82 79
80 public List<Version> getTrajectory() {
81 return new ArrayList<>(trajectory);
82 }
83
83 @Override 84 @Override
84 public Model getModel() { 85 public Model getModel() {
85 return model; 86 return model;
@@ -94,7 +95,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
94 public List<Version> explore() { 95 public List<Version> explore() {
95 var state = model.commit(); 96 var state = model.commit();
96 trajectory.add(state); 97 trajectory.add(state);
97 strategy.initStrategy(this);
98 strategy.explore(); 98 strategy.explore();
99 if (isVisualizationEnabled) { 99 if (isVisualizationEnabled) {
100 modelVisualizerAdapter.visualize(); 100 modelVisualizerAdapter.visualize();
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java
index 0883d3d7..047b204a 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java
@@ -22,8 +22,8 @@ public class BestFirstStrategy implements Strategy {
22 22
23 private DesignSpaceExplorationAdapter dseAdapter; 23 private DesignSpaceExplorationAdapter dseAdapter;
24 24
25 private final int maxDepth; 25 private int maxDepth = Integer.MAX_VALUE;
26 private final int maxSolutions; 26 private int maxSolutions = Integer.MAX_VALUE;
27 private boolean backTrackIfSolution = true; 27 private boolean backTrackIfSolution = true;
28 private boolean onlyBetterFirst = false; 28 private boolean onlyBetterFirst = false;
29 29
@@ -50,25 +50,18 @@ public class BestFirstStrategy implements Strategy {
50 } 50 }
51 } 51 }
52 52
53 public BestFirstStrategy() { 53 public BestFirstStrategy withDepthLimit(int maxDepth) {
54 this(-1); 54 if (maxDepth >= 0) {
55 }
56
57 public BestFirstStrategy(int maxDepth) {
58 this(maxDepth, -1);
59 }
60
61 public BestFirstStrategy(int maxDepth, int maxSolutions) {
62 if (maxDepth < 0) {
63 this.maxDepth = Integer.MAX_VALUE;
64 } else {
65 this.maxDepth = maxDepth; 55 this.maxDepth = maxDepth;
66 } 56 }
67 if (maxSolutions < 0) { 57 return this;
68 this.maxSolutions = Integer.MAX_VALUE; 58 }
69 } else { 59
60 public BestFirstStrategy withSolutionLimit(int maxSolutions) {
61 if (maxSolutions >= 0) {
70 this.maxSolutions = maxSolutions; 62 this.maxSolutions = maxSolutions;
71 } 63 }
64 return this;
72 } 65 }
73 66
74 public BestFirstStrategy continueIfHardObjectivesFulfilled() { 67 public BestFirstStrategy continueIfHardObjectivesFulfilled() {
@@ -82,7 +75,7 @@ public class BestFirstStrategy implements Strategy {
82 } 75 }
83 76
84 @Override 77 @Override
85 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { 78 public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
86 this.dseAdapter = designSpaceExplorationAdapter; 79 this.dseAdapter = designSpaceExplorationAdapter;
87 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); 80 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
88 81
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java
index 425e1e01..5f7f61b8 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java
@@ -1,12 +1,8 @@
1/******************************************************************************* 1/*
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro 2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * 3 *
8 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/ 5 */
10package tools.refinery.store.dse.strategy; 6package tools.refinery.store.dse.strategy;
11 7
12import tools.refinery.store.dse.DesignSpaceExplorationAdapter; 8import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
@@ -17,38 +13,31 @@ public class DepthFirstStrategy implements Strategy {
17 13
18 private DesignSpaceExplorationAdapter dseAdapter; 14 private DesignSpaceExplorationAdapter dseAdapter;
19 15
20 private int maxDepth; 16 private int maxDepth = Integer.MAX_VALUE;
21 private int maxSolutions; 17 private int maxSolutions = Integer.MAX_VALUE;
22 private boolean backTrackIfSolution = true; 18 private boolean backtrackFromSolution = true;
23 19
24 public DepthFirstStrategy() { 20 public DepthFirstStrategy withDepthLimit(int maxDepth) {
25 this(-1); 21 if (maxDepth >= 0) {
26 }
27
28 public DepthFirstStrategy(int maxDepth) {
29 this(maxDepth, -1);
30 }
31
32 public DepthFirstStrategy(int maxDepth, int maxSolutions) {
33 if (maxDepth < 0) {
34 this.maxDepth = Integer.MAX_VALUE;
35 } else {
36 this.maxDepth = maxDepth; 22 this.maxDepth = maxDepth;
37 } 23 }
38 if (maxSolutions < 0) { 24 return this;
39 this.maxSolutions = Integer.MAX_VALUE; 25 }
40 } else { 26
27 public DepthFirstStrategy withSolutionLimit(int maxSolutions) {
28 if (maxSolutions >= 0) {
41 this.maxSolutions = maxSolutions; 29 this.maxSolutions = maxSolutions;
42 } 30 }
31 return this;
43 } 32 }
44 33
45 public DepthFirstStrategy continueIfHardObjectivesFulfilled() { 34 public DepthFirstStrategy continueIfHardObjectivesFulfilled() {
46 backTrackIfSolution = false; 35 backtrackFromSolution = false;
47 return this; 36 return this;
48 } 37 }
49 38
50 @Override 39 @Override
51 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { 40 public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
52 this.dseAdapter = designSpaceExplorationAdapter; 41 this.dseAdapter = designSpaceExplorationAdapter;
53 } 42 }
54 43
@@ -59,22 +48,18 @@ public class DepthFirstStrategy implements Strategy {
59 } 48 }
60 while (dseAdapter.getSolutions().size() < maxSolutions) { 49 while (dseAdapter.getSolutions().size() < maxSolutions) {
61 if (!checkAndHandleGlobalConstraints()) { 50 if (!checkAndHandleGlobalConstraints()) {
62 // Global constraint is not satisfied and cannot backtrack.
63 return; 51 return;
64 } 52 }
65 // Global constraint is not satisfied, backtrack.
66 53
67 Fitness fitness = dseAdapter.getFitness(); 54 Fitness fitness = dseAdapter.getFitness();
68 if (fitness.isSatisfiesHardObjectives()) { 55 if (fitness.isSatisfiesHardObjectives()) {
69 dseAdapter.newSolution(); 56 dseAdapter.newSolution();
70 if (backTrackIfSolution && !dseAdapter.backtrack()) { 57 if (backtrackFromSolution && !dseAdapter.backtrack()) {
71 // Found a solution but cannot backtrack.
72 return; 58 return;
73 } 59 }
74 } 60 }
75 61
76 if (!checkAndHandleDepth()) { 62 if (!checkAndHandleDepth()) {
77 // Reached max depth but cannot backtrack.
78 return; 63 return;
79 } 64 }
80 65
@@ -87,24 +72,18 @@ public class DepthFirstStrategy implements Strategy {
87 } 72 }
88 73
89 private boolean checkAndHandleGlobalConstraints() { 74 private boolean checkAndHandleGlobalConstraints() {
90 // Global constraint is not satisfied and cannot backtrack.
91 return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack(); 75 return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack();
92 // Global constraint is satisfied or backtrack.
93 } 76 }
94 77
95 private boolean checkAndHandleDepth() { 78 private boolean checkAndHandleDepth() {
96 // Reached max depth but cannot backtrack.
97 return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack(); 79 return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack();
98 // Reached max depth or backtrack.
99 } 80 }
100 81
101 private boolean backtrackToLastUntraversed() { 82 private boolean backtrackToLastUntraversed() {
102 while (dseAdapter.getUntraversedActivations().isEmpty()) { 83 while (dseAdapter.getUntraversedActivations().isEmpty()) {
103 if (!dseAdapter.backtrack()) { 84 if (!dseAdapter.backtrack()) {
104 // No more transitions from current state and cannot backtrack.
105 return false; 85 return false;
106 } 86 }
107 // No more transitions from current state, backtrack.
108 } 87 }
109 return true; 88 return true;
110 } 89 }
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
index d761db02..225de32e 100644
--- 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
@@ -201,8 +201,8 @@ class CRAExamplesTest {
201 .with(DesignSpaceExplorationAdapter.builder() 201 .with(DesignSpaceExplorationAdapter.builder()
202 .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) 202 .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule)
203 .objectives(new AlwaysSatisfiedRandomHardObjective()) 203 .objectives(new AlwaysSatisfiedRandomHardObjective())
204// .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled() 204// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled()
205 .strategy(new BestFirstStrategy(6).continueIfHardObjectivesFulfilled() 205 .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled()
206// .goOnOnlyIfFitnessIsBetter() 206// .goOnOnlyIfFitnessIsBetter()
207 )) 207 ))
208 .build(); 208 .build();
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
index 36bc6cce..c6da896c 100644
--- 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
@@ -103,8 +103,8 @@ class DebugTest {
103 .with(DesignSpaceExplorationAdapter.builder() 103 .with(DesignSpaceExplorationAdapter.builder()
104 .transformations(createClassRule, createFeatureRule) 104 .transformations(createClassRule, createFeatureRule)
105 .objectives(new AlwaysSatisfiedRandomHardObjective()) 105 .objectives(new AlwaysSatisfiedRandomHardObjective())
106 .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() 106 .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
107// .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() 107// .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
108// .goOnOnlyIfFitnessIsBetter() 108// .goOnOnlyIfFitnessIsBetter()
109 )) 109 ))
110 .build(); 110 .build();
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
index 89adbf65..91e33f4a 100644
--- 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
@@ -49,7 +49,8 @@ class DesignSpaceExplorationTest {
49 void createObjectTest() { 49 void createObjectTest() {
50 var store = ModelStore.builder() 50 var store = ModelStore.builder()
51 .with(ViatraModelQueryAdapter.builder()) 51 .with(ViatraModelQueryAdapter.builder())
52 .with(DesignSpaceExplorationAdapter.builder()) 52 .with(DesignSpaceExplorationAdapter.builder()
53 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
53 .build(); 54 .build();
54 55
55 var model = store.createEmptyModel(); 56 var model = store.createEmptyModel();
@@ -77,7 +78,8 @@ class DesignSpaceExplorationTest {
77 void deleteMiddleObjectTest() { 78 void deleteMiddleObjectTest() {
78 var store = ModelStore.builder() 79 var store = ModelStore.builder()
79 .with(ViatraModelQueryAdapter.builder()) 80 .with(ViatraModelQueryAdapter.builder())
80 .with(DesignSpaceExplorationAdapter.builder()) 81 .with(DesignSpaceExplorationAdapter.builder()
82 .strategy(new DepthFirstStrategy()))
81 .build(); 83 .build();
82 84
83 var model = store.createEmptyModel(); 85 var model = store.createEmptyModel();
@@ -118,7 +120,7 @@ class DesignSpaceExplorationTest {
118 .symbols(classModel) 120 .symbols(classModel)
119 .with(ViatraModelQueryAdapter.builder()) 121 .with(ViatraModelQueryAdapter.builder())
120 .with(DesignSpaceExplorationAdapter.builder() 122 .with(DesignSpaceExplorationAdapter.builder()
121 .strategy(new DepthFirstStrategy(0))) 123 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
122 .build(); 124 .build();
123 125
124 var model = store.createEmptyModel(); 126 var model = store.createEmptyModel();
@@ -158,7 +160,7 @@ class DesignSpaceExplorationTest {
158 .queries(createClassPrecondition)) 160 .queries(createClassPrecondition))
159 .with(DesignSpaceExplorationAdapter.builder() 161 .with(DesignSpaceExplorationAdapter.builder()
160 .transformations(createClassRule) 162 .transformations(createClassRule)
161 .strategy(new DepthFirstStrategy(4) 163 .strategy(new DepthFirstStrategy().withDepthLimit(0)
162 )) 164 ))
163 .build(); 165 .build();
164 166
@@ -204,7 +206,7 @@ class DesignSpaceExplorationTest {
204 .queries(createClassPrecondition)) 206 .queries(createClassPrecondition))
205 .with(DesignSpaceExplorationAdapter.builder() 207 .with(DesignSpaceExplorationAdapter.builder()
206 .transformations(createClassRule) 208 .transformations(createClassRule)
207 .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() 209 .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
208 )) 210 ))
209 .build(); 211 .build();
210 212
@@ -272,7 +274,7 @@ class DesignSpaceExplorationTest {
272 .queries(createClassPrecondition, createFeaturePrecondition)) 274 .queries(createClassPrecondition, createFeaturePrecondition))
273 .with(DesignSpaceExplorationAdapter.builder() 275 .with(DesignSpaceExplorationAdapter.builder()
274 .transformations(createClassRule, createFeatureRule) 276 .transformations(createClassRule, createFeatureRule)
275 .strategy(new DepthFirstStrategy(10).continueIfHardObjectivesFulfilled() 277 .strategy(new DepthFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
276 )) 278 ))
277 .build(); 279 .build();
278 280
@@ -289,12 +291,81 @@ class DesignSpaceExplorationTest {
289 } 291 }
290 292
291 @Test 293 @Test
292 void BFSTrivialTest() { 294 void DFSSolutionLimitTest() {
295 var createClassPrecondition = Query.of("CreateClassPrecondition",
296 (builder, model) -> builder.clause(
297 classModelView.call(model)
298 ));
299
300 var createClassRule = new TransformationRule("CreateClass",
301 createClassPrecondition,
302 (model) -> {
303 var classesInterpretation = model.getInterpretation(classes);
304 var classElementInterpretation = model.getInterpretation(classElement);
305 return ((Tuple activation) -> {
306 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
307 var modelElement = activation.get(0);
308
309 var newClassElement = dseAdapter.createObject();
310 var newClassElementId = newClassElement.get(0);
311
312 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
313 classElementInterpretation.put(Tuple.of(newClassElementId), true);
314 });
315 });
316
317 var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
318 (builder, model) -> builder.clause(
319 classModelView.call(model)
320 ));
321
322 var createFeatureRule = new TransformationRule("CreateFeature",
323 createFeaturePrecondition,
324 (model) -> {
325 var featuresInterpretation = model.getInterpretation(features);
326 var featureInterpretation = model.getInterpretation(feature);
327 return ((Tuple activation) -> {
328 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
329 var modelElement = activation.get(0);
330
331 var newClassElement = dseAdapter.createObject();
332 var newClassElementId = newClassElement.get(0);
333
334 featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
335 featureInterpretation.put(Tuple.of(newClassElementId), true);
336 });
337 });
338
339 var store = ModelStore.builder()
340 .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
341 .with(ViatraModelQueryAdapter.builder()
342 .queries(createClassPrecondition, createFeaturePrecondition))
343 .with(DesignSpaceExplorationAdapter.builder()
344 .transformations(createClassRule, createFeatureRule)
345 .strategy(new DepthFirstStrategy().withSolutionLimit(222)
346 .continueIfHardObjectivesFulfilled()
347 ))
348 .build();
349
350 var model = store.createEmptyModel();
351 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
352 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
353
354 var modelElementInterpretation = model.getInterpretation(classModel);
355 modelElementInterpretation.put(dseAdapter.createObject(), true);
356 queryEngine.flushChanges();
357
358 var states = dseAdapter.explore();
359 assertEquals(222, states.size());
360 }
361
362 @Test
363 void BeFSTrivialTest() {
293 var store = ModelStore.builder() 364 var store = ModelStore.builder()
294 .symbols(classModel) 365 .symbols(classModel)
295 .with(ViatraModelQueryAdapter.builder()) 366 .with(ViatraModelQueryAdapter.builder())
296 .with(DesignSpaceExplorationAdapter.builder() 367 .with(DesignSpaceExplorationAdapter.builder()
297 .strategy(new BestFirstStrategy(0))) 368 .strategy(new BestFirstStrategy().withDepthLimit(0)))
298 .build(); 369 .build();
299 370
300 var model = store.createEmptyModel(); 371 var model = store.createEmptyModel();
@@ -305,7 +376,7 @@ class DesignSpaceExplorationTest {
305 } 376 }
306 377
307 @Test 378 @Test
308 void BFSOneRuleTest() { 379 void BeFSOneRuleTest() {
309 var createClassPrecondition = Query.of("CreateClassPrecondition", 380 var createClassPrecondition = Query.of("CreateClassPrecondition",
310 (builder, model) -> builder.clause( 381 (builder, model) -> builder.clause(
311 classModelView.call(model) 382 classModelView.call(model)
@@ -334,7 +405,7 @@ class DesignSpaceExplorationTest {
334 .queries(createClassPrecondition)) 405 .queries(createClassPrecondition))
335 .with(DesignSpaceExplorationAdapter.builder() 406 .with(DesignSpaceExplorationAdapter.builder()
336 .transformations(createClassRule) 407 .transformations(createClassRule)
337 .strategy(new BestFirstStrategy(4) 408 .strategy(new BestFirstStrategy().withDepthLimit(4)
338 )) 409 ))
339 .build(); 410 .build();
340 411
@@ -351,7 +422,7 @@ class DesignSpaceExplorationTest {
351 } 422 }
352 423
353 @Test 424 @Test
354 void BFSContinueTest() { 425 void BeFSContinueTest() {
355 var createClassPrecondition = Query.of("CreateClassPrecondition", 426 var createClassPrecondition = Query.of("CreateClassPrecondition",
356 (builder, model) -> builder.clause( 427 (builder, model) -> builder.clause(
357 classModelView.call(model) 428 classModelView.call(model)
@@ -380,7 +451,7 @@ class DesignSpaceExplorationTest {
380 .queries(createClassPrecondition)) 451 .queries(createClassPrecondition))
381 .with(DesignSpaceExplorationAdapter.builder() 452 .with(DesignSpaceExplorationAdapter.builder()
382 .transformations(createClassRule) 453 .transformations(createClassRule)
383 .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() 454 .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
384 )) 455 ))
385 .build(); 456 .build();
386 457
@@ -397,7 +468,7 @@ class DesignSpaceExplorationTest {
397 } 468 }
398 469
399 @Test 470 @Test
400 void BFSCompletenessTest() { 471 void BeFSCompletenessTest() {
401 var createClassPrecondition = Query.of("CreateClassPrecondition", 472 var createClassPrecondition = Query.of("CreateClassPrecondition",
402 (builder, model) -> builder.clause( 473 (builder, model) -> builder.clause(
403 classModelView.call(model) 474 classModelView.call(model)
@@ -448,7 +519,7 @@ class DesignSpaceExplorationTest {
448 .queries(createClassPrecondition, createFeaturePrecondition)) 519 .queries(createClassPrecondition, createFeaturePrecondition))
449 .with(DesignSpaceExplorationAdapter.builder() 520 .with(DesignSpaceExplorationAdapter.builder()
450 .transformations(createClassRule, createFeatureRule) 521 .transformations(createClassRule, createFeatureRule)
451 .strategy(new BestFirstStrategy(10).continueIfHardObjectivesFulfilled() 522 .strategy(new BestFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
452 )) 523 ))
453 .build(); 524 .build();
454 525
@@ -464,4 +535,73 @@ class DesignSpaceExplorationTest {
464 assertEquals(2047, states.size()); 535 assertEquals(2047, states.size());
465 } 536 }
466 537
538 @Test
539 void BeFSSolutionLimitTest() {
540 var createClassPrecondition = Query.of("CreateClassPrecondition",
541 (builder, model) -> builder.clause(
542 classModelView.call(model)
543 ));
544
545 var createClassRule = new TransformationRule("CreateClass",
546 createClassPrecondition,
547 (model) -> {
548 var classesInterpretation = model.getInterpretation(classes);
549 var classElementInterpretation = model.getInterpretation(classElement);
550 return ((Tuple activation) -> {
551 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
552 var modelElement = activation.get(0);
553
554 var newClassElement = dseAdapter.createObject();
555 var newClassElementId = newClassElement.get(0);
556
557 classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
558 classElementInterpretation.put(Tuple.of(newClassElementId), true);
559 });
560 });
561
562 var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
563 (builder, model) -> builder.clause(
564 classModelView.call(model)
565 ));
566
567 var createFeatureRule = new TransformationRule("CreateFeature",
568 createFeaturePrecondition,
569 (model) -> {
570 var featuresInterpretation = model.getInterpretation(features);
571 var featureInterpretation = model.getInterpretation(feature);
572 return ((Tuple activation) -> {
573 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
574 var modelElement = activation.get(0);
575
576 var newClassElement = dseAdapter.createObject();
577 var newClassElementId = newClassElement.get(0);
578
579 featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
580 featureInterpretation.put(Tuple.of(newClassElementId), true);
581 });
582 });
583
584 var store = ModelStore.builder()
585 .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
586 .with(ViatraModelQueryAdapter.builder()
587 .queries(createClassPrecondition, createFeaturePrecondition))
588 .with(DesignSpaceExplorationAdapter.builder()
589 .transformations(createClassRule, createFeatureRule)
590 .strategy(new BestFirstStrategy().withSolutionLimit(222)
591 .continueIfHardObjectivesFulfilled()
592 ))
593 .build();
594
595 var model = store.createEmptyModel();
596 var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
597 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
598
599 var modelElementInterpretation = model.getInterpretation(classModel);
600 modelElementInterpretation.put(dseAdapter.createObject(), true);
601 queryEngine.flushChanges();
602
603 var states = dseAdapter.explore();
604 assertEquals(222, states.size());
605 }
606
467} 607}
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
index 3aa4c92e..5d24d712 100644
--- 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
@@ -6,6 +6,7 @@
6package tools.refinery.store.dse; 6package tools.refinery.store.dse;
7 7
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.dse.strategy.DepthFirstStrategy;
9import tools.refinery.store.model.ModelStore; 10import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.query.ModelQueryAdapter; 11import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.Query; 12import tools.refinery.store.query.dnf.Query;
@@ -103,7 +104,8 @@ class TransformationRuleTest {
103 .with(ViatraModelQueryAdapter.builder() 104 .with(ViatraModelQueryAdapter.builder()
104 .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper, 105 .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper,
105 deleteEmptyClassPrecondition)) 106 deleteEmptyClassPrecondition))
106 .with(DesignSpaceExplorationAdapter.builder()) 107 .with(DesignSpaceExplorationAdapter.builder()
108 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
107 .build(); 109 .build();
108 110
109 var model = store.createEmptyModel(); 111 var model = store.createEmptyModel();
@@ -195,7 +197,8 @@ class TransformationRuleTest {
195 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) 197 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
196 .with(ViatraModelQueryAdapter.builder() 198 .with(ViatraModelQueryAdapter.builder()
197 .queries(deleteEmptyClassPrecondition)) 199 .queries(deleteEmptyClassPrecondition))
198 .with(DesignSpaceExplorationAdapter.builder()) 200 .with(DesignSpaceExplorationAdapter.builder()
201 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
199 .build(); 202 .build();
200 203
201 var model = store.createEmptyModel(); 204 var model = store.createEmptyModel();
@@ -276,7 +279,8 @@ class TransformationRuleTest {
276 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) 279 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
277 .with(ViatraModelQueryAdapter.builder() 280 .with(ViatraModelQueryAdapter.builder()
278 .queries(deleteEmptyClassPrecondition)) 281 .queries(deleteEmptyClassPrecondition))
279 .with(DesignSpaceExplorationAdapter.builder()) 282 .with(DesignSpaceExplorationAdapter.builder()
283 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
280 .build(); 284 .build();
281 285
282 var model = store.createEmptyModel(); 286 var model = store.createEmptyModel();
@@ -352,7 +356,8 @@ class TransformationRuleTest {
352 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) 356 .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
353 .with(ViatraModelQueryAdapter.builder() 357 .with(ViatraModelQueryAdapter.builder()
354 .queries(deleteEmptyClassPrecondition)) 358 .queries(deleteEmptyClassPrecondition))
355 .with(DesignSpaceExplorationAdapter.builder()) 359 .with(DesignSpaceExplorationAdapter.builder()
360 .strategy(new DepthFirstStrategy().withDepthLimit(0)))
356 .build(); 361 .build();
357 362
358 var model = store.createEmptyModel(); 363 var model = store.createEmptyModel();