aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-09-05 07:59:17 +0200
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-09-05 07:59:17 +0200
commit9de7ead9602c2e51448c3b6710d13eb5dd2f3b1f (patch)
tree91d5097d5e4e5242b96299081c048cd98d47a5f7 /subprojects/store-dse
parentMerge pull request #37 from nagilooh/design-space-exploration (diff)
downloadrefinery-9de7ead9602c2e51448c3b6710d13eb5dd2f3b1f.tar.gz
refinery-9de7ead9602c2e51448c3b6710d13eb5dd2f3b1f.tar.zst
refinery-9de7ead9602c2e51448c3b6710d13eb5dd2f3b1f.zip
restructured DSE framework, failing build
Diffstat (limited to 'subprojects/store-dse')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java68
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java48
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java29
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java13
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java14
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java294
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java67
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java65
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java97
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java24
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java11
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java11
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java62
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java29
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java29
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java52
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java56
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java132
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java26
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java46
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java101
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java60
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java164
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java71
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java203
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java113
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java92
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/SubmitResult.java14
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationAdapter.java31
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java59
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java27
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValue.java24
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValues.java69
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java43
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java63
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/VersionWithObjectiveValue.java11
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationAdapterImpl.java90
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java75
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java70
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java15
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/CriterionCalculator.java10
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java15
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/ObjectiveCalculator.java10
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java44
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java44
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ActivationStore.java18
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java16
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ObjectivePriorityQueue.java21
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/SolutionStore.java17
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java47
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreBitVectorEntry.java46
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreEntry.java32
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java131
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreListEntry.java95
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java56
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/CompleteEquivalenceClassStore.java107
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java32
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java74
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java53
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java6
-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.java3
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java3
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/statespace/internal/ActivationUnitTest.java72
64 files changed, 2054 insertions, 1470 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
deleted file mode 100644
index 5aed5298..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.map.Version;
10import tools.refinery.store.dse.internal.Activation;
11import tools.refinery.store.dse.internal.DesignSpaceExplorationBuilderImpl;
12import tools.refinery.store.dse.objectives.Fitness;
13import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
14import tools.refinery.store.tuple.Tuple;
15import tools.refinery.store.tuple.Tuple1;
16
17import java.util.Collection;
18import java.util.List;
19import java.util.Random;
20
21public interface DesignSpaceExplorationAdapter extends ModelAdapter {
22 @Override
23 DesignSpaceExplorationStoreAdapter getStoreAdapter();
24
25 static DesignSpaceExplorationBuilder builder() {
26 return new DesignSpaceExplorationBuilderImpl();
27 }
28
29 Collection<Version> explore();
30
31 public int getModelSize();
32
33 public Tuple1 createObject();
34
35 public Tuple deleteObject(Tuple tuple);
36
37 public boolean checkGlobalConstraints();
38
39 public boolean backtrack();
40
41 public boolean backtrack(String reason);
42
43 public Fitness getFitness();
44
45 public void newSolution();
46
47 public int getDepth();
48
49 public Collection<Activation> getUntraversedActivations();
50
51 public boolean fireActivation(Activation activation);
52
53 public boolean fireRandomActivation();
54
55 public List<Version> getTrajectory();
56
57 public boolean isCurrentStateAlreadyTraversed();
58
59 public ObjectiveComparatorHelper getObjectiveComparatorHelper();
60
61 public void restoreTrajectory(List<Version> trajectory);
62
63 public void setRandom(Random random);
64
65 public void setRandom(long seed);
66
67 public List<Version> getSolutions();
68}
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
deleted file mode 100644
index 4def5cb2..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationBuilder.java
+++ /dev/null
@@ -1,48 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import tools.refinery.store.adapter.ModelAdapterBuilder;
9import tools.refinery.store.query.dnf.RelationalQuery;
10import tools.refinery.store.dse.internal.TransformationRule;
11import tools.refinery.store.dse.objectives.Objective;
12
13import java.util.Collection;
14import java.util.List;
15
16public interface DesignSpaceExplorationBuilder extends ModelAdapterBuilder {
17 default DesignSpaceExplorationBuilder transformations(TransformationRule... transformationRules) {
18 return transformations(List.of(transformationRules));
19 }
20
21 default DesignSpaceExplorationBuilder transformations(Collection<? extends TransformationRule> transformationRules) {
22 transformationRules.forEach(this::transformation);
23 return this;
24 }
25
26 default DesignSpaceExplorationBuilder globalConstraints(RelationalQuery... globalConstraints) {
27 return globalConstraints(List.of(globalConstraints));
28 }
29
30 default DesignSpaceExplorationBuilder globalConstraints(Collection<RelationalQuery> globalConstraints) {
31 globalConstraints.forEach(this::globalConstraint);
32 return this;
33 }
34
35 default DesignSpaceExplorationBuilder objectives(Objective... objectives) {
36 return objectives(List.of(objectives));
37 }
38
39 default DesignSpaceExplorationBuilder objectives(Collection<? extends Objective> objectives) {
40 objectives.forEach(this::objective);
41 return this;
42 }
43
44 DesignSpaceExplorationBuilder transformation(TransformationRule transformationRule);
45 DesignSpaceExplorationBuilder globalConstraint(RelationalQuery globalConstraint);
46 DesignSpaceExplorationBuilder objective(Objective objective);
47 DesignSpaceExplorationBuilder strategy(Strategy strategy);
48}
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
deleted file mode 100644
index 0252748d..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import 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;
16
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();
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
deleted file mode 100644
index c60a4410..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java
+++ /dev/null
@@ -1,13 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8public interface Strategy {
9
10 void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter);
11
12 void explore();
13}
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
deleted file mode 100644
index 1893ce2e..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/Activation.java
+++ /dev/null
@@ -1,14 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal;
7
8import tools.refinery.store.tuple.Tuple;
9
10public record Activation(TransformationRule transformationRule, Tuple activation) {
11 public boolean fire() {
12 return transformationRule.fireActivation(activation);
13 }
14}
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
deleted file mode 100644
index 220f0b2d..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
+++ /dev/null
@@ -1,294 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.internal;
11
12import tools.refinery.store.map.Version;
13import tools.refinery.store.model.Interpretation;
14import tools.refinery.store.model.Model;
15import tools.refinery.store.query.ModelQueryAdapter;
16import tools.refinery.store.query.dnf.RelationalQuery;
17import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
18import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
19import tools.refinery.store.dse.Strategy;
20import tools.refinery.store.dse.objectives.Fitness;
21import tools.refinery.store.dse.objectives.Objective;
22import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
23import tools.refinery.store.query.resultset.ResultSet;
24import tools.refinery.store.representation.Symbol;
25import tools.refinery.store.tuple.Tuple;
26import tools.refinery.store.tuple.Tuple1;
27import tools.refinery.visualization.ModelVisualizerAdapter;
28
29import java.util.*;
30
31public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExplorationAdapter {
32 static final Symbol<Integer> NODE_COUNT_SYMBOL = Symbol.of("MODEL_SIZE", 0, Integer.class, 0);
33 private final Model model;
34 private final ModelQueryAdapter queryEngine;
35 private final DesignSpaceExplorationStoreAdapterImpl storeAdapter;
36 private final Set<TransformationRule> transformationRules;
37 private final Set<RelationalQuery> globalConstraints;
38 private final List<Objective> objectives;
39 private final LinkedHashSet<ResultSet<Boolean>> globalConstraintResultSets = new LinkedHashSet<>();
40 private final Interpretation<Integer> sizeInterpretation;
41 private final Strategy strategy;
42
43 private ObjectiveComparatorHelper objectiveComparatorHelper;
44 private List<Version> trajectory = new ArrayList<>();
45 private Map<Version, Version> parents = new HashMap<>();
46 private final List<Version> solutions = new ArrayList<>();
47 private Map<Version, List<Activation>> statesAndTraversedActivations;
48 private Random random = new Random();
49 private boolean isNewState = false;
50 private final boolean isVisualizationEnabled;
51 private final ModelVisualizerAdapter modelVisualizerAdapter;
52
53 private final Map<Version, Fitness> fitnessCache = new HashMap<>();
54
55 public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) {
56 this.model = model;
57 this.storeAdapter = storeAdapter;
58 this.sizeInterpretation = model.getInterpretation(NODE_COUNT_SYMBOL);
59 queryEngine = model.getAdapter(ModelQueryAdapter.class);
60
61 globalConstraints = storeAdapter.getGlobalConstraints();
62 for (var constraint : globalConstraints) {
63 globalConstraintResultSets.add(queryEngine.getResultSet(constraint));
64 }
65
66 transformationRules = storeAdapter.getTransformationSpecifications();
67 for (var rule : transformationRules) {
68 rule.prepare(model, queryEngine);
69 }
70
71 objectives = storeAdapter.getObjectives();
72 statesAndTraversedActivations = new HashMap<>();
73 strategy = storeAdapter.getStrategy();
74 strategy.initialize(this);
75 modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null);
76 isVisualizationEnabled = modelVisualizerAdapter != null;
77
78 }
79
80 public List<Version> getTrajectory() {
81 return new ArrayList<>(trajectory);
82 }
83
84 @Override
85 public Model getModel() {
86 return model;
87 }
88
89 @Override
90 public DesignSpaceExplorationStoreAdapter getStoreAdapter() {
91 return storeAdapter;
92 }
93
94 @Override
95 public List<Version> explore() {
96 var state = model.commit();
97 trajectory.add(state);
98 strategy.explore();
99 if (isVisualizationEnabled) {
100 modelVisualizerAdapter.visualize();
101 }
102 return solutions;
103 }
104
105 @Override
106 public int getModelSize() {
107 return sizeInterpretation.get(Tuple.of());
108 }
109
110 @Override
111 public Tuple1 createObject() {
112 var newNodeId = getModelSize();
113 sizeInterpretation.put(Tuple.of(), newNodeId + 1);
114 return Tuple.of(newNodeId);
115 }
116
117 @Override
118 public Tuple deleteObject(Tuple tuple) {
119 if (tuple.getSize() != 1) {
120 throw new IllegalArgumentException("Tuple size must be 1");
121 }
122// TODO: implement more efficient deletion
123// if (tuple.get(0) == getModelSize() - 1) {
124// sizeInterpretation.put(Tuple.of(), getModelSize() - 1);
125// }
126 return tuple;
127 }
128
129 @Override
130 public boolean checkGlobalConstraints() {
131 for (var resultSet : globalConstraintResultSets) {
132 if (resultSet.size() > 0) {
133 return false;
134 }
135 }
136 return true;
137 }
138
139 @Override
140 public boolean backtrack() {
141 return backtrack("");
142 }
143 @Override
144 public boolean backtrack(String reason) {
145 if (trajectory.size() < 2) {
146 return false;
147 }
148 var currentState = model.getState();
149 if (!parents.containsKey(currentState)) {
150 return false;
151 }
152 if (isVisualizationEnabled) {
153 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 1),
154 trajectory.get(trajectory.size() - 2), "backtrack(" + reason + ")");
155 }
156 model.restore(parents.get(model.getState()));
157 trajectory.remove(trajectory.size() - 1);
158 return true;
159 }
160
161 @Override
162 public void restoreTrajectory(List<Version> trajectory) {
163 model.restore(trajectory.get(trajectory.size() - 1));
164// if (isVisualizationEnabled) {
165// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1),
166// trajectory.get(trajectory.size() - 1), "restore");
167// }
168 this.trajectory = new ArrayList<>(trajectory);
169
170 }
171
172 @Override
173 public void setRandom(Random random) {
174 this.random = random;
175 }
176
177 @Override
178 public void setRandom(long seed) {
179 this.random = new Random(seed);
180 }
181
182 @Override
183 public List<Version> getSolutions() {
184 return solutions;
185 }
186
187 @Override
188 public Fitness getFitness() {
189 return fitnessCache.computeIfAbsent(model.getState(), s -> calculateFitness());
190 }
191
192 private Fitness calculateFitness() {
193 Fitness result = new Fitness();
194 boolean satisfiesHardObjectives = true;
195 for (Objective objective : objectives) {
196 var fitness = objective.getFitness(this);
197 result.put(objective.getName(), fitness);
198 if (objective.isHardObjective() && !objective.satisfiesHardObjective(fitness)) {
199 satisfiesHardObjectives = false;
200 }
201 }
202 result.setSatisfiesHardObjectives(satisfiesHardObjectives);
203
204 return result;
205 }
206
207 @Override
208 public void newSolution() {
209 var state = model.getState();
210 solutions.add(state);
211 if (isVisualizationEnabled) {
212 modelVisualizerAdapter.addSolution(state);
213 }
214 }
215
216 @Override
217 public int getDepth() {
218 return trajectory.size() - 1;
219 }
220
221 public LinkedHashSet<Activation> getUntraversedActivations() {
222 var traversedActivations = statesAndTraversedActivations.get(model.getState());
223 if (traversedActivations == null) {
224 return new LinkedHashSet<>(getAllActivations());
225 }
226 else {
227 LinkedHashSet<Activation> untraversedActivations = new LinkedHashSet<>();
228 for (Activation activation : getAllActivations()) {
229 if (!traversedActivations.contains(activation)) {
230 untraversedActivations.add(activation);
231 }
232 }
233 return untraversedActivations;
234 }
235 }
236
237 @Override
238 public boolean fireActivation(Activation activation) {
239 if (activation == null) {
240 return false;
241 }
242 var previousState = model.getState();
243 if (!activation.fire()) {
244 return false;
245 }
246 statesAndTraversedActivations.computeIfAbsent(previousState, s -> new ArrayList<>()).add(activation);
247 var newState = model.commit();
248 trajectory.add(newState);
249 parents.put(newState, previousState);
250 isNewState = !statesAndTraversedActivations.containsKey(newState);
251 if (isVisualizationEnabled) {
252 if (isNewState) {
253 modelVisualizerAdapter.addState(newState, getFitness().values());
254 }
255 modelVisualizerAdapter.addTransition(previousState, newState, activation.transformationRule().getName(),
256 activation.activation());
257 }
258 return true;
259 }
260
261 @Override
262 public boolean fireRandomActivation() {
263 var activations = getUntraversedActivations();
264 if (activations.isEmpty()) {
265 return false;
266 }
267 int index = random.nextInt(activations.size());
268 var iterator = activations.iterator();
269 while (index-- > 0) {
270 iterator.next();
271 }
272 var activationId = iterator.next();
273 return fireActivation(activationId);
274 }
275
276 public List<Activation> getAllActivations() {
277 List<Activation> result = new LinkedList<>();
278 for (var rule : transformationRules) {
279 result.addAll(rule.getAllActivationsAsList());
280 }
281 return result;
282 }
283
284 public boolean isCurrentStateAlreadyTraversed() {
285 return !isNewState;
286 }
287
288 public ObjectiveComparatorHelper getObjectiveComparatorHelper() {
289 if (objectiveComparatorHelper == null) {
290 objectiveComparatorHelper = new ObjectiveComparatorHelper(objectives);
291 }
292 return objectiveComparatorHelper;
293 }
294}
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
deleted file mode 100644
index 8f7056f2..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationBuilderImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal;
7
8import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.model.ModelStoreBuilder;
11import tools.refinery.store.query.dnf.RelationalQuery;
12import tools.refinery.store.dse.DesignSpaceExplorationBuilder;
13import tools.refinery.store.dse.Strategy;
14import tools.refinery.store.dse.objectives.Objective;
15
16import java.util.LinkedHashSet;
17import java.util.LinkedList;
18import java.util.List;
19
20public class DesignSpaceExplorationBuilderImpl
21 extends AbstractModelAdapterBuilder<DesignSpaceExplorationStoreAdapterImpl>
22 implements DesignSpaceExplorationBuilder {
23 private final LinkedHashSet<TransformationRule> transformationSpecifications = new LinkedHashSet<>();
24 private final LinkedHashSet<RelationalQuery> globalConstraints = new LinkedHashSet<>();
25 private final List<Objective> objectives = new LinkedList<>();
26 private Strategy strategy;
27
28 @Override
29 protected DesignSpaceExplorationStoreAdapterImpl doBuild(ModelStore store) {
30 return new DesignSpaceExplorationStoreAdapterImpl(store, transformationSpecifications, globalConstraints,
31 objectives, strategy);
32 }
33
34 @Override
35 public DesignSpaceExplorationBuilder transformation(TransformationRule transformationRule) {
36 checkNotConfigured();
37 transformationSpecifications.add(transformationRule);
38 return this;
39 }
40
41 @Override
42 public DesignSpaceExplorationBuilder globalConstraint(RelationalQuery globalConstraint) {
43 checkNotConfigured();
44 globalConstraints.add(globalConstraint);
45 return this;
46 }
47
48 @Override
49 public DesignSpaceExplorationBuilder objective(Objective objective) {
50 checkNotConfigured();
51 objectives.add(objective);
52 return this;
53 }
54
55 @Override
56 public DesignSpaceExplorationBuilder strategy(Strategy strategy) {
57 checkNotConfigured();
58 this.strategy = strategy;
59 return this;
60 }
61
62 @Override
63 protected void doConfigure(ModelStoreBuilder storeBuilder) {
64 storeBuilder.symbols(DesignSpaceExplorationAdapterImpl.NODE_COUNT_SYMBOL);
65 super.doConfigure(storeBuilder);
66 }
67}
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
deleted file mode 100644
index fea39886..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java
+++ /dev/null
@@ -1,65 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal;
7
8import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
9import tools.refinery.store.dse.Strategy;
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;
14
15import java.util.List;
16import java.util.Set;
17
18public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter {
19 private final ModelStore store;
20 private final Set<TransformationRule> transformationSpecifications;
21 private final Set<RelationalQuery> globalConstraints;
22 private final List<Objective> objectives;
23 private final Strategy strategy;
24
25 public DesignSpaceExplorationStoreAdapterImpl(ModelStore store,
26 Set<TransformationRule> transformationSpecifications,
27 Set<RelationalQuery> globalConstraints,
28 List<Objective> objectives, Strategy strategy) {
29 this.store = store;
30 this.transformationSpecifications = transformationSpecifications;
31 this.globalConstraints = globalConstraints;
32 this.objectives = objectives;
33 this.strategy = strategy;
34 }
35
36 @Override
37 public ModelStore getStore() {
38 return store;
39 }
40
41 @Override
42 public DesignSpaceExplorationAdapterImpl createModelAdapter(Model model) {
43 return new DesignSpaceExplorationAdapterImpl(model, this);
44 }
45
46 @Override
47 public Set<TransformationRule> getTransformationSpecifications() {
48 return transformationSpecifications;
49 }
50
51 @Override
52 public Set<RelationalQuery> getGlobalConstraints() {
53 return globalConstraints;
54 }
55
56 @Override
57 public List<Objective> getObjectives() {
58 return objectives;
59 }
60
61 @Override
62 public Strategy getStrategy() {
63 return strategy;
64 }
65}
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
deleted file mode 100644
index 8123c0d6..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
+++ /dev/null
@@ -1,97 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal;
7
8import org.eclipse.collections.api.block.procedure.Procedure;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.dnf.RelationalQuery;
12import tools.refinery.store.dse.ActionFactory;
13import tools.refinery.store.query.resultset.OrderedResultSet;
14import tools.refinery.store.query.resultset.ResultSet;
15import tools.refinery.store.tuple.Tuple;
16
17import java.util.*;
18
19public class TransformationRule {
20
21 private final String name;
22 private final RelationalQuery precondition;
23 private final ActionFactory actionFactory;
24 private Procedure<Tuple> action;
25 private OrderedResultSet<Boolean> activations;
26 private Random random;
27 private ModelQueryAdapter queryEngine;
28
29 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) {
30 this(name, precondition, actionFactory, new Random());
31 }
32
33 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) {
34 this(name, precondition, actionFactory, new Random(seed));
35 }
36
37 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, Random random) {
38 this.name = name;
39 this.precondition = precondition;
40 this.actionFactory = actionFactory;
41 this.random = random;
42 }
43 public boolean prepare(Model model, ModelQueryAdapter queryEngine) {
44 action = actionFactory.prepare(model);
45 this.queryEngine = queryEngine;
46 activations = new OrderedResultSet<>(queryEngine.getResultSet(precondition));
47 return true;
48 }
49
50 public boolean fireActivation(Tuple activation) {
51 action.accept(activation);
52 queryEngine.flushChanges();
53 return true;
54 }
55
56 public boolean fireRandomActivation() {
57 return getRandomActivation().fire();
58 }
59
60 public String getName() {
61 return name;
62 }
63
64 public RelationalQuery getPrecondition() {
65 return precondition;
66 }
67
68 public ResultSet<Boolean> getAllActivationsAsResultSet() {
69 return activations;
70 }
71
72 public Set<Activation> getAllActivations() {
73 var result = new LinkedHashSet<Activation>();
74 var cursor = activations.getAll();
75 while (cursor.move()) {
76 result.add(new Activation(this, cursor.getKey()));
77 }
78 return result;
79 }
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
90 public Activation getRandomActivation() {
91 return new Activation(this, activations.getKey(random.nextInt(activations.size())));
92 }
93
94 public Activation getActivation(int index) {
95 return new Activation(this, activations.getKey(index));
96 }
97}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java
new file mode 100644
index 00000000..f15c16e0
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java
@@ -0,0 +1,24 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification;
7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.dse.modification.internal.ModificationBuilderImpl;
10import tools.refinery.store.tuple.Tuple;
11import tools.refinery.store.tuple.Tuple1;
12
13public interface ModificationAdapter extends ModelAdapter {
14
15 int getModelSize();
16
17 Tuple1 createObject();
18
19 Tuple deleteObject(Tuple tuple);
20
21 static ModificationBuilder builder() {
22 return new ModificationBuilderImpl();
23 }
24}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java
new file mode 100644
index 00000000..48c22bdf
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java
@@ -0,0 +1,11 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification;
7
8import tools.refinery.store.adapter.ModelAdapterBuilder;
9
10public interface ModificationBuilder extends ModelAdapterBuilder {
11}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java
new file mode 100644
index 00000000..144c4d05
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java
@@ -0,0 +1,11 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9
10public interface ModificationStoreAdapter extends ModelStoreAdapter {
11}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java
new file mode 100644
index 00000000..b2a80d71
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java
@@ -0,0 +1,62 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification.internal;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.dse.modification.ModificationAdapter;
10import tools.refinery.store.model.Interpretation;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.representation.Symbol;
13import tools.refinery.store.tuple.Tuple;
14import tools.refinery.store.tuple.Tuple1;
15
16public class ModificationAdapterImpl implements ModificationAdapter {
17 static final Symbol<Integer> NEXT_ID = Symbol.of("NEXT_ID", 0, Integer.class, 0);
18
19 final ModelStoreAdapter storeAdapter;
20 final Model model;
21 Interpretation<Integer> nodeCountInterpretation;
22
23 ModificationAdapterImpl(ModelStoreAdapter storeAdapter, Model model) {
24 this.storeAdapter = storeAdapter;
25 this.model = model;
26 this.nodeCountInterpretation = model.getInterpretation(NEXT_ID);
27 }
28
29 @Override
30 public Model getModel() {
31 return model;
32 }
33
34 @Override
35 public ModelStoreAdapter getStoreAdapter() {
36 return storeAdapter;
37 }
38
39 @Override
40 public int getModelSize() {
41 return nodeCountInterpretation.get(Tuple.of());
42 }
43
44 @Override
45 public Tuple1 createObject() {
46 var newNodeId = getModelSize();
47 nodeCountInterpretation.put(Tuple.of(), newNodeId + 1);
48 return Tuple.of(newNodeId);
49 }
50
51 @Override
52 public Tuple deleteObject(Tuple tuple) {
53 if (tuple.getSize() != 1) {
54 throw new IllegalArgumentException("Tuple size must be 1");
55 }
56// TODO: implement more efficient deletion
57 if (tuple.get(0) == getModelSize() - 1) {
58 nodeCountInterpretation.put(Tuple.of(), getModelSize() - 1);
59 }
60 return tuple;
61 }
62}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java
new file mode 100644
index 00000000..c4d38d22
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java
@@ -0,0 +1,29 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification.internal;
7
8import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
9import tools.refinery.store.dse.modification.ModificationBuilder;
10import tools.refinery.store.dse.modification.ModificationStoreAdapter;
11import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.model.ModelStoreBuilder;
13import tools.refinery.store.statecoding.StateCoderBuilder;
14
15public class ModificationBuilderImpl extends AbstractModelAdapterBuilder<ModificationStoreAdapter> implements ModificationBuilder {
16
17 @Override
18 protected void doConfigure(ModelStoreBuilder storeBuilder) {
19 storeBuilder.symbols(ModificationAdapterImpl.NEXT_ID);
20 storeBuilder.tryGetAdapter(StateCoderBuilder.class).ifPresent(
21 coderBuilder -> coderBuilder.exclude(ModificationAdapterImpl.NEXT_ID));
22 super.doConfigure(storeBuilder);
23 }
24
25 @Override
26 protected ModificationStoreAdapter doBuild(ModelStore store) {
27 return new ModificationStoreAdapterImpl(store);
28 }
29}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java
new file mode 100644
index 00000000..913cb33f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java
@@ -0,0 +1,29 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.modification.internal;
7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.dse.modification.ModificationStoreAdapter;
10import tools.refinery.store.model.Model;
11import tools.refinery.store.model.ModelStore;
12
13public class ModificationStoreAdapterImpl implements ModificationStoreAdapter {
14 ModelStore store;
15
16 ModificationStoreAdapterImpl(ModelStore store) {
17 this.store = store;
18 }
19
20 @Override
21 public ModelStore getStore() {
22 return store;
23 }
24
25 @Override
26 public ModelAdapter createModelAdapter(Model model) {
27 return null;
28 }
29}
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
deleted file mode 100644
index afed75fd..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedDummyHardObjective.java
+++ /dev/null
@@ -1,52 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
13
14/**
15 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution.
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class AlwaysSatisfiedDummyHardObjective extends BaseObjective {
21
22 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective";
23
24 public AlwaysSatisfiedDummyHardObjective() {
25 super(DEFAULT_NAME);
26 }
27
28 public AlwaysSatisfiedDummyHardObjective(String name) {
29 super(name);
30 }
31
32 @Override
33 public Double getFitness(DesignSpaceExplorationAdapter context) {
34 return 0d;
35 }
36
37 @Override
38 public boolean isHardObjective() {
39 return true;
40 }
41
42 @Override
43 public boolean satisfiesHardObjective(Double fitness) {
44 return true;
45 }
46
47 @Override
48 public Objective createNew() {
49 return this;
50 }
51
52}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java
deleted file mode 100644
index 327d5e2f..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java
+++ /dev/null
@@ -1,56 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
13
14import java.util.Random;
15
16/**
17 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution.
18 *
19 * @author Andras Szabolcs Nagy
20 *
21 */
22public class AlwaysSatisfiedRandomHardObjective extends BaseObjective {
23
24 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective";
25 private static final Random random = new Random(0);
26
27 public AlwaysSatisfiedRandomHardObjective() {
28 super(DEFAULT_NAME);
29 }
30
31 public AlwaysSatisfiedRandomHardObjective(String name) {
32 super(name);
33 }
34
35 @Override
36 public Double getFitness(DesignSpaceExplorationAdapter context) {
37// return 0d;
38 return random.nextDouble();
39 }
40
41 @Override
42 public boolean isHardObjective() {
43 return true;
44 }
45
46 @Override
47 public boolean satisfiesHardObjective(Double fitness) {
48 return true;
49 }
50
51 @Override
52 public Objective createNew() {
53 return this;
54 }
55
56}
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
deleted file mode 100644
index b76598fb..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java
+++ /dev/null
@@ -1,132 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
13
14import java.util.Comparator;
15import java.util.Objects;
16
17/**
18 * This abstract class implements the basic functionality of an objective ({@link Objective} namely its name,
19 * comparator, level and fitness hard constraint.
20 *
21 * @author Andras Szabolcs Nagy
22 *
23 */
24public abstract class BaseObjective implements Objective {
25
26 protected final String name;
27 protected Comparator<Double> comparator = Comparators.HIGHER_IS_BETTER;
28
29 protected double fitnessConstraint;
30 protected boolean isThereFitnessConstraint = false;
31 protected Comparator<Double> fitnessConstraintComparator;
32
33 protected BaseObjective(String name) {
34 Objects.requireNonNull(name, "Name of the objective cannot be null.");
35 this.name = name;
36 }
37
38 @Override
39 public String getName() {
40 return name;
41 }
42
43 @Override
44 public void setComparator(Comparator<Double> comparator) {
45 this.comparator = comparator;
46 }
47
48 @Override
49 public Comparator<Double> getComparator() {
50 return comparator;
51 }
52
53 public BaseObjective withComparator(Comparator<Double> comparator) {
54 setComparator(comparator);
55 return this;
56 }
57
58 /**
59 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
60 * current state as a solution.
61 *
62 * @param fitnessConstraint
63 * Solutions should be better than this value.
64 * @param fitnessConstraintComparator
65 * {@link Comparator} to determine if the current state is better than the given value.
66 * @return The actual instance to enable builder pattern like usage.
67 */
68 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint,
69 Comparator<Double> fitnessConstraintComparator) {
70 this.fitnessConstraint = fitnessConstraint;
71 this.fitnessConstraintComparator = fitnessConstraintComparator;
72 this.isThereFitnessConstraint = true;
73 return this;
74 }
75
76 /**
77 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
78 * current state as a solution. The provided comparator will be used.
79 *
80 * @param fitnessConstraint
81 * Solutions should be better than this value.
82 * @return The actual instance to enable builder pattern like usage.
83 */
84 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint) {
85 return withHardConstraintOnFitness(fitnessConstraint, null);
86 }
87
88 @Override
89 public void init(DesignSpaceExplorationAdapter context) {
90 if (fitnessConstraintComparator == null) {
91 fitnessConstraintComparator = comparator;
92 }
93 }
94
95 @Override
96 public boolean isHardObjective() {
97 return isThereFitnessConstraint;
98 }
99
100 @Override
101 public boolean satisfiesHardObjective(Double fitness) {
102 if (isThereFitnessConstraint) {
103 int compare = fitnessConstraintComparator.compare(fitness, fitnessConstraint);
104 if (compare < 0) {
105 return false;
106 }
107 }
108 return true;
109 }
110
111 @Override
112 public int hashCode() {
113 return name.hashCode();
114 }
115
116 @Override
117 public boolean equals(Object obj) {
118 if (this == obj) {
119 return true;
120 }
121 if (obj instanceof BaseObjective baseObjective) {
122 return name.equals(baseObjective.getName());
123 }
124 return false;
125 }
126
127 @Override
128 public String toString() {
129 return name;
130 }
131
132}
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
deleted file mode 100644
index 181397b3..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java
+++ /dev/null
@@ -1,26 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import java.util.Comparator;
13
14public class Comparators {
15
16 private Comparators() { /*Utility class constructor*/ }
17
18 public static final Comparator<Double> HIGHER_IS_BETTER = Double::compareTo;
19
20 public static final Comparator<Double> LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1);
21
22 private static final Double ZERO = (double) 0;
23
24 public static final Comparator<Double> DIFFERENCE_TO_ZERO_IS_BETTER = (o1, o2) -> ZERO.compareTo(Math.abs(o1)-Math.abs(o2));
25
26}
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
deleted file mode 100644
index b1dc4442..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java
+++ /dev/null
@@ -1,46 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import java.util.HashMap;
13
14public class Fitness extends HashMap<String, Double> {
15
16 private boolean satisfiesHardObjectives;
17
18 public boolean isSatisfiesHardObjectives() {
19 return satisfiesHardObjectives;
20 }
21
22 public void setSatisfiesHardObjectives(boolean satisfiesHardObjectives) {
23 this.satisfiesHardObjectives = satisfiesHardObjectives;
24 }
25
26 @Override
27 public String toString() {
28 return super.toString() + " hardObjectives=" + satisfiesHardObjectives;
29 }
30
31 @Override
32 public boolean equals(Object other) {
33 if (other == null) return false;
34 if (getClass() != other.getClass()) return false;
35 if (!super.equals(other)) return false;
36 return satisfiesHardObjectives == ((Fitness) other).satisfiesHardObjectives;
37 }
38
39 @Override
40 public int hashCode() {
41 int h = super.hashCode();
42 h = h * 31 + (satisfiesHardObjectives ? 1 : 0);
43 return h;
44 }
45
46}
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
deleted file mode 100644
index c7313622..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Objective.java
+++ /dev/null
@@ -1,101 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
13
14import java.util.Comparator;
15
16/**
17 *
18 * Implementation of this interface represents a single objective of the DSE problem, which can assess a solution
19 * (trajectory) in a single number. It has a name and a comparator which orders two solution based on the calculated
20 * value.
21 * <p>
22 * Objectives can be either hard or soft objectives. Hard objectives can be satisfied or unsatisfied. If all of the hard
23 * objectives are satisfied on a single solution, then it is considered to be a valid (or goal) solution.
24 * <p>
25 * Certain objectives can have inner state for calculating the fitness value. In this case a new instance is necessary
26 * for every new thread, and the {@code createNew} method should not return the same instance more than once.
27 *
28 * @author Andras Szabolcs Nagy
29 *
30 */
31public interface Objective {
32
33 /**
34 * Returns the name of the objective.
35 *
36 * @return The name of the objective.
37 */
38 String getName();
39
40 /**
41 * Sets the {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is to
42 * minimize or maximize (or minimize or maximize a delta from a given number).
43 *
44 * @param comparator The comparator.
45 */
46 void setComparator(Comparator<Double> comparator);
47
48 /**
49 * Returns a {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is
50 * to minimize or maximize (or minimize or maximize a delta from a given number).
51 *
52 * @return The comparator.
53 */
54 Comparator<Double> getComparator();
55
56 /**
57 * Calculates the value of the objective on a given solution (trajectory).
58 *
59 * @param context
60 * The {@link DesignSpaceExplorationAdapter}
61 * @return The objective value in double.
62 */
63 Double getFitness(DesignSpaceExplorationAdapter context);
64
65 /**
66 * Initializes the objective. It is called exactly once for every thread starts.
67 *
68 * @param context
69 * The {@link DesignSpaceExplorationAdapter}.
70 */
71 void init(DesignSpaceExplorationAdapter context);
72
73 /**
74 * Returns an instance of the {@link Objective}. If it returns the same instance, all the methods has to be thread
75 * save as they are called concurrently.
76 *
77 * @return An instance of the objective.
78 */
79 Objective createNew();
80
81 /**
82 * Returns true if the objective is a hard objective. In such a case the method
83 * {@link Objective#satisfiesHardObjective(Double)} is called.
84 *
85 * @return True if the objective is a hard objective.
86 * @see Objective#satisfiesHardObjective(Double)
87 * @see Objective
88 */
89 boolean isHardObjective();
90
91 /**
92 * Determines if the given fitness value satisfies the hard objective.
93 *
94 * @param fitness
95 * The fitness value of a solution.
96 * @return True if it satisfies the hard objective or it is a soft constraint.
97 * @see Objective
98 */
99 boolean satisfiesHardObjective(Double fitness);
100
101}
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
deleted file mode 100644
index eb03eeaf..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java
+++ /dev/null
@@ -1,60 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.objectives;
11
12import java.util.List;
13
14/**
15 * This class is responsible to compare and sort fitness values.
16 *
17 * @author András Szabolcs Nagy
18 */
19public class ObjectiveComparatorHelper {
20
21 private final List<Objective> objectives;
22
23 public ObjectiveComparatorHelper(List<Objective> objectives) {
24 this.objectives = objectives;
25 }
26
27 /**
28 * Compares two fitnesses based on dominance. Returns -1 if the second parameter {@code o2} is a better
29 * solution ({@code o2} dominates {@code o1}), 1 if the first parameter {@code o1} is better ({@code o1} dominates
30 * {@code o2}) and returns 0 if they are non-dominating each other.
31 */
32 public int compare(Fitness o1, Fitness o2) {
33
34 boolean o1HasBetterFitness = false;
35 boolean o2HasBetterFitness = false;
36
37 for (Objective objective : objectives) {
38 String objectiveName = objective.getName();
39 int sgn = objective.getComparator().compare(o1.get(objectiveName), o2.get(objectiveName));
40
41 if (sgn < 0) {
42 o2HasBetterFitness = true;
43 }
44 if (sgn > 0) {
45 o1HasBetterFitness = true;
46 }
47 if (o1HasBetterFitness && o2HasBetterFitness) {
48 break;
49 }
50 }
51 if (o2HasBetterFitness) {
52 return -1;
53 } else if (o1HasBetterFitness) {
54 return 1;
55 }
56
57 return 0;
58
59 }
60}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java
new file mode 100644
index 00000000..72bbbc55
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java
@@ -0,0 +1,164 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.strategy;
7
8import tools.refinery.store.dse.transition.ObjectiveValue;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.model.Model;
11
12import java.util.Random;
13
14public class BestFirstExplorer extends BestFirstWorker {
15 final int id;
16 Random random;
17 public BestFirstExplorer(BestFirstStoreManager storeManager, Model model, int id) {
18 super(storeManager, model);
19 this.id = id;
20 this.random = new Random(id);
21 }
22
23 private boolean interrupted = false;
24 public void interrupt() {
25 this.interrupted = true;
26 }
27
28 private boolean shouldRun() {
29 return !interrupted && !hasEnoughSolution();
30 }
31
32 public void explore() {
33 VersionWithObjectiveValue lastVisited = submit().newVersion();
34
35 mainLoop: while (shouldRun()) {
36
37 if (lastVisited == null) {
38 var restored = this.restoreToBest();
39 if(restored != null) {
40 lastVisited = restored;
41 } else {
42 return;
43 }
44 }
45
46 boolean tryActivation = true;
47 while(tryActivation && shouldRun()) {
48 RandomVisitResult randomVisitResult = this.visitRandomUnvisited(random);
49
50 tryActivation &= randomVisitResult.shouldRetry();
51 var newSubmit = randomVisitResult.submitResult();
52 if(newSubmit != null) {
53 if(!newSubmit.include()) {
54 restoreToLast();
55 } else {
56 var newVisit = newSubmit.newVersion();
57 int compareResult = compare(lastVisited,newVisit);
58 if(compareResult >= 0) {
59 lastVisited = newVisit;
60 continue mainLoop;
61 }
62 }
63 }
64 }
65
66 //final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
67
68 /*boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
69 if (!globalConstraintsAreSatisfied) {
70 // Global constraint is not satisfied in the first state. Terminate.
71 return;
72 }
73
74 final Fitness firstFitness = dseAdapter.getFitness();
75 if (firstFitness.isSatisfiesHardObjectives()) {
76 dseAdapter.newSolution();
77 // First state is a solution. Terminate.
78 if (backTrackIfSolution) {
79 return;
80 }
81 }
82
83 if (maxDepth == 0) {
84 return;
85 }*/
86
87 /*
88 var firstTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), firstFitness);
89 trajectoriesToExplore.add(firstTrajectoryWithFitness);
90 TrajectoryWithFitness currentTrajectoryWithFitness = null;
91 */
92/*
93 Collection<Activation> activations = dseAdapter.getUntraversedActivations();
94 Iterator<Activation> iterator = activations.iterator();
95
96 while (iterator.hasNext()) {
97 final Activation nextActivation = iterator.next();
98 if (!iterator.hasNext()) {
99 // Last untraversed activation of the state.
100 trajectoriesToExplore.remove(currentTrajectoryWithFitness);
101 }
102
103 // Executing new activation
104 dseAdapter.fireActivation(nextActivation);
105 if (dseAdapter.isCurrentStateAlreadyTraversed()) {
106 // The new state is already visited.
107 dseAdapter.backtrack();
108 } else if (!dseAdapter.checkGlobalConstraints()) {
109 // Global constraint is not satisfied.
110 dseAdapter.backtrack();
111 } else {
112 final Fitness nextFitness = dseAdapter.getFitness();
113 if (nextFitness.isSatisfiesHardObjectives()) {
114 dseAdapter.newSolution();
115 var solutions = dseAdapter.getSolutions().size();
116 if (solutions >= maxSolutions) {
117 return;
118 }
119 // Found a solution.
120 if (backTrackIfSolution) {
121 dseAdapter.backtrack();
122 continue;
123 }
124 }
125 if (dseAdapter.getDepth() >= maxDepth) {
126 // Reached max depth.
127 dseAdapter.backtrack();
128 continue;
129 }
130
131 TrajectoryWithFitness nextTrajectoryWithFitness = new TrajectoryWithFitness(
132 dseAdapter.getTrajectory(), nextFitness);
133 trajectoriesToExplore.add(nextTrajectoryWithFitness);
134
135 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness,
136 nextTrajectoryWithFitness.fitness);
137 if (compare < 0) {
138 // Better fitness, moving on
139 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
140 continue mainLoop;
141 } else if (compare == 0) {
142 if (onlyBetterFirst) {
143 // Equally good fitness, backtrack
144 dseAdapter.backtrack();
145 } else {
146 // Equally good fitness, moving on
147 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
148 continue mainLoop;
149 }
150 } else {
151 //"Worse fitness
152 currentTrajectoryWithFitness = null;
153 continue mainLoop;
154 }
155 }
156 }
157
158 // State is fully traversed.
159 currentTrajectoryWithFitness = null;
160*/
161 }
162 // Interrupted.
163 }
164}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java
new file mode 100644
index 00000000..d1fd7884
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java
@@ -0,0 +1,71 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.strategy;
7
8import org.eclipse.collections.api.block.procedure.Procedure;
9import tools.refinery.store.dse.transition.DesignSpaceExplorationStoreAdapter;
10import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
11import tools.refinery.store.dse.transition.statespace.ActivationStore;
12import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
13import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue;
14import tools.refinery.store.dse.transition.statespace.SolutionStore;
15import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreImpl;
16import tools.refinery.store.dse.transition.statespace.internal.FastEquivalenceClassStore;
17import tools.refinery.store.dse.transition.statespace.internal.ObjectivePriorityQueueImpl;
18import tools.refinery.store.dse.transition.statespace.internal.SolutionStoreImpl;
19import tools.refinery.store.map.Version;
20import tools.refinery.store.model.ModelStore;
21import tools.refinery.store.statecoding.StateCoderStoreAdapter;
22
23public class BestFirstStoreManager {
24 ModelStore modelStore;
25 ObjectivePriorityQueue objectiveStore;
26 ActivationStore activationStore;
27 SolutionStore solutionStore;
28 EquivalenceClassStore equivalenceClassStore;
29
30 public BestFirstStoreManager(ModelStore modelStore) {
31 this.modelStore = modelStore;
32 DesignSpaceExplorationStoreAdapter storeAdapter =
33 modelStore.getAdapter(DesignSpaceExplorationStoreAdapter.class);
34
35 objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives());
36 Procedure<VersionWithObjectiveValue> whenAllActivationsVisited = x -> objectiveStore.remove(x);
37 activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited);
38 solutionStore = new SolutionStoreImpl(1);
39 equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) {
40 @Override
41 protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) {
42 objectiveStore.submit(version);
43 activationStore.markNewAsVisited(version, emptyActivations);
44 if(accept) {
45 solutionStore.submit(version);
46 }
47 }
48 };
49 }
50
51 ObjectivePriorityQueue getObjectiveStore() {
52 return objectiveStore;
53 }
54
55 ActivationStore getActivationStore() {
56 return activationStore;
57 }
58
59 SolutionStore getSolutionStore() {
60 return solutionStore;
61 }
62
63 EquivalenceClassStore getEquivalenceClassStore() {
64 return equivalenceClassStore;
65 }
66
67 public void startExploration(Version initial) {
68 BestFirstExplorer bestFirstExplorer = new BestFirstExplorer(this, modelStore.createModelForState(initial), 1);
69 bestFirstExplorer.explore();
70 }
71}
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
deleted file mode 100644
index 92d878ce..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java
+++ /dev/null
@@ -1,203 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro
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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.store.dse.strategy;
11
12import tools.refinery.store.map.Version;
13import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
14import tools.refinery.store.dse.Strategy;
15import tools.refinery.store.dse.internal.Activation;
16import tools.refinery.store.dse.objectives.Fitness;
17import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper;
18
19import java.util.*;
20
21public class BestFirstStrategy implements Strategy {
22
23 private DesignSpaceExplorationAdapter dseAdapter;
24
25 private int maxDepth = Integer.MAX_VALUE;
26 private int maxSolutions = Integer.MAX_VALUE;
27 private boolean backTrackIfSolution = true;
28 private boolean onlyBetterFirst = false;
29
30 private PriorityQueue<TrajectoryWithFitness> trajectoriesToExplore;
31
32 private record TrajectoryWithFitness(List<Version> trajectory, Fitness fitness) {
33 @Override
34 public String toString() {
35 return trajectory.toString() + fitness.toString();
36 }
37
38 @Override
39 public int hashCode() {
40 return trajectory.get(trajectory.size() - 1).hashCode();
41 }
42
43 @Override
44 public boolean equals(Object obj) {
45 if (obj instanceof TrajectoryWithFitness other) {
46 return Objects.equals(trajectory.get(trajectory.size() - 1), other.trajectory.get(other.trajectory.size() - 1));
47// return trajectory.equals(((TrajectoryWithFitness) obj).trajectory);
48 }
49 return false;
50 }
51 }
52
53 public BestFirstStrategy withDepthLimit(int maxDepth) {
54 if (maxDepth >= 0) {
55 this.maxDepth = maxDepth;
56 }
57 return this;
58 }
59
60 public BestFirstStrategy withSolutionLimit(int maxSolutions) {
61 if (maxSolutions >= 0) {
62 this.maxSolutions = maxSolutions;
63 }
64 return this;
65 }
66
67 public BestFirstStrategy continueIfHardObjectivesFulfilled() {
68 backTrackIfSolution = false;
69 return this;
70 }
71
72 public BestFirstStrategy goOnOnlyIfFitnessIsBetter() {
73 onlyBetterFirst = true;
74 return this;
75 }
76
77 @Override
78 public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
79 this.dseAdapter = designSpaceExplorationAdapter;
80 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
81
82 trajectoriesToExplore = new PriorityQueue<>(11,
83 (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness));
84 }
85
86 @Override
87 public void explore() {
88 if (maxSolutions == 0) {
89 return;
90 }
91 final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper();
92
93 boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints();
94 if (!globalConstraintsAreSatisfied) {
95 // Global constraint is not satisfied in the first state. Terminate.
96 return;
97 }
98
99 final Fitness firstFitness = dseAdapter.getFitness();
100 if (firstFitness.isSatisfiesHardObjectives()) {
101 dseAdapter.newSolution();
102 // First state is a solution. Terminate.
103 if (backTrackIfSolution) {
104 return;
105 }
106 }
107
108 if (maxDepth == 0) {
109 return;
110 }
111
112
113 var firstTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), firstFitness);
114 trajectoriesToExplore.add(firstTrajectoryWithFitness);
115 TrajectoryWithFitness currentTrajectoryWithFitness = null;
116
117 mainLoop: while (true) {
118
119 if (currentTrajectoryWithFitness == null) {
120 if (trajectoriesToExplore.isEmpty()) {
121 // State space is fully traversed.
122 return;
123 } else {
124 currentTrajectoryWithFitness = trajectoriesToExplore.element();
125 // New trajectory is chosen: " + currentTrajectoryWithFitness
126 dseAdapter.restoreTrajectory(currentTrajectoryWithFitness.trajectory);
127 }
128 }
129
130 Collection<Activation> activations = dseAdapter.getUntraversedActivations();
131 Iterator<Activation> iterator = activations.iterator();
132
133
134
135 while (iterator.hasNext()) {
136 final Activation nextActivation = iterator.next();
137 if (!iterator.hasNext()) {
138 // Last untraversed activation of the state.
139 trajectoriesToExplore.remove(currentTrajectoryWithFitness);
140 }
141
142 // Executing new activation
143 dseAdapter.fireActivation(nextActivation);
144 if (dseAdapter.isCurrentStateAlreadyTraversed()) {
145 // The new state is already visited.
146 dseAdapter.backtrack();
147 } else if (!dseAdapter.checkGlobalConstraints()) {
148 // Global constraint is not satisfied.
149 dseAdapter.backtrack();
150 } else {
151 final Fitness nextFitness = dseAdapter.getFitness();
152 if (nextFitness.isSatisfiesHardObjectives()) {
153 dseAdapter.newSolution();
154 var solutions = dseAdapter.getSolutions().size();
155 if (solutions >= maxSolutions) {
156 return;
157 }
158 // Found a solution.
159 if (backTrackIfSolution) {
160 dseAdapter.backtrack();
161 continue;
162 }
163 }
164 if (dseAdapter.getDepth() >= maxDepth) {
165 // Reached max depth.
166 dseAdapter.backtrack();
167 continue;
168 }
169
170 TrajectoryWithFitness nextTrajectoryWithFitness = new TrajectoryWithFitness(
171 dseAdapter.getTrajectory(), nextFitness);
172 trajectoriesToExplore.add(nextTrajectoryWithFitness);
173
174 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness,
175 nextTrajectoryWithFitness.fitness);
176 if (compare < 0) {
177 // Better fitness, moving on
178 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
179 continue mainLoop;
180 } else if (compare == 0) {
181 if (onlyBetterFirst) {
182 // Equally good fitness, backtrack
183 dseAdapter.backtrack();
184 } else {
185 // Equally good fitness, moving on
186 currentTrajectoryWithFitness = nextTrajectoryWithFitness;
187 continue mainLoop;
188 }
189 } else {
190 //"Worse fitness
191 currentTrajectoryWithFitness = null;
192 continue mainLoop;
193 }
194 }
195 }
196
197 // State is fully traversed.
198 currentTrajectoryWithFitness = null;
199
200 }
201 // Interrupted.
202 }
203}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java
new file mode 100644
index 00000000..ea7fe43f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java
@@ -0,0 +1,113 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.strategy;
7
8import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
9import tools.refinery.store.dse.transition.ObjectiveValue;
10import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
11import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker;
12import tools.refinery.store.map.Version;
13import tools.refinery.store.model.Model;
14import tools.refinery.store.statecoding.StateCoderAdapter;
15
16
17import java.util.Random;
18
19public class BestFirstWorker {
20 final BestFirstStoreManager storeManager;
21 final Model model;
22 final ActivationStoreWorker activationStoreWorker;
23 final StateCoderAdapter stateCoderAdapter;
24 final DesignSpaceExplorationAdapter explorationAdapter;
25
26 public BestFirstWorker(BestFirstStoreManager storeManager, Model model) {
27 this.storeManager = storeManager;
28 this.model = model;
29
30 explorationAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
31 stateCoderAdapter = model.getAdapter(StateCoderAdapter.class);
32 activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(),
33 explorationAdapter.getTransformations());
34 }
35
36 private VersionWithObjectiveValue last = null;
37
38 //public boolean isIncluded
39
40 public SubmitResult submit() {
41 if (explorationAdapter.checkExclude()) {
42 last = null;
43 return new SubmitResult(false, false, null, null);
44 }
45
46 Version version = model.commit();
47 ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue();
48 var res = new VersionWithObjectiveValue(version, objectiveValue);
49 var code = stateCoderAdapter.calculateStateCode();
50 var accepted = explorationAdapter.checkAccept();
51
52 boolean isNew = storeManager.getEquivalenceClassStore().submit(res, code,
53 activationStoreWorker.calculateEmptyActivationSize(), accepted);
54
55 last = new VersionWithObjectiveValue(version, objectiveValue);
56 return new SubmitResult(isNew, accepted, objectiveValue, last);
57 }
58
59 public void restoreToLast() {
60 if (explorationAdapter.getModel().hasUncommittedChanges()) {
61 explorationAdapter.getModel().restore(last.version());
62 }
63 }
64
65 public VersionWithObjectiveValue restoreToBest() {
66 var bestVersion = storeManager.getObjectiveStore().getBest();
67 if (bestVersion != null) {
68 this.model.restore(bestVersion.version());
69 }
70 return bestVersion;
71 }
72
73 public VersionWithObjectiveValue restoreToRandom(Random random) {
74 var randomVersion = storeManager.getObjectiveStore().getRandom(random);
75 last = randomVersion;
76 if (randomVersion != null) {
77 this.model.restore(randomVersion.version());
78 }
79 return randomVersion;
80 }
81
82 public int compare(VersionWithObjectiveValue s1, VersionWithObjectiveValue s2) {
83 return storeManager.getObjectiveStore().getComparator().compare(s1, s2);
84 }
85
86 public boolean stateHasUnvisited() {
87 if (!model.hasUncommittedChanges()) {
88 return storeManager.getActivationStore().hasUnmarkedActivation(last);
89 } else {
90 throw new IllegalStateException("The model has uncommitted changes!");
91 }
92 }
93
94 record RandomVisitResult(SubmitResult submitResult, boolean shouldRetry) {
95 }
96
97 public RandomVisitResult visitRandomUnvisited(Random random) {
98 if (!model.hasUncommittedChanges()) {
99 var visitResult = activationStoreWorker.fireRandomActivation(this.last, random);
100 if (visitResult.successfulVisit()) {
101 return new RandomVisitResult(submit(), visitResult.mayHaveMore());
102 } else {
103 return new RandomVisitResult(null, visitResult.mayHaveMore());
104 }
105 } else {
106 throw new IllegalStateException("The model has uncommitted changes!");
107 }
108 }
109
110 public boolean hasEnoughSolution() {
111 return storeManager.solutionStore.hasEnoughSolution();
112 }
113}
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
deleted file mode 100644
index 0a0caa7e..00000000
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java
+++ /dev/null
@@ -1,92 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.strategy;
7
8import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
9import tools.refinery.store.dse.Strategy;
10import tools.refinery.store.dse.objectives.Fitness;
11
12public class DepthFirstStrategy implements Strategy {
13
14 private DesignSpaceExplorationAdapter dseAdapter;
15
16 private int maxDepth = Integer.MAX_VALUE;
17 private int maxSolutions = Integer.MAX_VALUE;
18 private boolean backtrackFromSolution = true;
19
20 public DepthFirstStrategy withDepthLimit(int maxDepth) {
21 if (maxDepth >= 0) {
22 this.maxDepth = maxDepth;
23 }
24 return this;
25 }
26
27 public DepthFirstStrategy withSolutionLimit(int maxSolutions) {
28 if (maxSolutions >= 0) {
29 this.maxSolutions = maxSolutions;
30 }
31 return this;
32 }
33
34 public DepthFirstStrategy continueIfHardObjectivesFulfilled() {
35 backtrackFromSolution = false;
36 return this;
37 }
38
39 @Override
40 public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) {
41 this.dseAdapter = designSpaceExplorationAdapter;
42 }
43
44 @Override
45 public void explore() {
46 if (maxSolutions == 0) {
47 return;
48 }
49 while (dseAdapter.getSolutions().size() < maxSolutions) {
50 if (!checkAndHandleGlobalConstraints()) {
51 return;
52 }
53
54 Fitness fitness = dseAdapter.getFitness();
55 if (fitness.isSatisfiesHardObjectives()) {
56 dseAdapter.newSolution();
57 if (backtrackFromSolution && !dseAdapter.backtrack()) {
58 return;
59 }
60 }
61
62 if (!checkAndHandleDepth()) {
63 return;
64 }
65
66 if (!backtrackToLastUntraversed()) {
67 return;
68 }
69
70 if (!dseAdapter.fireRandomActivation()) {
71 return;
72 }
73 }
74 }
75
76 private boolean checkAndHandleGlobalConstraints() {
77 return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack();
78 }
79
80 private boolean checkAndHandleDepth() {
81 return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack();
82 }
83
84 private boolean backtrackToLastUntraversed() {
85 while (dseAdapter.getUntraversedActivations().isEmpty()) {
86 if (!dseAdapter.backtrack()) {
87 return false;
88 }
89 }
90 return true;
91 }
92}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/SubmitResult.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/SubmitResult.java
new file mode 100644
index 00000000..37d548d7
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/SubmitResult.java
@@ -0,0 +1,14 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.strategy;
7
8import tools.refinery.store.dse.transition.ObjectiveValue;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.map.Version;
11
12public record SubmitResult(boolean include, boolean accepted, ObjectiveValue objective, VersionWithObjectiveValue newVersion) {
13
14 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationAdapter.java
new file mode 100644
index 00000000..37448309
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationAdapter.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.dse.transition.internal.DesignSpaceExplorationBuilderImpl;
10import tools.refinery.store.map.Version;
11import tools.refinery.store.tuple.Tuple;
12import tools.refinery.store.tuple.Tuple1;
13
14import java.util.Collection;
15import java.util.List;
16
17public interface DesignSpaceExplorationAdapter extends ModelAdapter {
18
19
20
21 @Override
22 DesignSpaceExplorationStoreAdapter getStoreAdapter();
23
24 static DesignSpaceExplorationBuilder builder() {
25 return new DesignSpaceExplorationBuilderImpl();
26 }
27 List<Transformation> getTransformations();
28 boolean checkAccept();
29 boolean checkExclude();
30 ObjectiveValue getObjectiveValue();
31}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java
new file mode 100644
index 00000000..3855a20a
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java
@@ -0,0 +1,59 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import tools.refinery.store.adapter.ModelAdapterBuilder;
9import tools.refinery.store.dse.transition.objectives.Criterion;
10import tools.refinery.store.dse.transition.objectives.Objective;
11
12import java.util.Collection;
13import java.util.List;
14
15public interface DesignSpaceExplorationBuilder extends ModelAdapterBuilder {
16
17 DesignSpaceExplorationBuilder transformation(TransformationRule transformationRuleDefinition);
18 default DesignSpaceExplorationBuilder transformations(TransformationRule... transformationRuleDefinitions) {
19 return transformations(List.of(transformationRuleDefinitions));
20 }
21
22 default DesignSpaceExplorationBuilder transformations(Collection<? extends TransformationRule> transformationRules) {
23 transformationRules.forEach(this::transformation);
24 return this;
25 }
26
27 DesignSpaceExplorationBuilder accept(Criterion criteria);
28
29 default DesignSpaceExplorationBuilder accept(Criterion... criteria) {
30 return accept(List.of(criteria));
31 }
32
33 default DesignSpaceExplorationBuilder accept(Collection<Criterion> criteria) {
34 criteria.forEach(this::accept);
35 return this;
36 }
37
38 DesignSpaceExplorationBuilder exclude(Criterion criteria);
39
40 default DesignSpaceExplorationBuilder exclude(Criterion... criteria) {
41 return exclude(List.of(criteria));
42 }
43
44 default DesignSpaceExplorationBuilder exclude(Collection<Criterion> criteria) {
45 criteria.forEach(this::exclude);
46 return this;
47 }
48
49 DesignSpaceExplorationBuilder objective(Objective objective);
50
51 default DesignSpaceExplorationBuilder objectives(Objective... objectives) {
52 return objectives(List.of(objectives));
53 }
54
55 default DesignSpaceExplorationBuilder objectives(Collection<? extends Objective> objectives) {
56 objectives.forEach(this::objective);
57 return this;
58 }
59}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java
new file mode 100644
index 00000000..5c8c7a4d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java
@@ -0,0 +1,27 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.dse.transition.objectives.Criterion;
10import tools.refinery.store.dse.transition.objectives.Objective;
11import tools.refinery.store.model.Model;
12
13import java.util.List;
14
15public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter
16{
17 @Override
18 DesignSpaceExplorationAdapter createModelAdapter(Model model);
19
20 List<TransformationRule> getTransformations();
21
22 List<Criterion> getAccepts();
23
24 List<Criterion> getExcludes();
25
26 List<Objective> getObjectives();
27}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValue.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValue.java
new file mode 100644
index 00000000..89ee61c8
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValue.java
@@ -0,0 +1,24 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8public interface ObjectiveValue {
9 double get(int index);
10 int getSize();
11
12 static ObjectiveValue of(double v1) {
13 return new ObjectiveValues.ObjectiveValue1(v1);
14 }
15
16 static ObjectiveValue of(double v1, double v2) {
17 return new ObjectiveValues.ObjectiveValue2(v1,v2);
18 }
19
20 static ObjectiveValue of(double[] v) {
21 return new ObjectiveValues.ObjectiveValueN(v);
22 }
23
24}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValues.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValues.java
new file mode 100644
index 00000000..60913ff3
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/ObjectiveValues.java
@@ -0,0 +1,69 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import java.util.Arrays;
9
10public interface ObjectiveValues {
11 public record ObjectiveValue1(double value0) implements ObjectiveValue {
12 @Override
13 public double get(int index) {
14 if(index == 0) return value0;
15 else throw new IllegalArgumentException("No value at " + index);
16 }
17
18 @Override
19 public int getSize() {
20 return 1;
21 }
22 }
23 public record ObjectiveValue2(double value0, double value1) implements ObjectiveValue {
24 @Override
25 public double get(int index) {
26 if(index == 0) return value0;
27 else if(index == 1) return value1;
28 else throw new IllegalArgumentException("No value at " + index);
29 }
30
31 @Override
32 public int getSize() {
33 return 2;
34 }
35 }
36 public record ObjectiveValueN(double[] values) implements ObjectiveValue {
37 @Override
38 public double get(int index) {
39 return values[index];
40 }
41
42 @Override
43 public int getSize() {
44 return values().length;
45 }
46
47 @Override
48 public boolean equals(Object o) {
49 if (this == o) return true;
50 if (o == null || getClass() != o.getClass()) return false;
51
52 ObjectiveValueN that = (ObjectiveValueN) o;
53
54 return Arrays.equals(values, that.values);
55 }
56
57 @Override
58 public int hashCode() {
59 return Arrays.hashCode(values);
60 }
61
62 @Override
63 public String toString() {
64 return "ObjectiveValueN{" +
65 "values=" + Arrays.toString(values) +
66 '}';
67 }
68 }
69}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java
new file mode 100644
index 00000000..2cce738f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java
@@ -0,0 +1,43 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import org.eclipse.collections.api.block.procedure.Procedure;
9import tools.refinery.store.query.resultset.OrderedResultSet;
10import tools.refinery.store.query.resultset.ResultSet;
11import tools.refinery.store.tuple.Tuple;
12
13public class Transformation {
14 private final TransformationRule definition;
15
16 private final OrderedResultSet<Boolean> activations;
17
18 private final Procedure<Tuple> action;
19
20 public Transformation(TransformationRule definition, OrderedResultSet<Boolean> activations, Procedure<Tuple> action) {
21 this.definition = definition;
22 this.activations = activations;
23 this.action = action;
24 }
25
26 public TransformationRule getDefinition() {
27 return definition;
28 }
29
30 public ResultSet<Boolean> getAllActivationsAsResultSet() {
31 return activations;
32 }
33
34 public Tuple getActivation(int index) {
35 return activations.getKey(index);
36 }
37
38 public boolean fireActivation(Tuple activation) {
39 action.accept(activation);
40 //queryEngine.flushChanges();
41 return true;
42 }
43}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java
new file mode 100644
index 00000000..d64a3db1
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java
@@ -0,0 +1,63 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.ModelQueryBuilder;
12import tools.refinery.store.query.dnf.RelationalQuery;
13import tools.refinery.store.dse.ActionFactory;
14import tools.refinery.store.query.resultset.OrderedResultSet;
15import tools.refinery.store.query.resultset.ResultSet;
16import tools.refinery.store.tuple.Tuple;
17
18import java.util.*;
19
20public class TransformationRule {
21
22 private final String name;
23 private final RelationalQuery precondition;
24 private final ActionFactory actionFactory;
25
26 private Random random;
27 private ModelQueryAdapter queryEngine;
28
29 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) {
30 this(name, precondition, actionFactory, new Random());
31 }
32
33 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) {
34 this(name, precondition, actionFactory, new Random(seed));
35 }
36
37 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, Random random) {
38 this.name = name;
39 this.precondition = precondition;
40 this.actionFactory = actionFactory;
41 this.random = random;
42 }
43 public void doConfigure(ModelStoreBuilder storeBuilder) {
44 var queryBuilder = storeBuilder.getAdapter(ModelQueryBuilder.class);
45 queryBuilder.query(this.precondition);
46 }
47
48 public Transformation prepare(Model model) {
49 var queryEngine = model.getAdapter(ModelQueryAdapter.class);
50 var activations = new OrderedResultSet<>(queryEngine.getResultSet(precondition));
51 var action = actionFactory.prepare(model);
52 return new Transformation(this,activations,action);
53 }
54
55 public String getName() {
56 return name;
57 }
58
59 public RelationalQuery getPrecondition() {
60 return precondition;
61 }
62
63}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/VersionWithObjectiveValue.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/VersionWithObjectiveValue.java
new file mode 100644
index 00000000..ca28e27f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/VersionWithObjectiveValue.java
@@ -0,0 +1,11 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition;
7
8import tools.refinery.store.map.Version;
9
10public record VersionWithObjectiveValue(Version version, ObjectiveValue objectiveValue) {
11}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationAdapterImpl.java
new file mode 100644
index 00000000..e1a29d40
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationAdapterImpl.java
@@ -0,0 +1,90 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.internal;
7
8import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
9import tools.refinery.store.dse.transition.DesignSpaceExplorationStoreAdapter;
10import tools.refinery.store.dse.transition.ObjectiveValue;
11import tools.refinery.store.dse.transition.Transformation;
12import tools.refinery.store.dse.transition.objectives.CriterionCalculator;
13import tools.refinery.store.dse.transition.objectives.ObjectiveCalculator;
14import tools.refinery.store.model.Model;
15
16import java.util.List;
17
18public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExplorationAdapter {
19 final Model model;
20 final DesignSpaceExplorationStoreAdapter designSpaceExplorationStoreAdapter;
21
22 final List<Transformation> transformations;
23 final List<CriterionCalculator> accepts;
24 final List<CriterionCalculator> excludes;
25 final List<ObjectiveCalculator> objectives;
26
27 public DesignSpaceExplorationAdapterImpl(Model model,
28 DesignSpaceExplorationStoreAdapter designSpaceExplorationStoreAdapter,
29 List<Transformation> transformations,
30 List<CriterionCalculator> accepts,
31 List<CriterionCalculator> excludes,
32 List<ObjectiveCalculator> objectives) {
33 this.model = model;
34 this.designSpaceExplorationStoreAdapter = designSpaceExplorationStoreAdapter;
35
36 this.transformations = transformations;
37 this.accepts = accepts;
38 this.excludes = excludes;
39 this.objectives = objectives;
40 }
41
42 @Override
43 public Model getModel() {
44 return model;
45 }
46
47 @Override
48 public DesignSpaceExplorationStoreAdapter getStoreAdapter() {
49 return designSpaceExplorationStoreAdapter;
50 }
51
52 public List<Transformation> getTransformations() {
53 return transformations;
54 }
55
56 @Override
57 public boolean checkAccept() {
58 for (var accept : this.accepts) {
59 if (!accept.isSatisfied()) {
60 return false;
61 }
62 }
63 return true;
64 }
65
66 @Override
67 public boolean checkExclude() {
68 for (var exclude : this.excludes) {
69 if (exclude.isSatisfied()) {
70 return true;
71 }
72 }
73 return false;
74 }
75
76 @Override
77 public ObjectiveValue getObjectiveValue() {
78 if (objectives.size() == 1) {
79 return ObjectiveValue.of(objectives.get(0).getValue());
80 } else if (objectives.size() == 2) {
81 return ObjectiveValue.of(objectives.get(0).getValue(), objectives.get(1).getValue());
82 } else {
83 double[] res = new double[objectives.size()];
84 for (int i = 0; i < objectives.size(); i++) {
85 res[i] = objectives.get(i).getValue();
86 }
87 return ObjectiveValue.of(res);
88 }
89 }
90}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java
new file mode 100644
index 00000000..4371cc03
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java
@@ -0,0 +1,75 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.internal;
7
8import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
9import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder;
10import tools.refinery.store.dse.transition.TransformationRule;
11import tools.refinery.store.dse.transition.objectives.Criterion;
12import tools.refinery.store.dse.transition.objectives.Objective;
13import tools.refinery.store.model.ModelStore;
14import tools.refinery.store.model.ModelStoreBuilder;
15
16import java.util.ArrayList;
17import java.util.LinkedHashSet;
18import java.util.List;
19
20public class DesignSpaceExplorationBuilderImpl
21 extends AbstractModelAdapterBuilder<DesignSpaceExplorationStoreAdapterImpl>
22 implements DesignSpaceExplorationBuilder {
23
24 LinkedHashSet<TransformationRule> transformationRuleDefinitions = new LinkedHashSet<>();
25 LinkedHashSet<Criterion> accepts = new LinkedHashSet<>();
26 LinkedHashSet<Criterion> excludes = new LinkedHashSet<>();
27 LinkedHashSet<Objective> objectives = new LinkedHashSet<>();
28
29 @Override
30 public DesignSpaceExplorationBuilder transformation(TransformationRule transformationRuleDefinition) {
31 transformationRuleDefinitions.add(transformationRuleDefinition);
32 return this;
33 }
34
35 @Override
36 public DesignSpaceExplorationBuilder accept(Criterion criteria) {
37 accepts.add(criteria);
38 return this;
39 }
40
41 @Override
42 public DesignSpaceExplorationBuilder exclude(Criterion criteria) {
43 excludes.add(criteria);
44 return this;
45 }
46
47
48 @Override
49 public DesignSpaceExplorationBuilder objective(Objective objective) {
50 objectives.add(objective);
51 return this;
52 }
53
54 @Override
55 protected void doConfigure(ModelStoreBuilder storeBuilder) {
56 transformationRuleDefinitions.forEach(x -> x.doConfigure(storeBuilder));
57 accepts.forEach(x -> x.doConfigure(storeBuilder));
58 excludes.forEach(x -> x.doConfigure(storeBuilder));
59 objectives.forEach(x -> x.doConfigure(storeBuilder));
60
61 super.doConfigure(storeBuilder);
62 }
63
64 @Override
65 protected DesignSpaceExplorationStoreAdapterImpl doBuild(ModelStore store) {
66 List<TransformationRule> transformationRuleDefinitiions1 = new ArrayList<>(transformationRuleDefinitions);
67 List<Criterion> accepts1 = new ArrayList<>(accepts);
68 List<Criterion> excludes1 = new ArrayList<>(excludes);
69 List<Objective> objectives1 = new ArrayList<>(objectives);
70
71 return new DesignSpaceExplorationStoreAdapterImpl(store,
72 transformationRuleDefinitiions1, accepts1,
73 excludes1, objectives1);
74 }
75}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java
new file mode 100644
index 00000000..3319e148
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java
@@ -0,0 +1,70 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.internal;
7
8import tools.refinery.store.dse.transition.DesignSpaceExplorationStoreAdapter;
9import tools.refinery.store.dse.transition.Transformation;
10import tools.refinery.store.dse.transition.TransformationRule;
11import tools.refinery.store.dse.transition.objectives.Criterion;
12import tools.refinery.store.dse.transition.objectives.CriterionCalculator;
13import tools.refinery.store.dse.transition.objectives.Objective;
14import tools.refinery.store.dse.transition.objectives.ObjectiveCalculator;
15import tools.refinery.store.model.Model;
16import tools.refinery.store.model.ModelStore;
17
18import java.util.List;
19
20public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter {
21 protected final ModelStore store;
22
23 protected final List<TransformationRule> transformationRuleDefinitions;
24 protected final List<Criterion> accepts;
25 protected final List<Criterion> excludes;
26 protected final List<Objective> objectives;
27
28 public DesignSpaceExplorationStoreAdapterImpl(ModelStore store,
29 List<TransformationRule> transformationRuleDefinitions,
30 List<Criterion> accepts, List<Criterion> excludes,
31 List<Objective> objectives) {
32 this.store = store;
33
34 this.transformationRuleDefinitions = transformationRuleDefinitions;
35 this.accepts = accepts;
36 this.excludes = excludes;
37 this.objectives = objectives;
38 }
39
40 @Override
41 public ModelStore getStore() {
42 return store;
43 }
44
45 @Override
46 public DesignSpaceExplorationAdapterImpl createModelAdapter(Model model) {
47 final List<Transformation> t = this.transformationRuleDefinitions.stream().map(x->x.prepare(model)).toList();
48 final List<CriterionCalculator> a = this.accepts.stream().map(x->x.createCalculator(model)).toList();
49 final List<CriterionCalculator> e = this.excludes.stream().map(x->x.createCalculator(model)).toList();
50 final List<ObjectiveCalculator> o = this.objectives.stream().map(x->x.createCalculator(model)).toList();
51
52 return new DesignSpaceExplorationAdapterImpl(model, this, t, a, e, o);
53 }
54 @Override
55 public List<TransformationRule> getTransformations() {
56 return transformationRuleDefinitions;
57 }
58 @Override
59 public List<Criterion> getAccepts() {
60 return accepts;
61 }
62 @Override
63 public List<Criterion> getExcludes() {
64 return excludes;
65 }
66 @Override
67 public List<Objective> getObjectives() {
68 return objectives;
69 }
70}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java
new file mode 100644
index 00000000..66ca6f5e
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10
11public interface Criterion {
12 default void doConfigure(ModelStoreBuilder storeBuilder) {
13 }
14 CriterionCalculator createCalculator(Model model);
15}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/CriterionCalculator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/CriterionCalculator.java
new file mode 100644
index 00000000..944ffed6
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/CriterionCalculator.java
@@ -0,0 +1,10 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8public interface CriterionCalculator {
9 boolean isSatisfied();
10}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java
new file mode 100644
index 00000000..b5924455
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10
11public interface Objective {
12 default void doConfigure(ModelStoreBuilder storeBuilder) {
13 }
14 ObjectiveCalculator createCalculator(Model model);
15}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/ObjectiveCalculator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/ObjectiveCalculator.java
new file mode 100644
index 00000000..f01b8de9
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/ObjectiveCalculator.java
@@ -0,0 +1,10 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8public interface ObjectiveCalculator {
9 double getValue();
10}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java
new file mode 100644
index 00000000..e2260cca
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java
@@ -0,0 +1,44 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.ModelQueryBuilder;
12import tools.refinery.store.query.dnf.AnyQuery;
13
14public class QueryCriteria implements Criterion {
15 protected final boolean acceptIfHasMatch;
16 protected final AnyQuery query;
17
18 /**
19 * Criteria based on the existence of matches evaluated on the model.
20 * @param query The query evaluated on the model.
21 * @param acceptIfHasMatch If true, the criteria satisfied if the query has any match on the model. Otherwise,
22 * the criteria satisfied if the query has no match on the model.
23 */
24 public QueryCriteria(AnyQuery query, boolean acceptIfHasMatch) {
25 this.query = query;
26 this.acceptIfHasMatch = acceptIfHasMatch;
27 }
28
29 @Override
30 public CriterionCalculator createCalculator(Model model) {
31 var resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(query);
32 if(acceptIfHasMatch) {
33 return () -> resultSet.size() > 0;
34 } else {
35 return () -> resultSet.size() == 0;
36 }
37 }
38
39 @Override
40 public void doConfigure(ModelStoreBuilder storeBuilder) {
41 Criterion.super.doConfigure(storeBuilder);
42 storeBuilder.getAdapter(ModelQueryBuilder.class).query(query);
43 }
44}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java
new file mode 100644
index 00000000..dfddccfc
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java
@@ -0,0 +1,44 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.objectives;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.query.ModelQueryAdapter;
11import tools.refinery.store.query.ModelQueryBuilder;
12import tools.refinery.store.query.dnf.FunctionalQuery;
13
14public class QueryObjective implements Objective {
15 protected final FunctionalQuery<? extends Number> objectiveFunction;
16
17 public QueryObjective(FunctionalQuery<? extends Number> objectiveFunction) {
18 this.objectiveFunction = objectiveFunction;
19 }
20
21 @Override
22 public ObjectiveCalculator createCalculator(Model model) {
23 var resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(objectiveFunction);
24 return () -> {
25 var cursor = resultSet.getAll();
26 boolean hasElement = cursor.move();
27 if(hasElement) {
28 double result = cursor.getValue().doubleValue();
29 if(cursor.move()) {
30 throw new IllegalStateException("Query providing the objective function has multiple values!");
31 }
32 return result;
33 } else {
34 throw new IllegalStateException("Query providing the objective function has no values!");
35 }
36 };
37 }
38
39 @Override
40 public void doConfigure(ModelStoreBuilder storeBuilder) {
41 Objective.super.doConfigure(storeBuilder);
42 storeBuilder.getAdapter(ModelQueryBuilder.class).query(objectiveFunction);
43 }
44}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ActivationStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ActivationStore.java
new file mode 100644
index 00000000..52e0611d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ActivationStore.java
@@ -0,0 +1,18 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.map.Version;
10
11import java.util.Random;
12
13public interface ActivationStore {
14 record VisitResult(boolean successfulVisit, boolean mayHaveMore, int transformation, int activation) { }
15 VisitResult markNewAsVisited(VersionWithObjectiveValue to, int[] emptyEntrySizes);
16 boolean hasUnmarkedActivation(VersionWithObjectiveValue version);
17 VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random);
18}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java
new file mode 100644
index 00000000..bbe26fe5
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java
@@ -0,0 +1,16 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.statecoding.StateCoderResult;
10
11public interface EquivalenceClassStore {
12 boolean submit(VersionWithObjectiveValue version, StateCoderResult stateCoderResult, int[] emptyActivations, boolean accept);
13 boolean hasUnresolvedSymmetry();
14 void resolveOneSymmetry();
15 int getNumberOfUnresolvedSymmetries();
16}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ObjectivePriorityQueue.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ObjectivePriorityQueue.java
new file mode 100644
index 00000000..df72c343
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/ObjectivePriorityQueue.java
@@ -0,0 +1,21 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.map.Version;
10
11import java.util.Comparator;
12import java.util.Random;
13
14public interface ObjectivePriorityQueue {
15 Comparator<VersionWithObjectiveValue> getComparator();
16 void submit(VersionWithObjectiveValue versionWithObjectiveValue);
17 void remove(VersionWithObjectiveValue versionWithObjectiveValue);
18 int getSize();
19 VersionWithObjectiveValue getBest();
20 VersionWithObjectiveValue getRandom(Random random);
21}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/SolutionStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/SolutionStore.java
new file mode 100644
index 00000000..d1bfaa79
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/SolutionStore.java
@@ -0,0 +1,17 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9
10import java.util.List;
11import java.util.concurrent.Future;
12
13public interface SolutionStore {
14 boolean submit(VersionWithObjectiveValue version);
15 List<VersionWithObjectiveValue> getSolutions();
16 boolean hasEnoughSolution();
17}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java
new file mode 100644
index 00000000..8466a0f3
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java
@@ -0,0 +1,47 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
10import tools.refinery.store.statecoding.StateCoderResult;
11import tools.refinery.store.statecoding.StateCoderStoreAdapter;
12
13public abstract class AbstractEquivalenceClassStore implements EquivalenceClassStore {
14 protected final StateCoderStoreAdapter stateCoderStoreAdapter;
15 AbstractEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) {
16 this.stateCoderStoreAdapter = stateCoderStoreAdapter;
17 }
18
19 protected int numberOfUnresolvedSymmetries = 0;
20
21 protected abstract void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept);
22 protected abstract boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion,
23 int[] emptyActivations, boolean accept);
24
25 @Override
26 public synchronized boolean submit(VersionWithObjectiveValue version, StateCoderResult stateCoderResult,
27 int[] emptyActivations, boolean accept) {
28 boolean hasNewVersion = tryToAdd(stateCoderResult, version, emptyActivations, accept);
29 if (hasNewVersion) {
30 delegate(version, emptyActivations, accept);
31 return true;
32 } else {
33 numberOfUnresolvedSymmetries++;
34 return false;
35 }
36 }
37
38 @Override
39 public boolean hasUnresolvedSymmetry() {
40 return numberOfUnresolvedSymmetries > 0;
41 }
42
43 @Override
44 public int getNumberOfUnresolvedSymmetries() {
45 return numberOfUnresolvedSymmetries;
46 }
47}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreBitVectorEntry.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreBitVectorEntry.java
new file mode 100644
index 00000000..ba243d7d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreBitVectorEntry.java
@@ -0,0 +1,46 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8public class ActivationStoreBitVectorEntry extends ActivationStoreEntry {
9 final int[] selected;
10
11 ActivationStoreBitVectorEntry(int numberOfActivations) {
12 super(numberOfActivations);
13 this.selected = new int[(numberOfActivations / Integer.SIZE) + 1];
14 }
15
16 @Override
17 public int getNumberOfUnvisitedActivations() {
18 int visited = 0;
19 for (int i : selected) {
20 visited += Integer.bitCount(i);
21 }
22 return visited;
23 }
24
25 private static final int ELEMENT_POSITION = 5; // size of Integer.SIZE
26 private static final int ELEMENT_BITMASK = (1<<ELEMENT_POSITION)-1;
27 @Override
28 public int getAndAddActivationAfter(int index) {
29 int position = index;
30 do {
31 final int selectedElement = position >> ELEMENT_POSITION;
32 final int selectedBit = position & ELEMENT_BITMASK;
33 if((selected[selectedElement] & selectedBit) == 0) {
34 selected[selectedElement] |= selectedBit;
35 return position;
36 } else {
37 if(position < this.numberOfActivations) {
38 position++;
39 } else {
40 position = 0;
41 }
42 }
43 } while(position != index);
44 throw new IllegalArgumentException("There is are no unvisited activations!");
45 }
46}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreEntry.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreEntry.java
new file mode 100644
index 00000000..f69b234c
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreEntry.java
@@ -0,0 +1,32 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8public abstract class ActivationStoreEntry {
9 protected final int numberOfActivations;
10
11 ActivationStoreEntry(int numberOfActivations) {
12 this.numberOfActivations = numberOfActivations;
13 }
14
15 public int getNumberOfVisitedActivations() {
16 return numberOfActivations;
17 }
18
19 public abstract int getNumberOfUnvisitedActivations();
20 public abstract int getAndAddActivationAfter(int index);
21
22 // public abstract boolean contains(int activation)
23 // public abstract boolean add(int activation)
24
25 public static ActivationStoreEntry create(int size) {
26 if(size <= Integer.SIZE*6) {
27 return new ActivationStoreBitVectorEntry(size);
28 } else {
29 return new ActivationStoreListEntry(size);
30 }
31 }
32}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java
new file mode 100644
index 00000000..1229ec15
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java
@@ -0,0 +1,131 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import org.eclipse.collections.api.block.procedure.Procedure;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.statespace.ActivationStore;
11
12import java.util.*;
13
14public class ActivationStoreImpl implements ActivationStore {
15 final int numberOfTransformations;
16 final Procedure<VersionWithObjectiveValue> actionWhenAllActivationVisited;
17 final Map<VersionWithObjectiveValue, List<ActivationStoreEntry>> versionToActivations;
18
19 public ActivationStoreImpl(final int numberOfTransformations,
20 Procedure<VersionWithObjectiveValue> actionWhenAllActivationVisited) {
21 this.numberOfTransformations = numberOfTransformations;
22 this.actionWhenAllActivationVisited = actionWhenAllActivationVisited;
23 versionToActivations = new HashMap<>();
24 }
25
26 public synchronized VisitResult markNewAsVisited(VersionWithObjectiveValue to, int[] emptyEntrySizes) {
27 boolean[] successful = new boolean[]{false};
28 var entries = versionToActivations.computeIfAbsent(to, x -> {
29 successful[0] = true;
30 List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length);
31 for(int emptyEntrySize : emptyEntrySizes) {
32 result.add(ActivationStoreListEntry.create(emptyEntrySize));
33 }
34 return result;
35 });
36 boolean hasMore = false;
37 for (var entry : entries) {
38 if (entry.getNumberOfUnvisitedActivations() > 0) {
39 hasMore = true;
40 break;
41 }
42 }
43 if(!hasMore) {
44 actionWhenAllActivationVisited.accept(to);
45 }
46 return new VisitResult(successful[0], hasMore, -1, -1);
47 }
48
49 public synchronized VisitResult visitActivation(VersionWithObjectiveValue from, int transformationIndex, int activationIndex) {
50 var entries = versionToActivations.get(from);
51 var entry = entries.get(transformationIndex);
52 final int unvisited = entry.getNumberOfUnvisitedActivations();
53
54 final boolean successfulVisit = unvisited > 0;
55 final boolean hasMoreInActivation = unvisited > 1;
56 final boolean hasMore;
57 final int transformation;
58 final int activation;
59
60 if (successfulVisit) {
61 transformation = transformationIndex;
62 activation = entry.getAndAddActivationAfter(activationIndex);
63
64 } else {
65 transformation = -1;
66 activation = -1;
67 }
68
69 if(hasMoreInActivation) {
70 boolean hasMoreInOtherTransformation = false;
71 for (var e : entries) {
72 if (e != entry && e.getNumberOfVisitedActivations() > 0) {
73 hasMoreInOtherTransformation = true;
74 break;
75 }
76 }
77 hasMore = hasMoreInOtherTransformation;
78 } else {
79 hasMore = true;
80 }
81
82 if(!hasMore) {
83 actionWhenAllActivationVisited.accept(from);
84 }
85
86 return new VisitResult(false, hasMore, transformation, activation);
87 }
88
89 @Override
90 public synchronized boolean hasUnmarkedActivation(VersionWithObjectiveValue version) {
91 var entries = versionToActivations.get(version);
92 boolean hasMore = false;
93 for (var entry : entries) {
94 if (entry.getNumberOfUnvisitedActivations() > 0) {
95 hasMore = true;
96 break;
97 }
98 }
99 return hasMore;
100 }
101
102 @Override
103 public synchronized VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random) {
104 var entries = versionToActivations.get(version);
105
106 int sum1 = 0;
107 for (var entry : entries) {
108 sum1 += entry.getNumberOfUnvisitedActivations();
109 }
110
111 int selected = random.nextInt(sum1);
112 int sum2 = 0;
113 int transformation = 0;
114 int activation = -1;
115 for (; transformation < entries.size(); transformation++) {
116 var entry = entries.get(transformation);
117 int unvisited = entry.getNumberOfUnvisitedActivations();
118 if (selected < sum2 + unvisited) {
119 activation = sum2 + unvisited - selected;
120 break;
121 } else {
122 sum2 += unvisited;
123 }
124 }
125 if (activation == -1) {
126 throw new IllegalArgumentException("no unvisited");
127 }
128
129 return this.visitActivation(version, transformation, activation);
130 }
131}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreListEntry.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreListEntry.java
new file mode 100644
index 00000000..9e25301f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreListEntry.java
@@ -0,0 +1,95 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import org.eclipse.collections.impl.list.mutable.primitive.IntArrayList;
9
10public class ActivationStoreListEntry extends ActivationStoreEntry {
11 IntArrayList visitedActivations;
12
13 ActivationStoreListEntry(int numberOfActivations) {
14 super(numberOfActivations);
15 visitedActivations = new IntArrayList();
16 }
17
18 @Override
19 public int getNumberOfUnvisitedActivations() {
20 return this.numberOfActivations - visitedActivations.size();
21 }
22
23 @Override
24 public int getAndAddActivationAfter(int index) {
25 // If it is empty, just add it.
26 if(this.visitedActivations.isEmpty()) {
27 this.visitedActivations.add(index);
28 return index;
29 }
30
31 int position = getPosition(index);
32
33 // If the index is not in the position, one can insert it
34 if(this.visitedActivations.get(position) != index) {
35 this.visitedActivations.addAtIndex(position,index);
36 return index;
37 }
38
39 // Otherwise, get the next empty space between two elements
40 while(position + 2 < this.visitedActivations.size()) {
41 position++;
42 if(this.visitedActivations.get(position+1)-this.visitedActivations.get(position) > 1) {
43 this.visitedActivations.addAtIndex(position+1, this.visitedActivations.get(position+1)+1);
44 }
45 }
46
47 // Otherwise, try to add to the last space
48 int last = this.visitedActivations.get(this.visitedActivations.size()-1);
49 if(last<this.numberOfActivations) {
50 this.visitedActivations.add(last+1);
51 return last+1;
52 }
53
54 // Otherwise, try to put to the beginning
55 if(this.visitedActivations.get(0) > 0) {
56 this.visitedActivations.add(0);
57 return 0;
58 }
59
60 // Otherwise, get the next empty space between two elements
61 position = 0;
62 while(position + 2 < this.visitedActivations.size()) {
63 position++;
64 if(this.visitedActivations.get(position+1)-this.visitedActivations.get(position) > 1) {
65 this.visitedActivations.addAtIndex(position+1, this.visitedActivations.get(position+1)+1);
66 }
67 }
68
69 throw new IllegalArgumentException("There is are no unvisited activations!");
70 }
71
72 /**
73 * Returns the position of an index in the {@code visitedActivations}. If the collection contains the index, in
74 * returns its position, otherwise, it returns the position where the index need to be put.
75 *
76 * @param index Index of an activation.
77 * @return The position of the index.
78 */
79 private int getPosition(int index) {
80 int left = 0;
81 int right = this.visitedActivations.size() - 1;
82 while (left <= right) {
83 final int middle = (right - left) / 2 + left;
84 final int middleElement = visitedActivations.get(middle);
85 if(middleElement == index) {
86 return middle;
87 } else if(middleElement < index) {
88 left = middle +1;
89 } else{
90 right = middle-1;
91 }
92 }
93 return right+1;
94 }
95}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java
new file mode 100644
index 00000000..e05f5122
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java
@@ -0,0 +1,56 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import tools.refinery.store.dse.transition.Transformation;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.statespace.ActivationStore;
11import tools.refinery.store.map.Version;
12
13import java.util.List;
14import java.util.Random;
15
16public class ActivationStoreWorker {
17 final ActivationStore store;
18 final List<Transformation> transformations;
19
20 public ActivationStoreWorker(ActivationStore store, List<Transformation> transformations) {
21 this.store = store;
22 this.transformations = transformations;
23 }
24
25 public int[] calculateEmptyActivationSize() {
26 int[] result = new int[transformations.size()];
27 for (int i = 0; i < result.length; i++) {
28 result[i] = transformations.get(i).getAllActivationsAsResultSet().size();
29 }
30 return result;
31 }
32
33
34 public ActivationStore.VisitResult fireRandomActivation(VersionWithObjectiveValue thisVersion, Random random) {
35 var result = store.getRandomAndMarkAsVisited(thisVersion, random);
36 if(result.successfulVisit()) {
37 int selectedTransformation = result.transformation();
38 int selectedActivation = result.activation();
39
40 Transformation transformation = transformations.get(selectedTransformation);
41 var tuple = transformation.getActivation(selectedActivation);
42
43 boolean success = transformation.fireActivation(tuple);
44 if(success) {
45 return result;
46 } else {
47 return new ActivationStore.VisitResult(
48 false,
49 result.mayHaveMore(),
50 selectedActivation,
51 selectedActivation);
52 }
53 }
54 return result;
55 }
56}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/CompleteEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/CompleteEquivalenceClassStore.java
new file mode 100644
index 00000000..1555c3be
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/CompleteEquivalenceClassStore.java
@@ -0,0 +1,107 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.statespace.ActivationStore;
11import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue;
12import tools.refinery.store.dse.transition.statespace.SolutionStore;
13import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
14import tools.refinery.store.statecoding.StateCoderResult;
15import tools.refinery.store.statecoding.StateCoderStoreAdapter;
16import tools.refinery.store.statecoding.StateEquivalenceChecker;
17
18import java.util.ArrayList;
19
20public abstract class CompleteEquivalenceClassStore extends AbstractEquivalenceClassStore implements EquivalenceClassStore {
21
22 static class SymmetryStoreArray extends ArrayList<VersionWithObjectiveValue> {
23 final int[] activationSizes;
24 final boolean accept;
25
26 SymmetryStoreArray(int[] activationSizes, boolean accept) {
27 super();
28 this.activationSizes = activationSizes;
29 this.accept = accept;
30 }
31 }
32
33 final IntObjectHashMap<Object> modelCode2Versions;
34
35 protected CompleteEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) {
36 super(stateCoderStoreAdapter);
37 this.modelCode2Versions = new IntObjectHashMap<>();
38 }
39
40 @Override
41 protected boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion,
42 int[] emptyActivations, boolean accept) {
43 int modelCode = stateCoderResult.modelCode();
44 Object old = modelCode2Versions.updateValue(
45 modelCode,
46 () -> newVersion,
47 x -> {
48 if (x instanceof SymmetryStoreArray array) {
49 if(array.accept != accept || array.activationSizes != emptyActivations) {
50 this.delegate(newVersion,emptyActivations,accept);
51 return x;
52 }
53 array.add(newVersion);
54 return array;
55 } else {
56 SymmetryStoreArray result = new SymmetryStoreArray(emptyActivations, accept);
57 result.add((VersionWithObjectiveValue) x);
58 result.add(newVersion);
59 return result;
60 }
61 });
62 return old == null;
63 }
64
65 @Override
66 public void resolveOneSymmetry() {
67 var unresolvedSimilarity = getOneUnresolvedSymmetry();
68 if (unresolvedSimilarity == null) {
69 return;
70 }
71 var outcome = this.stateCoderStoreAdapter.checkEquivalence(unresolvedSimilarity.get(0),
72 unresolvedSimilarity.get(1));
73 if (outcome != StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC) {
74 delegate(unresolvedSimilarity.get(1), unresolvedSimilarity.activationSizes, unresolvedSimilarity.accept);
75 }
76 }
77
78 //record UnresolvedSymmetryResult
79
80 private synchronized SymmetryStoreArray getOneUnresolvedSymmetry() {
81 if (numberOfUnresolvedSymmetries <= 0) {
82 return null;
83 }
84
85 for (var entry : modelCode2Versions.keyValuesView()) {
86 int hash = entry.getOne();
87 var value = entry.getTwo();
88 if (value instanceof SymmetryStoreArray array) {
89 int size = array.size();
90 var representative = array.get(0);
91 var similar = array.get(size - 1);
92 array.remove(size - 1);
93
94 if (size <= 2) {
95 modelCode2Versions.put(hash, representative);
96 }
97
98 var result = new SymmetryStoreArray(array.activationSizes, array.accept);
99 result.add(representative);
100 result.add(similar);
101 return result;
102 }
103 }
104
105 return null;
106 }
107}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java
new file mode 100644
index 00000000..75e117c0
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java
@@ -0,0 +1,32 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
11import tools.refinery.store.statecoding.StateCoderResult;
12import tools.refinery.store.statecoding.StateCoderStoreAdapter;
13
14public abstract class FastEquivalenceClassStore extends AbstractEquivalenceClassStore implements EquivalenceClassStore {
15
16 final IntHashSet codes;
17
18 public FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) {
19 super(stateCoderStoreAdapter);
20 this.codes = new IntHashSet();
21 }
22
23 @Override
24 protected boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, int[] emptyActivations, boolean accept) {
25 return this.codes.add(stateCoderResult.modelCode());
26 }
27
28 @Override
29 public void resolveOneSymmetry() {
30 throw new IllegalArgumentException("This equivalence storage is not prepared to resolve symmetries!");
31 }
32}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java
new file mode 100644
index 00000000..249b22da
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java
@@ -0,0 +1,74 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import tools.refinery.store.dse.transition.ObjectiveValues;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.objectives.Objective;
11import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue;
12import tools.refinery.store.map.Version;
13
14import java.util.Comparator;
15import java.util.List;
16import java.util.PriorityQueue;
17import java.util.Random;
18
19public class ObjectivePriorityQueueImpl implements ObjectivePriorityQueue {
20 public static final Comparator<VersionWithObjectiveValue> c1 = (o1, o2) -> Double.compare(
21 ((ObjectiveValues.ObjectiveValue1) o1.objectiveValue()).value0(),
22 ((ObjectiveValues.ObjectiveValue1) o2.objectiveValue()).value0());
23 // TODO: support multi objective!
24 final PriorityQueue<VersionWithObjectiveValue> priorityQueue;
25
26 public ObjectivePriorityQueueImpl(List<Objective> objectives) {
27
28 if(objectives.size() == 1) {
29 this.priorityQueue = new PriorityQueue<>(c1);
30 } else {
31 throw new UnsupportedOperationException("Only single objective comparator is implemented currently!");
32 }
33 }
34 @Override
35 public Comparator<VersionWithObjectiveValue> getComparator() {
36 return c1;
37 }
38
39 @Override
40 public void submit(VersionWithObjectiveValue versionWithObjectiveValue) {
41 priorityQueue.add(versionWithObjectiveValue);
42 }
43
44 @Override
45 public void remove(VersionWithObjectiveValue versionWithObjectiveValue) {
46 priorityQueue.remove(versionWithObjectiveValue);
47 }
48
49 @Override
50 public int getSize() {
51 return priorityQueue.size();
52 }
53
54 @Override
55 public VersionWithObjectiveValue getBest() {
56 var best = priorityQueue.peek();
57 if (best != null) {
58 return best;
59 } else {
60 throw new IllegalArgumentException("The objective store is empty!");
61 }
62 }
63
64 @Override
65 public VersionWithObjectiveValue getRandom(Random random) {
66 int randomPosition = random.nextInt(getSize());
67 for (VersionWithObjectiveValue entry : this.priorityQueue) {
68 if (randomPosition-- == 0) {
69 return entry;
70 }
71 }
72 throw new IllegalStateException("The priority queue is inconsistent!");
73 }
74}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java
new file mode 100644
index 00000000..cc48864f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java
@@ -0,0 +1,53 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.dse.transition.statespace.SolutionStore;
10
11import java.util.ArrayList;
12import java.util.List;
13import java.util.SortedSet;
14import java.util.TreeSet;
15
16public class SolutionStoreImpl implements SolutionStore {
17 final int maxNumberSolutions;
18 public static final int UNLIMITED = -1;
19 final SortedSet<VersionWithObjectiveValue> solutions;
20
21 public SolutionStoreImpl(int maxNumberSolutions) {
22 this.maxNumberSolutions = maxNumberSolutions;
23 solutions = new TreeSet<>(ObjectivePriorityQueueImpl.c1);
24 }
25
26
27 @Override
28 public synchronized boolean submit(VersionWithObjectiveValue version) {
29 boolean removeLast = hasEnoughSolution();
30 solutions.add(version);
31 if(removeLast) {
32 var last = solutions.last();
33 solutions.remove(last);
34 return last != version;
35 } else {
36 return true;
37 }
38 }
39
40 @Override
41 public List<VersionWithObjectiveValue> getSolutions() {
42 return new ArrayList<>(solutions);
43 }
44
45 @Override
46 public boolean hasEnoughSolution() {
47 if (maxNumberSolutions == UNLIMITED) {
48 return false;
49 } else {
50 return solutions.size() >= maxNumberSolutions;
51 }
52 }
53}
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 225de32e..b0b416e1 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
@@ -8,13 +8,13 @@ package tools.refinery.store.dse;
8import org.junit.jupiter.api.Disabled; 8import org.junit.jupiter.api.Disabled;
9import org.junit.jupiter.api.Test; 9import org.junit.jupiter.api.Test;
10import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; 10import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective;
11import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
11import tools.refinery.store.model.ModelStore; 12import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.query.ModelQueryAdapter; 13import tools.refinery.store.query.ModelQueryAdapter;
13import tools.refinery.store.query.dnf.Query; 14import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.dnf.RelationalQuery; 15import tools.refinery.store.query.dnf.RelationalQuery;
15import tools.refinery.store.dse.internal.TransformationRule; 16import tools.refinery.store.dse.transition.TransformationRule;
16import tools.refinery.store.dse.strategy.BestFirstStrategy; 17import tools.refinery.store.dse.strategy.BestFirstStrategy;
17import tools.refinery.store.dse.strategy.DepthFirstStrategy;
18import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; 18import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
19import tools.refinery.store.query.view.AnySymbolView; 19import tools.refinery.store.query.view.AnySymbolView;
20import tools.refinery.store.query.view.KeyOnlyView; 20import tools.refinery.store.query.view.KeyOnlyView;
@@ -282,5 +282,5 @@ class CRAExamplesTest {
282 var states = dseAdapter.explore(); 282 var states = dseAdapter.explore();
283 System.out.println("states size: " + states.size()); 283 System.out.println("states size: " + states.size());
284 } 284 }
285 285*/
286} 286}
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 c6da896c..461d9353 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
@@ -8,11 +8,11 @@ package tools.refinery.store.dse;
8import org.junit.jupiter.api.Disabled; 8import org.junit.jupiter.api.Disabled;
9import org.junit.jupiter.api.Test; 9import org.junit.jupiter.api.Test;
10import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; 10import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective;
11import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
11import tools.refinery.store.model.ModelStore; 12import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.query.ModelQueryAdapter; 13import tools.refinery.store.query.ModelQueryAdapter;
13import tools.refinery.store.query.dnf.Query; 14import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.dse.internal.TransformationRule; 15import tools.refinery.store.dse.transition.TransformationRule;
15import tools.refinery.store.dse.strategy.BestFirstStrategy;
16import tools.refinery.store.dse.strategy.DepthFirstStrategy; 16import tools.refinery.store.dse.strategy.DepthFirstStrategy;
17import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; 17import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
18import tools.refinery.store.query.view.AnySymbolView; 18import tools.refinery.store.query.view.AnySymbolView;
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 91e33f4a..083f7ec3 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
@@ -6,10 +6,11 @@
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.transition.DesignSpaceExplorationAdapter;
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;
12import tools.refinery.store.dse.internal.TransformationRule; 13import tools.refinery.store.dse.transition.TransformationRule;
13import tools.refinery.store.dse.strategy.BestFirstStrategy; 14import tools.refinery.store.dse.strategy.BestFirstStrategy;
14import tools.refinery.store.dse.strategy.DepthFirstStrategy; 15import tools.refinery.store.dse.strategy.DepthFirstStrategy;
15import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; 16import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
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 5d24d712..1672b63a 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
@@ -7,10 +7,11 @@ package 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.dse.strategy.DepthFirstStrategy;
10import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
10import tools.refinery.store.model.ModelStore; 11import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.query.ModelQueryAdapter; 12import tools.refinery.store.query.ModelQueryAdapter;
12import tools.refinery.store.query.dnf.Query; 13import tools.refinery.store.query.dnf.Query;
13import tools.refinery.store.dse.internal.TransformationRule; 14import tools.refinery.store.dse.transition.TransformationRule;
14import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; 15import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
15import tools.refinery.store.query.view.AnySymbolView; 16import tools.refinery.store.query.view.AnySymbolView;
16import tools.refinery.store.query.view.KeyOnlyView; 17import tools.refinery.store.query.view.KeyOnlyView;
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/statespace/internal/ActivationUnitTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/statespace/internal/ActivationUnitTest.java
new file mode 100644
index 00000000..e7960a06
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/statespace/internal/ActivationUnitTest.java
@@ -0,0 +1,72 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import org.junit.jupiter.api.Assertions;
9import org.junit.jupiter.params.ParameterizedTest;
10import org.junit.jupiter.params.provider.MethodSource;
11
12import java.util.stream.Stream;
13
14class ActivationUnitTest {
15 private final static int SMALL_SIZE = 5;
16
17 private static Stream<ActivationStoreEntry> entries() {
18 return Stream.of(
19 new ActivationStoreBitVectorEntry(SMALL_SIZE),
20 new ActivationStoreListEntry(SMALL_SIZE));
21 }
22
23 void addTest(ActivationStoreEntry entry, int elementsAdded) {
24 Assertions.assertEquals(elementsAdded,entry.getNumberOfVisitedActivations());
25 Assertions.assertEquals(SMALL_SIZE-elementsAdded,entry.getNumberOfUnvisitedActivations());
26 }
27
28 @ParameterizedTest
29 @MethodSource("entries")
30 void testDifferent(ActivationStoreEntry entry) {
31 int elementsAdded = 0;
32 addTest(entry,elementsAdded);
33 Assertions.assertEquals(2, entry.getAndAddActivationAfter(2));
34 addTest(entry,++elementsAdded);
35 Assertions.assertEquals(3,entry.getAndAddActivationAfter(3));
36 addTest(entry,++elementsAdded);
37 Assertions.assertEquals(1,entry.getAndAddActivationAfter(1));
38 addTest(entry,++elementsAdded);
39 Assertions.assertEquals(4,entry.getAndAddActivationAfter(4));
40 addTest(entry,++elementsAdded);
41 Assertions.assertEquals(0,entry.getAndAddActivationAfter(0));
42 addTest(entry,++elementsAdded);
43 }
44
45 @ParameterizedTest
46 @MethodSource("entries")
47 void testSame(ActivationStoreEntry entry) {
48 int elementsAdded = 0;
49 addTest(entry,elementsAdded);
50 entry.getAndAddActivationAfter(2);
51 addTest(entry,++elementsAdded);
52 entry.getAndAddActivationAfter(2);
53 addTest(entry,++elementsAdded);
54 entry.getAndAddActivationAfter(2);
55 addTest(entry,++elementsAdded);
56 entry.getAndAddActivationAfter(2);
57 addTest(entry,++elementsAdded);
58 entry.getAndAddActivationAfter(2);
59 addTest(entry,++elementsAdded);
60 }
61
62 @ParameterizedTest
63 @MethodSource("entries")
64 void testFilling(ActivationStoreEntry entry) {
65 int elementsAdded = 0;
66 while(elementsAdded < SMALL_SIZE) {
67 entry.getAndAddActivationAfter(2);
68 elementsAdded++;
69 }
70 Assertions.assertThrows(IllegalArgumentException.class,()-> entry.getAndAddActivationAfter(2));
71 }
72}