aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse
diff options
context:
space:
mode:
authorLibravatar Attila Ficsor <ficsorattila96@gmail.com>2023-08-07 12:04:58 +0200
committerLibravatar Attila Ficsor <ficsorattila96@gmail.com>2023-08-07 15:12:17 +0200
commite722deec08fe509f3e5a2b701c7e3260ee10aa66 (patch)
tree8ab265f8550ed121031be9d7707d837a588bac9e /subprojects/store-dse
parentMerge pull request #33 from OszkarSemerath/datastructure (diff)
downloadrefinery-e722deec08fe509f3e5a2b701c7e3260ee10aa66.tar.gz
refinery-e722deec08fe509f3e5a2b701c7e3260ee10aa66.tar.zst
refinery-e722deec08fe509f3e5a2b701c7e3260ee10aa66.zip
Update exploration strategies
- Fix best first search algorithm - Improve efficiency of exploration adapter
Diffstat (limited to 'subprojects/store-dse')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java6
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java18
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java4
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java92
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java27
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java16
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java36
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java20
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java18
9 files changed, 161 insertions, 76 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
index 8963a496..c4aa97c2 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
@@ -38,7 +38,9 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter {
38 38
39 public boolean backtrack(); 39 public boolean backtrack();
40 40
41 public Fitness calculateFitness(); 41 public boolean backtrack(String reason);
42
43 public Fitness getFitness();
42 44
43 public void newSolution(); 45 public void newSolution();
44 46
@@ -63,4 +65,6 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter {
63 public void setRandom(Random random); 65 public void setRandom(Random random);
64 66
65 public void setRandom(long seed); 67 public void setRandom(long seed);
68
69 public List<Version> getSolutions();
66} 70}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java
index 186bfebb..0252748d 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java
@@ -6,6 +6,24 @@
6package tools.refinery.store.dse; 6package tools.refinery.store.dse;
7 7
8import tools.refinery.store.adapter.ModelStoreAdapter; 8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.dse.internal.TransformationRule;
10import tools.refinery.store.dse.objectives.Objective;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.query.dnf.RelationalQuery;
13
14import java.util.List;
15import java.util.Set;
9 16
10public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter { 17public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter {
18
19 @Override
20 DesignSpaceExplorationAdapter createModelAdapter(Model model);
21
22 Set<TransformationRule> getTransformationSpecifications();
23
24 Set<RelationalQuery> getGlobalConstraints();
25
26 List<Objective> getObjectives();
27
28 Strategy getStrategy();
11} 29}
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 e240f478..409fe8a6 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 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); 10 void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter);
11 11
12 public 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 b32e9696..4e5cc467 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
@@ -33,26 +33,28 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
33 private final Model model; 33 private final Model model;
34 private final ModelQueryAdapter queryEngine; 34 private final ModelQueryAdapter queryEngine;
35 private final DesignSpaceExplorationStoreAdapterImpl storeAdapter; 35 private final DesignSpaceExplorationStoreAdapterImpl storeAdapter;
36 private final LinkedHashSet<TransformationRule> transformationRules; 36 private final Set<TransformationRule> transformationRules;
37 private final LinkedHashSet<RelationalQuery> globalConstraints; 37 private final Set<RelationalQuery> globalConstraints;
38 private final List<Objective> objectives; 38 private final List<Objective> objectives;
39 private final LinkedHashSet<ResultSet<Boolean>> globalConstraintResultSets = new LinkedHashSet<>(); 39 private final LinkedHashSet<ResultSet<Boolean>> globalConstraintResultSets = new LinkedHashSet<>();
40 private final Interpretation<Integer> sizeInterpretation; 40 private final Interpretation<Integer> sizeInterpretation;
41 private final Strategy strategy; 41 private final Strategy strategy;
42 42
43 private ObjectiveComparatorHelper objectiveComparatorHelper; 43 private ObjectiveComparatorHelper objectiveComparatorHelper;
44 private List<Version> trajectory = new LinkedList<>(); 44 private List<Version> trajectory = new ArrayList<>();
45 private Map<Version, Version> parents = new HashMap<>();
45 private Fitness lastFitness; 46 private Fitness lastFitness;
46 private final LinkedHashSet<Version> solutions = new LinkedHashSet<>(); 47 private final List<Version> solutions = new ArrayList<>();
47 private Map<Version, LinkedHashSet<Activation>> statesAndUntraversedActivations; 48 private Map<Version, List<Activation>> statesAndTraversedActivations;
48 private Map<Version, LinkedHashSet<Activation>> statesAndTraversedActivations;
49 private Random random = new Random(); 49 private Random random = new Random();
50 private boolean isNewState = false; 50 private boolean isNewState = false;
51 private final boolean isVisualizationEnabled; 51 private final boolean isVisualizationEnabled;
52 private final ModelVisualizerAdapter modelVisualizerAdapter; 52 private final ModelVisualizerAdapter modelVisualizerAdapter;
53 53
54 private final Map<Version, Fitness> fitnessCache = new HashMap<>();
55
54 public List<Version> getTrajectory() { 56 public List<Version> getTrajectory() {
55 return new LinkedList<>(trajectory); 57 return new ArrayList<>(trajectory);
56 } 58 }
57 59
58 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { 60 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) {
@@ -72,7 +74,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
72 } 74 }
73 75
74 objectives = storeAdapter.getObjectives(); 76 objectives = storeAdapter.getObjectives();
75 statesAndUntraversedActivations = new HashMap<>();
76 statesAndTraversedActivations = new HashMap<>(); 77 statesAndTraversedActivations = new HashMap<>();
77 strategy = storeAdapter.getStrategy(); 78 strategy = storeAdapter.getStrategy();
78 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); 79 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null);
@@ -91,11 +92,9 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
91 } 92 }
92 93
93 @Override 94 @Override
94 public LinkedHashSet<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 statesAndUntraversedActivations.put(state, getAllActivations());
98 statesAndTraversedActivations.put(state, new LinkedHashSet<>());
99 strategy.initStrategy(this); 98 strategy.initStrategy(this);
100 strategy.explore(); 99 strategy.explore();
101 return solutions; 100 return solutions;
@@ -137,14 +136,22 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
137 136
138 @Override 137 @Override
139 public boolean backtrack() { 138 public boolean backtrack() {
139 return backtrack("");
140 }
141 @Override
142 public boolean backtrack(String reason) {
140 if (trajectory.size() < 2) { 143 if (trajectory.size() < 2) {
141 return false; 144 return false;
142 } 145 }
146 var currentState = model.getState();
147 if (!parents.containsKey(currentState)) {
148 return false;
149 }
143 if (isVisualizationEnabled) { 150 if (isVisualizationEnabled) {
144 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 1), 151 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 1),
145 trajectory.get(trajectory.size() - 2), "backtrack"); 152 trajectory.get(trajectory.size() - 2), "backtrack(" + reason + ")");
146 } 153 }
147 model.restore(trajectory.get(trajectory.size() - 2)); 154 model.restore(parents.get(model.getState()));
148 trajectory.remove(trajectory.size() - 1); 155 trajectory.remove(trajectory.size() - 1);
149 return true; 156 return true;
150 } 157 }
@@ -156,7 +163,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
156// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1), 163// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1),
157// trajectory.get(trajectory.size() - 1), "restore"); 164// trajectory.get(trajectory.size() - 1), "restore");
158// } 165// }
159 this.trajectory = trajectory; 166 this.trajectory = new ArrayList<>(trajectory);
160 167
161 } 168 }
162 169
@@ -171,7 +178,18 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
171 } 178 }
172 179
173 @Override 180 @Override
174 public Fitness calculateFitness() { 181 public List<Version> getSolutions() {
182 return solutions;
183 }
184
185 @Override
186 public Fitness getFitness() {
187 var result = fitnessCache.computeIfAbsent(model.getState(), s -> calculateFitness());
188 lastFitness = result;
189 return result;
190 }
191
192 private Fitness calculateFitness() {
175 Fitness result = new Fitness(); 193 Fitness result = new Fitness();
176 boolean satisfiesHardObjectives = true; 194 boolean satisfiesHardObjectives = true;
177 for (Objective objective : objectives) { 195 for (Objective objective : objectives) {
@@ -203,15 +221,19 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
203 } 221 }
204 222
205 public LinkedHashSet<Activation> getUntraversedActivations() { 223 public LinkedHashSet<Activation> getUntraversedActivations() {
206// return statesAndUntraversedActivations.get(model.getState()); 224 var traversedActivations = statesAndTraversedActivations.get(model.getState());
207 LinkedHashSet<Activation> untraversedActivations = new LinkedHashSet<>(); 225 if (traversedActivations == null) {
208 for (Activation activation : getAllActivations()) { 226 return new LinkedHashSet<>(getAllActivations());
209 if (!statesAndTraversedActivations.get(model.getState()).contains(activation)) { 227 }
210 untraversedActivations.add(activation); 228 else {
229 LinkedHashSet<Activation> untraversedActivations = new LinkedHashSet<>();
230 for (Activation activation : getAllActivations()) {
231 if (!traversedActivations.contains(activation)) {
232 untraversedActivations.add(activation);
233 }
211 } 234 }
235 return untraversedActivations;
212 } 236 }
213
214 return untraversedActivations;
215 } 237 }
216 238
217 @Override 239 @Override
@@ -220,26 +242,20 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
220 return false; 242 return false;
221 } 243 }
222 var previousState = model.getState(); 244 var previousState = model.getState();
223 if (!statesAndUntraversedActivations.get(previousState).contains(activation)) {
224// TODO: throw exception?
225 return false;
226 }
227 if (!activation.fire()) { 245 if (!activation.fire()) {
228 return false; 246 return false;
229 } 247 }
230 statesAndUntraversedActivations.get(previousState).remove(activation); 248 statesAndTraversedActivations.computeIfAbsent(previousState, s -> new ArrayList<>()).add(activation);
231 statesAndTraversedActivations.get(previousState).add(activation);
232 var newState = model.commit(); 249 var newState = model.commit();
233 trajectory.add(newState); 250 trajectory.add(newState);
234 isNewState = !statesAndUntraversedActivations.containsKey(newState); 251 parents.put(newState, previousState);
235 statesAndUntraversedActivations.put(newState, getAllActivations()); 252 isNewState = !statesAndTraversedActivations.containsKey(newState);
236 statesAndTraversedActivations.put(newState, new LinkedHashSet<>());
237 if (isVisualizationEnabled) { 253 if (isVisualizationEnabled) {
238 if (isNewState) { 254 if (isNewState) {
239 modelVisualizerAdapter.addState(newState); 255 modelVisualizerAdapter.addState(newState);
240 } 256 }
241 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 2), 257 // TODO: Change to this:
242 trajectory.get(trajectory.size() - 1), activation.transformationRule().getName(), 258 modelVisualizerAdapter.addTransition(previousState, newState, activation.transformationRule().getName(),
243 activation.activation()); 259 activation.activation());
244 } 260 }
245 return true; 261 return true;
@@ -266,10 +282,10 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
266 return trajectory.contains(model.getState()); 282 return trajectory.contains(model.getState());
267 } 283 }
268 284
269 public LinkedHashSet<Activation> getAllActivations() { 285 public List<Activation> getAllActivations() {
270 LinkedHashSet<Activation> result = new LinkedHashSet<>(); 286 List<Activation> result = new LinkedList<>();
271 for (var rule : transformationRules) { 287 for (var rule : transformationRules) {
272 result.addAll(rule.getAllActivations()); 288 result.addAll(rule.getAllActivationsAsList());
273 } 289 }
274 return result; 290 return result;
275 } 291 }
@@ -279,10 +295,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
279 return !isNewState; 295 return !isNewState;
280 } 296 }
281 297
282 public Fitness getLastFitness() {
283 return lastFitness;
284 }
285
286 public ObjectiveComparatorHelper getObjectiveComparatorHelper() { 298 public ObjectiveComparatorHelper getObjectiveComparatorHelper() {
287 if (objectiveComparatorHelper == null) { 299 if (objectiveComparatorHelper == null) {
288 objectiveComparatorHelper = new ObjectiveComparatorHelper(objectives); 300 objectiveComparatorHelper = new ObjectiveComparatorHelper(objectives);
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java
index 09925ae7..fea39886 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java
@@ -5,27 +5,26 @@
5 */ 5 */
6package tools.refinery.store.dse.internal; 6package tools.refinery.store.dse.internal;
7 7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.query.dnf.RelationalQuery;
12import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter; 8import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
13import tools.refinery.store.dse.Strategy; 9import tools.refinery.store.dse.Strategy;
14import tools.refinery.store.dse.objectives.Objective; 10import tools.refinery.store.dse.objectives.Objective;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.model.ModelStore;
13import tools.refinery.store.query.dnf.RelationalQuery;
15 14
16import java.util.LinkedHashSet;
17import java.util.List; 15import java.util.List;
16import java.util.Set;
18 17
19public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter { 18public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter {
20 private final ModelStore store; 19 private final ModelStore store;
21 private final LinkedHashSet<TransformationRule> transformationSpecifications; 20 private final Set<TransformationRule> transformationSpecifications;
22 private final LinkedHashSet<RelationalQuery> globalConstraints; 21 private final Set<RelationalQuery> globalConstraints;
23 private final List<Objective> objectives; 22 private final List<Objective> objectives;
24 private final Strategy strategy; 23 private final Strategy strategy;
25 24
26 public DesignSpaceExplorationStoreAdapterImpl(ModelStore store, 25 public DesignSpaceExplorationStoreAdapterImpl(ModelStore store,
27 LinkedHashSet<TransformationRule> transformationSpecifications, 26 Set<TransformationRule> transformationSpecifications,
28 LinkedHashSet<RelationalQuery> globalConstraints, 27 Set<RelationalQuery> globalConstraints,
29 List<Objective> objectives, Strategy strategy) { 28 List<Objective> objectives, Strategy strategy) {
30 this.store = store; 29 this.store = store;
31 this.transformationSpecifications = transformationSpecifications; 30 this.transformationSpecifications = transformationSpecifications;
@@ -40,22 +39,26 @@ public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplor
40 } 39 }
41 40
42 @Override 41 @Override
43 public ModelAdapter createModelAdapter(Model model) { 42 public DesignSpaceExplorationAdapterImpl createModelAdapter(Model model) {
44 return new DesignSpaceExplorationAdapterImpl(model, this); 43 return new DesignSpaceExplorationAdapterImpl(model, this);
45 } 44 }
46 45
47 public LinkedHashSet<TransformationRule> getTransformationSpecifications() { 46 @Override
47 public Set<TransformationRule> getTransformationSpecifications() {
48 return transformationSpecifications; 48 return transformationSpecifications;
49 } 49 }
50 50
51 public LinkedHashSet<RelationalQuery> getGlobalConstraints() { 51 @Override
52 public Set<RelationalQuery> getGlobalConstraints() {
52 return globalConstraints; 53 return globalConstraints;
53 } 54 }
54 55
56 @Override
55 public List<Objective> getObjectives() { 57 public List<Objective> getObjectives() {
56 return objectives; 58 return objectives;
57 } 59 }
58 60
61 @Override
59 public Strategy getStrategy() { 62 public Strategy getStrategy() {
60 return strategy; 63 return strategy;
61 } 64 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
index 015d4815..8123c0d6 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
@@ -14,8 +14,7 @@ import tools.refinery.store.query.resultset.OrderedResultSet;
14import tools.refinery.store.query.resultset.ResultSet; 14import tools.refinery.store.query.resultset.ResultSet;
15import tools.refinery.store.tuple.Tuple; 15import tools.refinery.store.tuple.Tuple;
16 16
17import java.util.LinkedHashSet; 17import java.util.*;
18import java.util.Random;
19 18
20public class TransformationRule { 19public class TransformationRule {
21 20
@@ -66,11 +65,11 @@ public class TransformationRule {
66 return precondition; 65 return precondition;
67 } 66 }
68 67
69 public ResultSet<Boolean> getAllActivationsAsSets() { 68 public ResultSet<Boolean> getAllActivationsAsResultSet() {
70 return activations; 69 return activations;
71 } 70 }
72 71
73 public LinkedHashSet<Activation> getAllActivations() { 72 public Set<Activation> getAllActivations() {
74 var result = new LinkedHashSet<Activation>(); 73 var result = new LinkedHashSet<Activation>();
75 var cursor = activations.getAll(); 74 var cursor = activations.getAll();
76 while (cursor.move()) { 75 while (cursor.move()) {
@@ -79,6 +78,15 @@ public class TransformationRule {
79 return result; 78 return result;
80 } 79 }
81 80
81 public List<Activation> getAllActivationsAsList() {
82 var result = new ArrayList<Activation>();
83 var cursor = activations.getAll();
84 while (cursor.move()) {
85 result.add(new Activation(this, cursor.getKey()));
86 }
87 return result;
88 }
89
82 public Activation getRandomActivation() { 90 public Activation getRandomActivation() {
83 return new Activation(this, activations.getKey(random.nextInt(activations.size()))); 91 return new Activation(this, activations.getKey(random.nextInt(activations.size())));
84 } 92 }
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 8648864c..57f86401 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
@@ -26,6 +26,7 @@ public class BestFirstStrategy implements Strategy {
26 private DesignSpaceExplorationAdapter dseAdapter; 26 private DesignSpaceExplorationAdapter dseAdapter;
27 27
28 private int maxDepth; 28 private int maxDepth;
29 private int maxSolutions;
29 private boolean backTrackIfSolution = true; 30 private boolean backTrackIfSolution = true;
30 private boolean onlyBetterFirst = false; 31 private boolean onlyBetterFirst = false;
31 32
@@ -54,11 +55,20 @@ public class BestFirstStrategy implements Strategy {
54 } 55 }
55 56
56 public BestFirstStrategy(int maxDepth) { 57 public BestFirstStrategy(int maxDepth) {
58 this(maxDepth, -1);
59 }
60
61 public BestFirstStrategy(int maxDepth, int maxSolutions) {
57 if (maxDepth < 0) { 62 if (maxDepth < 0) {
58 this.maxDepth = Integer.MAX_VALUE; 63 this.maxDepth = Integer.MAX_VALUE;
59 } else { 64 } else {
60 this.maxDepth = maxDepth; 65 this.maxDepth = maxDepth;
61 } 66 }
67 if (maxSolutions < 0) {
68 this.maxSolutions = Integer.MAX_VALUE;
69 } else {
70 this.maxSolutions = maxSolutions;
71 }
62 } 72 }
63 73
64 public BestFirstStrategy continueIfHardObjectivesFulfilled() { 74 public BestFirstStrategy continueIfHardObjectivesFulfilled() {
@@ -76,12 +86,15 @@ public class BestFirstStrategy implements Strategy {
76 this.dseAdapter = designSpaceExplorationAdapter; 86 this.dseAdapter = designSpaceExplorationAdapter;
77 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); 87 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
78 88
79 trajectoriesToExplore = new PriorityQueue<TrajectoryWithFitness>(11, 89 trajectoriesToExplore = new PriorityQueue<>(11,
80 (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness)); 90 (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness));
81 } 91 }
82 92
83 @Override 93 @Override
84 public void explore() { 94 public void explore() {
95 if (maxSolutions == 0) {
96 return;
97 }
85 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); 98 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
86 99
87 boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); 100 boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
@@ -90,7 +103,7 @@ public class BestFirstStrategy implements Strategy {
90 return; 103 return;
91 } 104 }
92 105
93 final Fitness firstFitness = dseAdapter.calculateFitness(); 106 final Fitness firstFitness = dseAdapter.getFitness();
94 if (firstFitness.isSatisfiesHardObjectives()) { 107 if (firstFitness.isSatisfiesHardObjectives()) {
95 dseAdapter.newSolution(); 108 dseAdapter.newSolution();
96 // "First state is a solution. Terminate."); 109 // "First state is a solution. Terminate.");
@@ -103,9 +116,16 @@ public class BestFirstStrategy implements Strategy {
103 return; 116 return;
104 } 117 }
105 118
106 final List<Version> firstTrajectory = dseAdapter.getTrajectory(); 119// final List<Version> firstTrajectory = dseAdapter.getTrajectory();
107 TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness); 120
108 trajectoriesToExplore.add(currentTrajectoryWithFitness); 121// TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(),
122// firstFitness);
123// trajectoriesToExplore.add(currentTrajectoryWithFitness);
124
125
126 var firstTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), firstFitness);
127 trajectoriesToExplore.add(firstTrajectoryWithFitness);
128 TrajectoryWithFitness currentTrajectoryWithFitness = null;
109 129
110 mainLoop: while (true) { 130 mainLoop: while (true) {
111 131
@@ -145,9 +165,13 @@ public class BestFirstStrategy implements Strategy {
145 // "Global constraint is not satisfied."); 165 // "Global constraint is not satisfied.");
146 dseAdapter.backtrack(); 166 dseAdapter.backtrack();
147 } else { 167 } else {
148 final Fitness nextFitness = dseAdapter.calculateFitness(); 168 final Fitness nextFitness = dseAdapter.getFitness();
149 if (nextFitness.isSatisfiesHardObjectives()) { 169 if (nextFitness.isSatisfiesHardObjectives()) {
150 dseAdapter.newSolution(); 170 dseAdapter.newSolution();
171 var solutions = dseAdapter.getSolutions().size();
172 if (solutions >= maxSolutions) {
173 return;
174 }
151 // "Found a solution."); 175 // "Found a solution.");
152 if (backTrackIfSolution) { 176 if (backTrackIfSolution) {
153 dseAdapter.backtrack(); 177 dseAdapter.backtrack();
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 1405789b..f4a0747a 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
@@ -21,6 +21,7 @@ public class DepthFirstStrategy implements Strategy {
21 private DesignSpaceExplorationAdapter dseAdapter; 21 private DesignSpaceExplorationAdapter dseAdapter;
22 22
23 private int maxDepth; 23 private int maxDepth;
24 private int maxSolutions;
24 private boolean backTrackIfSolution = true; 25 private boolean backTrackIfSolution = true;
25 26
26 public DepthFirstStrategy() { 27 public DepthFirstStrategy() {
@@ -28,11 +29,20 @@ public class DepthFirstStrategy implements Strategy {
28 } 29 }
29 30
30 public DepthFirstStrategy(int maxDepth) { 31 public DepthFirstStrategy(int maxDepth) {
32 this(maxDepth, -1);
33 }
34
35 public DepthFirstStrategy(int maxDepth, int maxSolutions) {
31 if (maxDepth < 0) { 36 if (maxDepth < 0) {
32 this.maxDepth = Integer.MAX_VALUE; 37 this.maxDepth = Integer.MAX_VALUE;
33 } else { 38 } else {
34 this.maxDepth = maxDepth; 39 this.maxDepth = maxDepth;
35 } 40 }
41 if (maxSolutions < 0) {
42 this.maxSolutions = Integer.MAX_VALUE;
43 } else {
44 this.maxSolutions = maxSolutions;
45 }
36 } 46 }
37 47
38 public DepthFirstStrategy continueIfHardObjectivesFulfilled() { 48 public DepthFirstStrategy continueIfHardObjectivesFulfilled() {
@@ -47,6 +57,9 @@ public class DepthFirstStrategy implements Strategy {
47 57
48 @Override 58 @Override
49 public void explore() { 59 public void explore() {
60 if (maxSolutions == 0) {
61 return;
62 }
50 mainloop: while (true) { 63 mainloop: while (true) {
51 var globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); 64 var globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
52 if (!globalConstraintsAreSatisfied) { 65 if (!globalConstraintsAreSatisfied) {
@@ -61,9 +74,13 @@ public class DepthFirstStrategy implements Strategy {
61 } 74 }
62 } 75 }
63 76
64 Fitness fitness = dseAdapter.calculateFitness(); 77 Fitness fitness = dseAdapter.getFitness();
65 if (fitness.isSatisfiesHardObjectives()) { 78 if (fitness.isSatisfiesHardObjectives()) {
66 dseAdapter.newSolution(); 79 dseAdapter.newSolution();
80 var solutions = dseAdapter.getSolutions().size();
81 if (solutions >= maxSolutions) {
82 return;
83 }
67 if (backTrackIfSolution) { 84 if (backTrackIfSolution) {
68 var isSuccessfulUndo = dseAdapter.backtrack(); 85 var isSuccessfulUndo = dseAdapter.backtrack();
69 if (!isSuccessfulUndo) { 86 if (!isSuccessfulUndo) {
@@ -76,7 +93,6 @@ public class DepthFirstStrategy implements Strategy {
76 } 93 }
77 } 94 }
78 95
79 var depth = dseAdapter.getDepth();
80 if (dseAdapter.getDepth() >= maxDepth) { 96 if (dseAdapter.getDepth() >= maxDepth) {
81 var isSuccessfulUndo = dseAdapter.backtrack(); 97 var isSuccessfulUndo = dseAdapter.backtrack();
82 if (!isSuccessfulUndo) { 98 if (!isSuccessfulUndo) {
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 312bcebd..f57f68ef 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
@@ -137,8 +137,8 @@ public class TransformationRuleTest {
137 137
138 queryEngine.flushChanges(); 138 queryEngine.flushChanges();
139 139
140 var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsSets(); 140 var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsResultSet();
141 var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsSets(); 141 var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsResultSet();
142 142
143 assertResults(Map.of( 143 assertResults(Map.of(
144 Tuple.of(newClass1Id, newFieldId), true, 144 Tuple.of(newClass1Id, newFieldId), true,
@@ -236,12 +236,12 @@ public class TransformationRuleTest {
236 assertResults(Map.of( 236 assertResults(Map.of(
237 Tuple.of(newModelId, newClass1Id), true, 237 Tuple.of(newModelId, newClass1Id), true,
238 Tuple.of(newModelId, newClass2Id), true 238 Tuple.of(newModelId, newClass2Id), true
239 ), deleteEmptyClassRule0.getAllActivationsAsSets()); 239 ), deleteEmptyClassRule0.getAllActivationsAsResultSet());
240 240
241 assertResults(Map.of( 241 assertResults(Map.of(
242 Tuple.of(newModelId, newClass1Id), true, 242 Tuple.of(newModelId, newClass1Id), true,
243 Tuple.of(newModelId, newClass2Id), true 243 Tuple.of(newModelId, newClass2Id), true
244 ), deleteEmptyClassRule1.getAllActivationsAsSets()); 244 ), deleteEmptyClassRule1.getAllActivationsAsResultSet());
245 245
246 assertEquals(Tuple.of(newModelId, newClass2Id), activation0); 246 assertEquals(Tuple.of(newModelId, newClass2Id), activation0);
247 assertEquals(Tuple.of(newModelId, newClass1Id), activation1); 247 assertEquals(Tuple.of(newModelId, newClass1Id), activation1);
@@ -312,7 +312,7 @@ public class TransformationRuleTest {
312 assertResults(Map.of( 312 assertResults(Map.of(
313 Tuple.of(newModelId, newClass1Id), true, 313 Tuple.of(newModelId, newClass1Id), true,
314 Tuple.of(newModelId, newClass2Id), true 314 Tuple.of(newModelId, newClass2Id), true
315 ), deleteEmptyClassRule.getAllActivationsAsSets()); 315 ), deleteEmptyClassRule.getAllActivationsAsResultSet());
316 316
317 317
318 deleteEmptyClassRule.fireActivation(Tuple.of(0, 1)); 318 deleteEmptyClassRule.fireActivation(Tuple.of(0, 1));
@@ -320,7 +320,7 @@ public class TransformationRuleTest {
320 assertResults(Map.of( 320 assertResults(Map.of(
321 Tuple.of(newModelId, newClass1Id), false, 321 Tuple.of(newModelId, newClass1Id), false,
322 Tuple.of(newModelId, newClass2Id), true 322 Tuple.of(newModelId, newClass2Id), true
323 ), deleteEmptyClassRule.getAllActivationsAsSets()); 323 ), deleteEmptyClassRule.getAllActivationsAsResultSet());
324 } 324 }
325 325
326 @Test 326 @Test
@@ -388,21 +388,21 @@ public class TransformationRuleTest {
388 assertResults(Map.of( 388 assertResults(Map.of(
389 Tuple.of(newModelId, newClass1Id), true, 389 Tuple.of(newModelId, newClass1Id), true,
390 Tuple.of(newModelId, newClass2Id), true 390 Tuple.of(newModelId, newClass2Id), true
391 ), deleteEmptyClassRule.getAllActivationsAsSets()); 391 ), deleteEmptyClassRule.getAllActivationsAsResultSet());
392 392
393 deleteEmptyClassRule.fireRandomActivation(); 393 deleteEmptyClassRule.fireRandomActivation();
394 394
395 assertResults(Map.of( 395 assertResults(Map.of(
396 Tuple.of(newModelId, newClass1Id), true, 396 Tuple.of(newModelId, newClass1Id), true,
397 Tuple.of(newModelId, newClass2Id), false 397 Tuple.of(newModelId, newClass2Id), false
398 ), deleteEmptyClassRule.getAllActivationsAsSets()); 398 ), deleteEmptyClassRule.getAllActivationsAsResultSet());
399 399
400 deleteEmptyClassRule.fireRandomActivation(); 400 deleteEmptyClassRule.fireRandomActivation();
401 401
402 assertResults(Map.of( 402 assertResults(Map.of(
403 Tuple.of(newModelId, newClass1Id), false, 403 Tuple.of(newModelId, newClass1Id), false,
404 Tuple.of(newModelId, newClass2Id), false 404 Tuple.of(newModelId, newClass2Id), false
405 ), deleteEmptyClassRule.getAllActivationsAsSets()); 405 ), deleteEmptyClassRule.getAllActivationsAsResultSet());
406 406
407 } 407 }
408} 408}