aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/main/java/tools
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/main/java/tools
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/main/java/tools')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java9
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java61
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java43
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java6
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java8
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java9
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java283
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java62
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java57
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java84
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java51
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java131
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java25
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java21
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java100
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java58
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java190
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java108
18 files changed, 1306 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java
new file mode 100644
index 00000000..2af22963
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java
@@ -0,0 +1,9 @@
1package tools.refinery.store.dse;
2
3import org.eclipse.collections.api.block.procedure.Procedure;
4import tools.refinery.store.model.Model;
5import tools.refinery.store.tuple.Tuple;
6
7public interface ActionFactory {
8 Procedure<Tuple> prepare(Model model);
9}
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
new file mode 100644
index 00000000..729a6fc9
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
@@ -0,0 +1,61 @@
1package tools.refinery.store.dse;
2
3import tools.refinery.store.adapter.ModelAdapter;
4import tools.refinery.store.map.Version;
5import tools.refinery.store.dse.internal.Activation;
6import tools.refinery.store.dse.internal.DesignSpaceExplorationBuilderImpl;
7import tools.refinery.store.dse.objectives.Fitness;
8import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
9import tools.refinery.store.tuple.Tuple;
10import tools.refinery.store.tuple.Tuple1;
11
12import java.util.Collection;
13import java.util.List;
14import java.util.Random;
15
16public interface DesignSpaceExplorationAdapter extends ModelAdapter {
17 @Override
18 DesignSpaceExplorationStoreAdapter getStoreAdapter();
19
20 static DesignSpaceExplorationBuilder builder() {
21 return new DesignSpaceExplorationBuilderImpl();
22 }
23
24 Collection<Version> explore();
25
26 public int getModelSize();
27
28 public Tuple1 createObject();
29
30 public Tuple deleteObject(Tuple tuple);
31
32 public boolean checkGlobalConstraints();
33
34 public boolean backtrack();
35
36 public Fitness calculateFitness();
37
38 public void newSolution();
39
40 public int getDepth();
41
42 public Collection<Activation> getUntraversedActivations();
43
44 public boolean fireActivation(Activation activation);
45
46 public void fireRandomActivation();
47
48 public boolean isCurrentInTrajectory();
49
50 public List<Version> getTrajectory();
51
52 public boolean isCurrentStateAlreadyTraversed();
53
54 public ObjectiveComparatorHelper getObjectiveComparatorHelper();
55
56 public void restoreTrajectory(List<Version> trajectory);
57
58 public void setRandom(Random random);
59
60 public void setRandom(long seed);
61}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java
new file mode 100644
index 00000000..8ca0037d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java
@@ -0,0 +1,43 @@
1package tools.refinery.store.dse;
2
3import tools.refinery.store.adapter.ModelAdapterBuilder;
4import tools.refinery.store.query.dnf.RelationalQuery;
5import tools.refinery.store.dse.internal.TransformationRule;
6import tools.refinery.store.dse.objectives.Objective;
7
8import java.util.Collection;
9import java.util.List;
10
11public interface DesignSpaceExplorationBuilder extends ModelAdapterBuilder {
12 default DesignSpaceExplorationBuilder transformations(TransformationRule... transformationRules) {
13 return transformations(List.of(transformationRules));
14 }
15
16 default DesignSpaceExplorationBuilder transformations(Collection<? extends TransformationRule> transformationRules) {
17 transformationRules.forEach(this::transformation);
18 return this;
19 }
20
21 default DesignSpaceExplorationBuilder globalConstraints(RelationalQuery... globalConstraints) {
22 return globalConstraints(List.of(globalConstraints));
23 }
24
25 default DesignSpaceExplorationBuilder globalConstraints(Collection<RelationalQuery> globalConstraints) {
26 globalConstraints.forEach(this::globalConstraint);
27 return this;
28 }
29
30 default DesignSpaceExplorationBuilder objectives(Objective... objectives) {
31 return objectives(List.of(objectives));
32 }
33
34 default DesignSpaceExplorationBuilder objectives(Collection<? extends Objective> objectives) {
35 objectives.forEach(this::objective);
36 return this;
37 }
38
39 DesignSpaceExplorationBuilder transformation(TransformationRule transformationRule);
40 DesignSpaceExplorationBuilder globalConstraint(RelationalQuery globalConstraint);
41 DesignSpaceExplorationBuilder objective(Objective objective);
42 DesignSpaceExplorationBuilder strategy(Strategy strategy);
43}
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
new file mode 100644
index 00000000..5964cd82
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java
@@ -0,0 +1,6 @@
1package tools.refinery.store.dse;
2
3import tools.refinery.store.adapter.ModelStoreAdapter;
4
5public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter {
6}
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
new file mode 100644
index 00000000..cef43386
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java
@@ -0,0 +1,8 @@
1package tools.refinery.store.dse;
2
3public interface Strategy {
4
5 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter);
6
7 public void explore();
8}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java
new file mode 100644
index 00000000..f1de00e6
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java
@@ -0,0 +1,9 @@
1package tools.refinery.store.dse.internal;
2
3import tools.refinery.store.tuple.Tuple;
4
5public record Activation(TransformationRule transformationRule, Tuple activation) {
6 public boolean fire() {
7 return transformationRule.fireActivation(activation);
8 }
9}
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
new file mode 100644
index 00000000..5fb54da9
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
@@ -0,0 +1,283 @@
1package tools.refinery.store.dse.internal;
2
3import tools.refinery.store.map.Version;
4import tools.refinery.store.model.Interpretation;
5import tools.refinery.store.model.Model;
6import tools.refinery.store.query.ModelQueryAdapter;
7import tools.refinery.store.query.dnf.RelationalQuery;
8import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
9import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
10import tools.refinery.store.dse.Strategy;
11import tools.refinery.store.dse.objectives.Fitness;
12import tools.refinery.store.dse.objectives.Objective;
13import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
14import tools.refinery.store.query.resultset.ResultSet;
15import tools.refinery.store.representation.Symbol;
16import tools.refinery.store.tuple.Tuple;
17import tools.refinery.store.tuple.Tuple1;
18import tools.refinery.visualization.ModelVisualizerAdapter;
19
20import java.util.*;
21
22public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExplorationAdapter {
23 static final Symbol<Integer> NODE_COUNT_SYMBOL = Symbol.of("MODEL_SIZE", 0, Integer.class, 0);
24 private final Model model;
25 private final ModelQueryAdapter queryEngine;
26 private final DesignSpaceExplorationStoreAdapterImpl storeAdapter;
27 private final LinkedHashSet<TransformationRule> transformationRules;
28 private final LinkedHashSet<RelationalQuery> globalConstraints;
29 private final List<Objective> objectives;
30 private final LinkedHashSet<ResultSet<Boolean>> globalConstraintResultSets = new LinkedHashSet<>();
31 private final Interpretation<Integer> sizeInterpretation;
32 private final Strategy strategy;
33
34 private ObjectiveComparatorHelper objectiveComparatorHelper;
35 private List<Version> trajectory = new LinkedList<>();
36 private Fitness lastFitness;
37 private final LinkedHashSet<Version> solutions = new LinkedHashSet<>();
38 private Map<Version, LinkedHashSet<Activation>> statesAndUntraversedActivations;
39 private Map<Version, LinkedHashSet<Activation>> statesAndTraversedActivations;
40 private Random random = new Random();
41 private boolean isNewState = false;
42 private final boolean isVisualizationEnabled;
43 private final ModelVisualizerAdapter modelVisualizerAdapter;
44
45 public List<Version> getTrajectory() {
46 return new LinkedList<>(trajectory);
47 }
48
49 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) {
50 this.model = model;
51 this.storeAdapter = storeAdapter;
52 this.sizeInterpretation = model.getInterpretation(NODE_COUNT_SYMBOL);
53 queryEngine = model.getAdapter(ModelQueryAdapter.class);
54
55 globalConstraints = storeAdapter.getGlobalConstraints();
56 for (var constraint : globalConstraints) {
57 globalConstraintResultSets.add(queryEngine.getResultSet(constraint));
58 }
59
60 transformationRules = storeAdapter.getTransformationSpecifications();
61 for (var rule : transformationRules) {
62 rule.prepare(model, queryEngine);
63 }
64
65 objectives = storeAdapter.getObjectives();
66 statesAndUntraversedActivations = new HashMap<>();
67 statesAndTraversedActivations = new HashMap<>();
68 strategy = storeAdapter.getStrategy();
69 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null);
70 isVisualizationEnabled = modelVisualizerAdapter != null;
71
72 }
73
74 @Override
75 public Model getModel() {
76 return model;
77 }
78
79 @Override
80 public DesignSpaceExplorationStoreAdapter getStoreAdapter() {
81 return storeAdapter;
82 }
83
84 @Override
85 public LinkedHashSet<Version> explore() {
86 var state = model.commit();
87 trajectory.add(state);
88 statesAndUntraversedActivations.put(state, getAllActivations());
89 statesAndTraversedActivations.put(state, new LinkedHashSet<>());
90 strategy.initStrategy(this);
91 strategy.explore();
92 return solutions;
93 }
94
95 @Override
96 public int getModelSize() {
97 return sizeInterpretation.get(Tuple.of());
98 }
99
100 @Override
101 public Tuple1 createObject() {
102 var newNodeId = getModelSize();
103 sizeInterpretation.put(Tuple.of(), newNodeId + 1);
104 return Tuple.of(newNodeId);
105 }
106
107 @Override
108 public Tuple deleteObject(Tuple tuple) {
109 if (tuple.getSize() != 1) {
110 throw new IllegalArgumentException("Tuple size must be 1");
111 }
112// TODO: implement more efficient deletion
113// if (tuple.get(0) == getModelSize() - 1) {
114// sizeInterpretation.put(Tuple.of(), getModelSize() - 1);
115// }
116 return tuple;
117 }
118
119 @Override
120 public boolean checkGlobalConstraints() {
121 for (var resultSet : globalConstraintResultSets) {
122 if (resultSet.size() > 0) {
123 return false;
124 }
125 }
126 return true;
127 }
128
129 @Override
130 public boolean backtrack() {
131 if (trajectory.size() < 2) {
132 return false;
133 }
134 if (isVisualizationEnabled) {
135 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 1),
136 trajectory.get(trajectory.size() - 2), "backtrack");
137 }
138 model.restore(trajectory.get(trajectory.size() - 2));
139 trajectory.remove(trajectory.size() - 1);
140 return true;
141 }
142
143 @Override
144 public void restoreTrajectory(List<Version> trajectory) {
145 model.restore(trajectory.get(trajectory.size() - 1));
146// if (isVisualizationEnabled) {
147// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1),
148// trajectory.get(trajectory.size() - 1), "restore");
149// }
150 this.trajectory = trajectory;
151
152 }
153
154 @Override
155 public void setRandom(Random random) {
156 this.random = random;
157 }
158
159 @Override
160 public void setRandom(long seed) {
161 this.random = new Random(seed);
162 }
163
164 @Override
165 public Fitness calculateFitness() {
166 Fitness result = new Fitness();
167 boolean satisfiesHardObjectives = true;
168 for (Objective objective : objectives) {
169 var fitness = objective.getFitness(this);
170 result.put(objective.getName(), fitness);
171 if (objective.isHardObjective() && !objective.satisfiesHardObjective(fitness)) {
172 satisfiesHardObjectives = false;
173 }
174 }
175 result.setSatisfiesHardObjectives(satisfiesHardObjectives);
176
177 lastFitness = result;
178
179 return result;
180 }
181
182 @Override
183 public void newSolution() {
184 var state = model.getState();
185 solutions.add(state);
186 if (isVisualizationEnabled) {
187 modelVisualizerAdapter.addSolution(state);
188 }
189 }
190
191 @Override
192 public int getDepth() {
193 return trajectory.size() - 1;
194 }
195
196 public LinkedHashSet<Activation> getUntraversedActivations() {
197// return statesAndUntraversedActivations.get(model.getState());
198 LinkedHashSet<Activation> untraversedActivations = new LinkedHashSet<>();
199 for (Activation activation : getAllActivations()) {
200 if (!statesAndTraversedActivations.get(model.getState()).contains(activation)) {
201 untraversedActivations.add(activation);
202 }
203 }
204
205 return untraversedActivations;
206 }
207
208 @Override
209 public boolean fireActivation(Activation activation) {
210 if (activation == null) {
211 return false;
212 }
213 var previousState = model.getState();
214 if (!statesAndUntraversedActivations.get(previousState).contains(activation)) {
215// TODO: throw exception?
216 return false;
217 }
218 if (!activation.fire()) {
219 return false;
220 }
221 statesAndUntraversedActivations.get(previousState).remove(activation);
222 statesAndTraversedActivations.get(previousState).add(activation);
223 var newState = model.commit();
224 trajectory.add(newState);
225 isNewState = !statesAndUntraversedActivations.containsKey(newState);
226 statesAndUntraversedActivations.put(newState, getAllActivations());
227 statesAndTraversedActivations.put(newState, new LinkedHashSet<>());
228 if (isVisualizationEnabled) {
229 if (isNewState) {
230 modelVisualizerAdapter.addState(newState);
231 }
232 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 2),
233 trajectory.get(trajectory.size() - 1), activation.transformationRule().getName(),
234 activation.activation());
235 }
236 return true;
237 }
238
239 @Override
240 public void fireRandomActivation() {
241 var activations = getUntraversedActivations();
242 if (activations.isEmpty()) {
243// TODO: throw exception
244 return;
245 }
246 int index = random.nextInt(activations.size());
247 var iterator = activations.iterator();
248 while (index-- > 0) {
249 iterator.next();
250 }
251 var activationId = iterator.next();
252 fireActivation(activationId);
253 }
254
255 @Override
256 public boolean isCurrentInTrajectory() {
257 return trajectory.contains(model.getState());
258 }
259
260 public LinkedHashSet<Activation> getAllActivations() {
261 LinkedHashSet<Activation> result = new LinkedHashSet<>();
262 for (var rule : transformationRules) {
263 result.addAll(rule.getAllActivations());
264 }
265 return result;
266 }
267
268 public boolean isCurrentStateAlreadyTraversed() {
269// TODO: check isomorphism?
270 return !isNewState;
271 }
272
273 public Fitness getLastFitness() {
274 return lastFitness;
275 }
276
277 public ObjectiveComparatorHelper getObjectiveComparatorHelper() {
278 if (objectiveComparatorHelper == null) {
279 objectiveComparatorHelper = new ObjectiveComparatorHelper(objectives);
280 }
281 return objectiveComparatorHelper;
282 }
283}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java
new file mode 100644
index 00000000..03508adc
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java
@@ -0,0 +1,62 @@
1package tools.refinery.store.dse.internal;
2
3import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
4import tools.refinery.store.model.ModelStore;
5import tools.refinery.store.model.ModelStoreBuilder;
6import tools.refinery.store.query.dnf.RelationalQuery;
7import tools.refinery.store.dse.DesignSpaceExplorationBuilder;
8import tools.refinery.store.dse.Strategy;
9import tools.refinery.store.dse.objectives.Objective;
10
11import java.util.LinkedHashSet;
12import java.util.LinkedList;
13import java.util.List;
14
15public class DesignSpaceExplorationBuilderImpl
16 extends AbstractModelAdapterBuilder<DesignSpaceExplorationStoreAdapterImpl>
17 implements DesignSpaceExplorationBuilder {
18 private final LinkedHashSet<TransformationRule> transformationSpecifications = new LinkedHashSet<>();
19 private final LinkedHashSet<RelationalQuery> globalConstraints = new LinkedHashSet<>();
20 private final List<Objective> objectives = new LinkedList<>();
21 private Strategy strategy;
22
23 @Override
24 protected DesignSpaceExplorationStoreAdapterImpl doBuild(ModelStore store) {
25 return new DesignSpaceExplorationStoreAdapterImpl(store, transformationSpecifications, globalConstraints,
26 objectives, strategy);
27 }
28
29 @Override
30 public DesignSpaceExplorationBuilder transformation(TransformationRule transformationRule) {
31 checkNotConfigured();
32 transformationSpecifications.add(transformationRule);
33 return this;
34 }
35
36 @Override
37 public DesignSpaceExplorationBuilder globalConstraint(RelationalQuery globalConstraint) {
38 checkNotConfigured();
39 globalConstraints.add(globalConstraint);
40 return this;
41 }
42
43 @Override
44 public DesignSpaceExplorationBuilder objective(Objective objective) {
45 checkNotConfigured();
46 objectives.add(objective);
47 return this;
48 }
49
50 @Override
51 public DesignSpaceExplorationBuilder strategy(Strategy strategy) {
52 checkNotConfigured();
53 this.strategy = strategy;
54 return this;
55 }
56
57 @Override
58 protected void doConfigure(ModelStoreBuilder storeBuilder) {
59 storeBuilder.symbols(DesignSpaceExplorationAdapterImpl.NODE_COUNT_SYMBOL);
60 super.doConfigure(storeBuilder);
61 }
62}
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
new file mode 100644
index 00000000..b06462ce
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java
@@ -0,0 +1,57 @@
1package tools.refinery.store.dse.internal;
2
3import tools.refinery.store.adapter.ModelAdapter;
4import tools.refinery.store.model.Model;
5import tools.refinery.store.model.ModelStore;
6import tools.refinery.store.query.dnf.RelationalQuery;
7import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
8import tools.refinery.store.dse.Strategy;
9import tools.refinery.store.dse.objectives.Objective;
10
11import java.util.LinkedHashSet;
12import java.util.List;
13
14public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter {
15 private final ModelStore store;
16 private final LinkedHashSet<TransformationRule> transformationSpecifications;
17 private final LinkedHashSet<RelationalQuery> globalConstraints;
18 private final List<Objective> objectives;
19 private final Strategy strategy;
20
21 public DesignSpaceExplorationStoreAdapterImpl(ModelStore store,
22 LinkedHashSet<TransformationRule> transformationSpecifications,
23 LinkedHashSet<RelationalQuery> globalConstraints,
24 List<Objective> objectives, Strategy strategy) {
25 this.store = store;
26 this.transformationSpecifications = transformationSpecifications;
27 this.globalConstraints = globalConstraints;
28 this.objectives = objectives;
29 this.strategy = strategy;
30 }
31
32 @Override
33 public ModelStore getStore() {
34 return store;
35 }
36
37 @Override
38 public ModelAdapter createModelAdapter(Model model) {
39 return new DesignSpaceExplorationAdapterImpl(model, this);
40 }
41
42 public LinkedHashSet<TransformationRule> getTransformationSpecifications() {
43 return transformationSpecifications;
44 }
45
46 public LinkedHashSet<RelationalQuery> getGlobalConstraints() {
47 return globalConstraints;
48 }
49
50 public List<Objective> getObjectives() {
51 return objectives;
52 }
53
54 public Strategy getStrategy() {
55 return strategy;
56 }
57}
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
new file mode 100644
index 00000000..ed2e77f1
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
@@ -0,0 +1,84 @@
1package tools.refinery.store.dse.internal;
2
3import org.eclipse.collections.api.block.procedure.Procedure;
4import tools.refinery.store.model.Model;
5import tools.refinery.store.query.ModelQueryAdapter;
6import tools.refinery.store.query.dnf.RelationalQuery;
7import tools.refinery.store.dse.ActionFactory;
8import tools.refinery.store.query.resultset.OrderedResultSet;
9import tools.refinery.store.query.resultset.ResultSet;
10import tools.refinery.store.tuple.Tuple;
11
12import java.util.LinkedHashSet;
13import java.util.Random;
14
15public class TransformationRule {
16
17 private final String name;
18 private final RelationalQuery precondition;
19 private final ActionFactory actionFactory;
20 private Procedure<Tuple> action;
21 private OrderedResultSet<Boolean> activations;
22 private Random random;
23 private ModelQueryAdapter queryEngine;
24
25 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) {
26 this(name, precondition, actionFactory, new Random());
27 }
28
29 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) {
30 this(name, precondition, actionFactory, new Random(seed));
31 }
32
33 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, Random random) {
34 this.name = name;
35 this.precondition = precondition;
36 this.actionFactory = actionFactory;
37 this.random = random;
38 }
39 public boolean prepare(Model model, ModelQueryAdapter queryEngine) {
40 action = actionFactory.prepare(model);
41 this.queryEngine = queryEngine;
42 activations = new OrderedResultSet<>(queryEngine.getResultSet(precondition));
43 return true;
44 }
45
46 public boolean fireActivation(Tuple activation) {
47 action.accept(activation);
48 queryEngine.flushChanges();
49 return true;
50 }
51
52 public boolean fireRandomActivation() {
53 return getRandomActivation().fire();
54 }
55
56 public String getName() {
57 return name;
58 }
59
60 public RelationalQuery getPrecondition() {
61 return precondition;
62 }
63
64 public ResultSet<Boolean> getAllActivationsAsSets() {
65 return activations;
66 }
67
68 public LinkedHashSet<Activation> getAllActivations() {
69 var result = new LinkedHashSet<Activation>();
70 var cursor = activations.getAll();
71 while (cursor.move()) {
72 result.add(new Activation(this, cursor.getKey()));
73 }
74 return result;
75 }
76
77 public Activation getRandomActivation() {
78 return new Activation(this, activations.getKey(random.nextInt(activations.size())));
79 }
80
81 public Activation getActivation(int index) {
82 return new Activation(this, activations.getKey(index));
83 }
84}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java
new file mode 100644
index 00000000..82695704
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java
@@ -0,0 +1,51 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.dse.objectives;
10
11import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
12
13/**
14 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution.
15 *
16 * @author Andras Szabolcs Nagy
17 *
18 */
19public class AlwaysSatisfiedDummyHardObjective extends BaseObjective {
20
21 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective";
22
23 public AlwaysSatisfiedDummyHardObjective() {
24 super(DEFAULT_NAME);
25 }
26
27 public AlwaysSatisfiedDummyHardObjective(String name) {
28 super(name);
29 }
30
31 @Override
32 public Double getFitness(DesignSpaceExplorationAdapter context) {
33 return 0d;
34 }
35
36 @Override
37 public boolean isHardObjective() {
38 return true;
39 }
40
41 @Override
42 public boolean satisfiesHardObjective(Double fitness) {
43 return true;
44 }
45
46 @Override
47 public Objective createNew() {
48 return this;
49 }
50
51}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java
new file mode 100644
index 00000000..24e3280d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java
@@ -0,0 +1,131 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.dse.objectives;
10
11import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
12
13import java.util.Comparator;
14import java.util.Objects;
15
16/**
17 * This abstract class implements the basic functionality of an objective ({@link Objective} namely its name,
18 * comparator, level and fitness hard constraint.
19 *
20 * @author Andras Szabolcs Nagy
21 *
22 */
23public abstract class BaseObjective implements Objective {
24
25 protected final String name;
26 protected Comparator<Double> comparator = Comparators.HIGHER_IS_BETTER;
27
28 protected double fitnessConstraint;
29 protected boolean isThereFitnessConstraint = false;
30 protected Comparator<Double> fitnessConstraintComparator;
31
32 public BaseObjective(String name) {
33 Objects.requireNonNull(name, "Name of the objective cannot be null.");
34 this.name = name;
35 }
36
37 @Override
38 public String getName() {
39 return name;
40 }
41
42 @Override
43 public void setComparator(Comparator<Double> comparator) {
44 this.comparator = comparator;
45 }
46
47 @Override
48 public Comparator<Double> getComparator() {
49 return comparator;
50 }
51
52 public BaseObjective withComparator(Comparator<Double> comparator) {
53 setComparator(comparator);
54 return this;
55 }
56
57 /**
58 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
59 * current state as a solution.
60 *
61 * @param fitnessConstraint
62 * Solutions should be better than this value.
63 * @param fitnessConstraintComparator
64 * {@link Comparator} to determine if the current state is better than the given value.
65 * @return The actual instance to enable builder pattern like usage.
66 */
67 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint,
68 Comparator<Double> fitnessConstraintComparator) {
69 this.fitnessConstraint = fitnessConstraint;
70 this.fitnessConstraintComparator = fitnessConstraintComparator;
71 this.isThereFitnessConstraint = true;
72 return this;
73 }
74
75 /**
76 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
77 * current state as a solution. The provided comparator will be used.
78 *
79 * @param fitnessConstraint
80 * Solutions should be better than this value.
81 * @return The actual instance to enable builder pattern like usage.
82 */
83 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint) {
84 return withHardConstraintOnFitness(fitnessConstraint, null);
85 }
86
87 @Override
88 public void init(DesignSpaceExplorationAdapter context) {
89 if (fitnessConstraintComparator == null) {
90 fitnessConstraintComparator = comparator;
91 }
92 }
93
94 @Override
95 public boolean isHardObjective() {
96 return isThereFitnessConstraint;
97 }
98
99 @Override
100 public boolean satisfiesHardObjective(Double fitness) {
101 if (isThereFitnessConstraint) {
102 int compare = fitnessConstraintComparator.compare(fitness, fitnessConstraint);
103 if (compare < 0) {
104 return false;
105 }
106 }
107 return true;
108 }
109
110 @Override
111 public int hashCode() {
112 return name.hashCode();
113 }
114
115 @Override
116 public boolean equals(Object obj) {
117 if (this == obj) {
118 return true;
119 }
120 if (obj instanceof BaseObjective baseObjective) {
121 return name.equals(baseObjective.getName());
122 }
123 return false;
124 }
125
126 @Override
127 public String toString() {
128 return name;
129 }
130
131}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java
new file mode 100644
index 00000000..e64e04e8
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java
@@ -0,0 +1,25 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.dse.objectives;
10
11import java.util.Comparator;
12
13public class Comparators {
14
15 private Comparators() { /*Utility class constructor*/ }
16
17 public static final Comparator<Double> HIGHER_IS_BETTER = (o1, o2) -> o1.compareTo(o2);
18
19 public static final Comparator<Double> LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1);
20
21 private static final Double ZERO = (double) 0;
22
23 public static final Comparator<Double> DIFFERENCE_TO_ZERO_IS_BETTER = (o1, o2) -> ZERO.compareTo(Math.abs(o1)-Math.abs(o2));
24
25}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java
new file mode 100644
index 00000000..16caed85
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java
@@ -0,0 +1,21 @@
1package tools.refinery.store.dse.objectives;
2
3import java.util.HashMap;
4
5public class Fitness extends HashMap<String, Double> {
6
7 private boolean satisfiesHardObjectives;
8
9 public boolean isSatisfiesHardObjectives() {
10 return satisfiesHardObjectives;
11 }
12
13 public void setSatisfiesHardObjectives(boolean satisfiesHardObjectives) {
14 this.satisfiesHardObjectives = satisfiesHardObjectives;
15 }
16
17 @Override
18 public String toString() {
19 return super.toString() + " hardObjectives=" + satisfiesHardObjectives;
20 }
21}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java
new file mode 100644
index 00000000..4e14c9a3
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java
@@ -0,0 +1,100 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.dse.objectives;
10
11import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
12
13import java.util.Comparator;
14
15/**
16 *
17 * Implementation of this interface represents a single objective of the DSE problem, which can assess a solution
18 * (trajectory) in a single number. It has a name and a comparator which orders two solution based on the calculated
19 * value.
20 * <p>
21 * Objectives can be either hard or soft objectives. Hard objectives can be satisfied or unsatisfied. If all of the hard
22 * objectives are satisfied on a single solution, then it is considered to be a valid (or goal) solution.
23 * <p>
24 * Certain objectives can have inner state for calculating the fitness value. In this case a new instance is necessary
25 * for every new thread, and the {@code createNew} method should not return the same instance more than once.
26 *
27 * @author Andras Szabolcs Nagy
28 *
29 */
30public interface Objective {
31
32 /**
33 * Returns the name of the objective.
34 *
35 * @return The name of the objective.
36 */
37 String getName();
38
39 /**
40 * Sets the {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is to
41 * minimize or maximize (or minimize or maximize a delta from a given number).
42 *
43 * @param comparator The comparator.
44 */
45 void setComparator(Comparator<Double> comparator);
46
47 /**
48 * Returns a {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is
49 * to minimize or maximize (or minimize or maximize a delta from a given number).
50 *
51 * @return The comparator.
52 */
53 Comparator<Double> getComparator();
54
55 /**
56 * Calculates the value of the objective on a given solution (trajectory).
57 *
58 * @param context
59 * The {@link DesignSpaceExplorationAdapter}
60 * @return The objective value in double.
61 */
62 Double getFitness(DesignSpaceExplorationAdapter context);
63
64 /**
65 * Initializes the objective. It is called exactly once for every thread starts.
66 *
67 * @param context
68 * The {@link DesignSpaceExplorationAdapter}.
69 */
70 void init(DesignSpaceExplorationAdapter context);
71
72 /**
73 * Returns an instance of the {@link Objective}. If it returns the same instance, all the methods has to be thread
74 * save as they are called concurrently.
75 *
76 * @return An instance of the objective.
77 */
78 Objective createNew();
79
80 /**
81 * Returns true if the objective is a hard objective. In such a case the method
82 * {@link Objective#satisfiesHardObjective(Double)} is called.
83 *
84 * @return True if the objective is a hard objective.
85 * @see Objective#satisfiesHardObjective(Double)
86 * @see Objective
87 */
88 boolean isHardObjective();
89
90 /**
91 * Determines if the given fitness value satisfies the hard objective.
92 *
93 * @param fitness
94 * The fitness value of a solution.
95 * @return True if it satisfies the hard objective or it is a soft constraint.
96 * @see Objective
97 */
98 boolean satisfiesHardObjective(Double fitness);
99
100}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java
new file mode 100644
index 00000000..3184b8c4
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java
@@ -0,0 +1,58 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.dse.objectives;
10
11import java.util.List;
12
13/**
14 * This class is responsible to compare and sort fitness values.
15 *
16 * @author András Szabolcs Nagy
17 */
18public class ObjectiveComparatorHelper {
19
20 private final List<Objective> objectives;
21
22 public ObjectiveComparatorHelper(List<Objective> objectives) {
23 this.objectives = objectives;
24 }
25
26 /**
27 * Compares two fitnesses based on dominance. Returns -1 if the second parameter {@code o2} is a better
28 * solution ({@code o2} dominates {@code o1}), 1 if the first parameter {@code o1} is better ({@code o1} dominates
29 * {@code o2}) and returns 0 if they are non-dominating each other.
30 */
31 public int compare(Fitness o1, Fitness o2) {
32
33 boolean o1HasBetterFitness = false;
34 boolean o2HasBetterFitness = false;
35
36 for (Objective objective : objectives) {
37 String objectiveName = objective.getName();
38 int sgn = objective.getComparator().compare(o1.get(objectiveName), o2.get(objectiveName));
39
40 if (sgn < 0) {
41 o2HasBetterFitness = true;
42 }
43 if (sgn > 0) {
44 o1HasBetterFitness = true;
45 }
46 if (o1HasBetterFitness && o2HasBetterFitness) {
47 break;
48 }
49 }
50 if (o2HasBetterFitness) {
51 } else if (o1HasBetterFitness) {
52 return 1;
53 }
54
55 return 0;
56
57 }
58}
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
new file mode 100644
index 00000000..05cc5bac
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java
@@ -0,0 +1,190 @@
1package tools.refinery.store.dse.strategy;
2
3import tools.refinery.store.map.Version;
4import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
5import tools.refinery.store.dse.Strategy;
6import tools.refinery.store.dse.internal.Activation;
7import tools.refinery.store.dse.objectives.Fitness;
8import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
9
10import java.util.Collection;
11import java.util.Iterator;
12import java.util.List;
13import java.util.PriorityQueue;
14
15public class BestFirstStrategy implements Strategy {
16
17 private DesignSpaceExplorationAdapter dseAdapter;
18
19 private int maxDepth;
20 private boolean backTrackIfSolution = true;
21 private boolean onlyBetterFirst = false;
22
23 private PriorityQueue<TrajectoryWithFitness> trajectoriesToExplore;
24
25 private static class TrajectoryWithFitness {
26
27 public List<Version> trajectory;
28 public Fitness fitness;
29
30 public TrajectoryWithFitness(List<Version> trajectory, Fitness fitness) {
31 super();
32 this.trajectory = trajectory;
33 this.fitness = fitness;
34 }
35
36 @Override
37 public String toString() {
38 return trajectory.toString() + fitness.toString();
39 }
40
41 }
42
43 public BestFirstStrategy() {
44 this(-1);
45 }
46
47 public BestFirstStrategy(int maxDepth) {
48 if (maxDepth < 0) {
49 this.maxDepth = Integer.MAX_VALUE;
50 } else {
51 this.maxDepth = maxDepth;
52 }
53 }
54
55 public BestFirstStrategy continueIfHardObjectivesFulfilled() {
56 backTrackIfSolution = false;
57 return this;
58 }
59
60 public BestFirstStrategy goOnOnlyIfFitnessIsBetter() {
61 onlyBetterFirst = true;
62 return this;
63 }
64
65 @Override
66 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
67 this.dseAdapter = designSpaceExplorationAdapter;
68 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
69
70 trajectoriesToExplore = new PriorityQueue<TrajectoryWithFitness>(11,
71 (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness));
72 }
73
74 @Override
75 public void explore() {
76 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
77
78 boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
79 if (!globalConstraintsAreSatisfied) {
80 // "Global constraint is not satisfied in the first state. Terminate.");
81 return;
82 }
83
84 final Fitness firstFitness = dseAdapter.calculateFitness();
85 if (firstFitness.isSatisfiesHardObjectives()) {
86 dseAdapter.newSolution();
87 // "First state is a solution. Terminate.");
88 if (backTrackIfSolution) {
89 return;
90 }
91 }
92
93 if (maxDepth == 0) {
94 return;
95 }
96
97 final List<Version> firstTrajectory = dseAdapter.getTrajectory();
98 TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness);
99 trajectoriesToExplore.add(currentTrajectoryWithFitness);
100
101 mainLoop: while (true) {
102
103 if (currentTrajectoryWithFitness == null) {
104 if (trajectoriesToExplore.isEmpty()) {
105 // "State space is fully traversed.");
106 return;
107 } else {
108 currentTrajectoryWithFitness = trajectoriesToExplore.element();
109// if (logger.isDebugEnabled()) {
110// "New trajectory is chosen: " + currentTrajectoryWithFitness);
111// }
112 dseAdapter.restoreTrajectory(currentTrajectoryWithFitness.trajectory);
113 }
114 }
115
116 Collection<Activation> activations = dseAdapter.getUntraversedActivations();
117 Iterator<Activation> iterator = activations.iterator();
118
119
120
121 while (iterator.hasNext()) {
122 final Activation nextActivation = iterator.next();
123 if (!iterator.hasNext()) {
124 // "Last untraversed activation of the state.");
125 trajectoriesToExplore.remove(currentTrajectoryWithFitness);
126 }
127
128// if (logger.isDebugEnabled()) {
129// "Executing new activation: " + nextActivation);
130// }
131 dseAdapter.fireActivation(nextActivation);
132 if (dseAdapter.isCurrentStateAlreadyTraversed()) {
133 // "The new state is already visited.");
134 dseAdapter.backtrack();
135 } else if (!dseAdapter.checkGlobalConstraints()) {
136 // "Global constraint is not satisfied.");
137 dseAdapter.backtrack();
138 } else {
139 final Fitness nextFitness = dseAdapter.calculateFitness();
140 if (nextFitness.isSatisfiesHardObjectives()) {
141 dseAdapter.newSolution();
142 // "Found a solution.");
143 if (backTrackIfSolution) {
144 dseAdapter.backtrack();
145 continue;
146 }
147 }
148 if (dseAdapter.getDepth() >= maxDepth) {
149 // "Reached max depth.");
150 dseAdapter.backtrack();
151 continue;
152 }
153
154 TrajectoryWithFitness nextTrajectoryWithFitness = new TrajectoryWithFitness(
155 dseAdapter.getTrajectory(), nextFitness);
156 trajectoriesToExplore.add(nextTrajectoryWithFitness);
157
158 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness,
159 nextTrajectoryWithFitness.fitness);
160 if (compare < 0) {
161 // "Better fitness, moving on: " + nextFitness);
162 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
163 continue mainLoop;
164 } else if (compare == 0) {
165 if (onlyBetterFirst) {
166 // "Equally good fitness, backtrack: " + nextFitness);
167 dseAdapter.backtrack();
168 continue;
169 } else {
170 // "Equally good fitness, moving on: " + nextFitness);
171 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
172 continue mainLoop;
173 }
174 } else {
175 // "Worse fitness.");
176 currentTrajectoryWithFitness = null;
177 continue mainLoop;
178 }
179 }
180 }
181
182 // "State is fully traversed.");
183 trajectoriesToExplore.remove(currentTrajectoryWithFitness);
184 currentTrajectoryWithFitness = null;
185
186 }
187 // "Interrupted.");
188
189 }
190}
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
new file mode 100644
index 00000000..42985013
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java
@@ -0,0 +1,108 @@
1package tools.refinery.store.dse.strategy;
2
3import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
4import tools.refinery.store.dse.Strategy;
5import tools.refinery.store.dse.internal.Activation;
6import tools.refinery.store.dse.objectives.Fitness;
7
8import java.util.Collection;
9
10public class DepthFirstStrategy implements Strategy {
11
12 private DesignSpaceExplorationAdapter dseAdapter;
13
14 private int maxDepth;
15 private boolean backTrackIfSolution = true;
16
17 public DepthFirstStrategy() {
18 this(-1);
19 }
20
21 public DepthFirstStrategy(int maxDepth) {
22 if (maxDepth < 0) {
23 this.maxDepth = Integer.MAX_VALUE;
24 } else {
25 this.maxDepth = maxDepth;
26 }
27 }
28
29 public DepthFirstStrategy continueIfHardObjectivesFulfilled() {
30 backTrackIfSolution = false;
31 return this;
32 }
33
34 @Override
35 public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
36 this.dseAdapter = designSpaceExplorationAdapter;
37 }
38
39 @Override
40 public void explore() {
41 mainloop: while (true) {
42 var globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
43 if (!globalConstraintsAreSatisfied) {
44 var isSuccessfulUndo = dseAdapter.backtrack();
45 if (!isSuccessfulUndo) {
46// "Global constraint is not satisfied and cannot backtrack."
47 break;
48 }
49 else {
50// "Global constraint is not satisfied, backtrack."
51 continue;
52 }
53 }
54
55 Fitness fitness = dseAdapter.calculateFitness();
56 if (fitness.isSatisfiesHardObjectives()) {
57 dseAdapter.newSolution();
58 if (backTrackIfSolution) {
59 var isSuccessfulUndo = dseAdapter.backtrack();
60 if (!isSuccessfulUndo) {
61// "Found a solution but cannot backtrack."
62 break;
63 } else {
64// "Found a solution, backtrack."
65 continue;
66 }
67 }
68 }
69
70 var depth = dseAdapter.getDepth();
71 if (dseAdapter.getDepth() >= maxDepth) {
72 var isSuccessfulUndo = dseAdapter.backtrack();
73 if (!isSuccessfulUndo) {
74// "Reached max depth but cannot backtrack."
75 break;
76 }
77 }
78
79 Collection<Activation> activations;
80 do {
81 activations = dseAdapter.getUntraversedActivations();
82 if (activations.isEmpty()) {
83 if (!dseAdapter.backtrack()) {
84 // "No more transitions from current state and cannot backtrack."
85 break mainloop;
86 }
87 else {
88 // "No more transitions from current state, backtrack."
89 continue;
90 }
91 }
92 } while (activations.isEmpty());
93
94 dseAdapter.fireRandomActivation();
95// if (dseAdapter.isCurrentInTrajectory()) {
96// if (!dseAdapter.backtrack()) {
97//// TODO: throw exception
98//// "The new state is present in the trajectory but cannot backtrack. Should never happen!"
99// break;
100// }
101// else {
102//// "The new state is already visited in the trajectory, backtrack."
103// continue;
104// }
105// }
106 }
107 }
108}