aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java164
1 files changed, 164 insertions, 0 deletions
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..aca800a3
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.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 org.jetbrains.annotations.Nullable;
9import tools.refinery.store.dse.propagation.PropagationAdapter;
10import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
11import tools.refinery.store.dse.transition.ObjectiveValue;
12import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
13import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker;
14import tools.refinery.store.map.Version;
15import tools.refinery.store.model.Model;
16import tools.refinery.store.query.ModelQueryAdapter;
17import tools.refinery.store.statecoding.StateCoderAdapter;
18import tools.refinery.visualization.statespace.VisualizationStore;
19
20import java.util.Random;
21
22public class BestFirstWorker {
23 final BestFirstStoreManager storeManager;
24 final Model model;
25 final ActivationStoreWorker activationStoreWorker;
26 final StateCoderAdapter stateCoderAdapter;
27 final DesignSpaceExplorationAdapter explorationAdapter;
28 final ModelQueryAdapter queryAdapter;
29 final @Nullable PropagationAdapter propagationAdapter;
30 final VisualizationStore visualizationStore;
31 final boolean isVisualizationEnabled;
32
33 public BestFirstWorker(BestFirstStoreManager storeManager, Model model) {
34 this.storeManager = storeManager;
35 this.model = model;
36
37 explorationAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
38 stateCoderAdapter = model.getAdapter(StateCoderAdapter.class);
39 queryAdapter = model.getAdapter(ModelQueryAdapter.class);
40 propagationAdapter = model.tryGetAdapter(PropagationAdapter.class).orElse(null);
41 activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(),
42 explorationAdapter.getTransformations());
43 visualizationStore = storeManager.getVisualizationStore();
44 isVisualizationEnabled = visualizationStore != null;
45 }
46
47 protected VersionWithObjectiveValue last = null;
48
49 public SubmitResult submit() {
50 checkSynchronized();
51 if (queryAdapter.hasPendingChanges()) {
52 throw new AssertionError("Pending changes detected before model submission");
53 }
54 if (explorationAdapter.checkExclude()) {
55 return new SubmitResult(false, false, null, null);
56 }
57
58 var code = stateCoderAdapter.calculateStateCode();
59
60 boolean isNew = storeManager.getEquivalenceClassStore().submit(code);
61 if (isNew) {
62 Version version = model.commit();
63 ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue();
64 var versionWithObjectiveValue = new VersionWithObjectiveValue(version, objectiveValue);
65 last = versionWithObjectiveValue;
66 var accepted = explorationAdapter.checkAccept();
67
68 storeManager.getObjectiveStore().submit(versionWithObjectiveValue);
69 storeManager.getActivationStore().markNewAsVisited(versionWithObjectiveValue, activationStoreWorker.calculateEmptyActivationSize());
70 if(accepted) {
71 storeManager.solutionStore.submit(versionWithObjectiveValue);
72 }
73
74 if (isVisualizationEnabled) {
75 visualizationStore.addState(last.version(), last.objectiveValue().toString());
76 if (accepted) {
77 visualizationStore.addSolution(last.version());
78 }
79 }
80
81 return new SubmitResult(true, accepted, objectiveValue, last);
82 }
83
84 return new SubmitResult(false, false, null, null);
85 }
86
87 public void restoreToLast() {
88 if (explorationAdapter.getModel().hasUncommittedChanges()) {
89 explorationAdapter.getModel().restore(last.version());
90 }
91 }
92
93 public VersionWithObjectiveValue restoreToBest() {
94 var bestVersion = storeManager.getObjectiveStore().getBest();
95 last = bestVersion;
96 if (bestVersion != null) {
97 this.model.restore(bestVersion.version());
98 }
99 return last;
100 }
101
102 public VersionWithObjectiveValue restoreToRandom(Random random) {
103 var objectiveStore = storeManager.getObjectiveStore();
104 if (objectiveStore.getSize() == 0) {
105 return null;
106 }
107 var randomVersion = objectiveStore.getRandom(random);
108 last = randomVersion;
109 if (randomVersion != null) {
110 this.model.restore(randomVersion.version());
111 }
112 return last;
113 }
114
115 public int compare(VersionWithObjectiveValue s1, VersionWithObjectiveValue s2) {
116 return storeManager.getObjectiveStore().getComparator().compare(s1, s2);
117 }
118
119 public record RandomVisitResult(SubmitResult submitResult, boolean shouldRetry) {
120 }
121
122 public RandomVisitResult visitRandomUnvisited(Random random) {
123 checkSynchronized();
124 if (model.hasUncommittedChanges()) {
125 throw new IllegalStateException("The model has uncommitted changes!");
126 }
127
128 var visitResult = activationStoreWorker.fireRandomActivation(this.last, random);
129
130 if (!visitResult.successfulVisit()) {
131 return new RandomVisitResult(null, visitResult.mayHaveMore());
132 }
133
134 if (propagationAdapter != null) {
135 var propagationResult = propagationAdapter.propagate();
136 if (propagationResult.isRejected()) {
137 return new RandomVisitResult(null, visitResult.mayHaveMore());
138 }
139 }
140 queryAdapter.flushChanges();
141
142 Version oldVersion = null;
143 if (isVisualizationEnabled) {
144 oldVersion = last.version();
145 }
146 var submitResult = submit();
147 if (isVisualizationEnabled && submitResult.newVersion() != null) {
148 var newVersion = submitResult.newVersion().version();
149 visualizationStore.addTransition(oldVersion, newVersion,
150 "fire: " + visitResult.transformation() + ", " + visitResult.activation());
151 }
152 return new RandomVisitResult(submitResult, visitResult.mayHaveMore());
153 }
154
155 public boolean hasEnoughSolution() {
156 return storeManager.solutionStore.hasEnoughSolution();
157 }
158
159 private void checkSynchronized() {
160 if (last != null && !last.version().equals(model.getState())) {
161 throw new AssertionError("Worker is not synchronized with model state");
162 }
163 }
164}