diff options
10 files changed, 98 insertions, 179 deletions
diff --git a/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java b/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java index 592f5fcf..1ee41cc3 100644 --- a/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java +++ b/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java | |||
@@ -9,7 +9,7 @@ import tools.refinery.store.adapter.ModelAdapterBuilder; | |||
9 | import tools.refinery.visualization.internal.FileFormat; | 9 | import tools.refinery.visualization.internal.FileFormat; |
10 | 10 | ||
11 | public interface ModelVisualizerBuilder extends ModelAdapterBuilder { | 11 | public interface ModelVisualizerBuilder extends ModelAdapterBuilder { |
12 | ModelVisualizerBuilder withOutputpath(String outputpath); | 12 | ModelVisualizerBuilder withOutputPath(String outputPath); |
13 | ModelVisualizerBuilder withFormat(FileFormat format); | 13 | ModelVisualizerBuilder withFormat(FileFormat format); |
14 | ModelVisualizerBuilder saveDesignSpace(); | 14 | ModelVisualizerBuilder saveDesignSpace(); |
15 | ModelVisualizerBuilder saveStates(); | 15 | ModelVisualizerBuilder saveStates(); |
diff --git a/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java b/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java index e4d801d8..9ba2abe8 100644 --- a/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java +++ b/subprojects/store-dse-visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java | |||
@@ -18,7 +18,7 @@ public class ModelVisualizerBuilderImpl | |||
18 | private String outputPath; | 18 | private String outputPath; |
19 | private boolean saveDesignSpace = false; | 19 | private boolean saveDesignSpace = false; |
20 | private boolean saveStates = false; | 20 | private boolean saveStates = false; |
21 | private Set<FileFormat> formats = new LinkedHashSet<>(); | 21 | private final Set<FileFormat> formats = new LinkedHashSet<>(); |
22 | 22 | ||
23 | @Override | 23 | @Override |
24 | protected ModelVisualizeStoreAdapterImpl doBuild(ModelStore store) { | 24 | protected ModelVisualizeStoreAdapterImpl doBuild(ModelStore store) { |
@@ -26,9 +26,9 @@ public class ModelVisualizerBuilderImpl | |||
26 | } | 26 | } |
27 | 27 | ||
28 | @Override | 28 | @Override |
29 | public ModelVisualizerBuilder withOutputpath(String outputpath) { | 29 | public ModelVisualizerBuilder withOutputPath(String outputPath) { |
30 | checkNotConfigured(); | 30 | checkNotConfigured(); |
31 | this.outputPath = outputpath; | 31 | this.outputPath = outputPath; |
32 | return this; | 32 | return this; |
33 | } | 33 | } |
34 | 34 | ||
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 index a2b6268f..8f7e3bdc 100644 --- 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 | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.dse.strategy; | 6 | package tools.refinery.store.dse.strategy; |
7 | 7 | ||
8 | import tools.refinery.store.dse.transition.VersionWithObjectiveValue; | ||
9 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
10 | 9 | ||
11 | import java.util.Random; | 10 | import java.util.Random; |
@@ -13,6 +12,7 @@ import java.util.Random; | |||
13 | public class BestFirstExplorer extends BestFirstWorker { | 12 | public class BestFirstExplorer extends BestFirstWorker { |
14 | final int id; | 13 | final int id; |
15 | Random random; | 14 | Random random; |
15 | |||
16 | public BestFirstExplorer(BestFirstStoreManager storeManager, Model model, int id) { | 16 | public BestFirstExplorer(BestFirstStoreManager storeManager, Model model, int id) { |
17 | super(storeManager, model); | 17 | super(storeManager, model); |
18 | this.id = id; | 18 | this.id = id; |
@@ -20,6 +20,7 @@ public class BestFirstExplorer extends BestFirstWorker { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | private boolean interrupted = false; | 22 | private boolean interrupted = false; |
23 | |||
23 | public void interrupt() { | 24 | public void interrupt() { |
24 | this.interrupted = true; | 25 | this.interrupted = true; |
25 | } | 26 | } |
@@ -29,138 +30,37 @@ public class BestFirstExplorer extends BestFirstWorker { | |||
29 | } | 30 | } |
30 | 31 | ||
31 | public void explore() { | 32 | public void explore() { |
32 | VersionWithObjectiveValue lastVisited = submit().newVersion(); | 33 | var lastBest = submit().newVersion(); |
33 | |||
34 | while (shouldRun()) { | 34 | while (shouldRun()) { |
35 | 35 | if (lastBest == null) { | |
36 | if (lastVisited == null) { | 36 | lastBest = restoreToBest(); |
37 | lastVisited = this.restoreToBest(); | 37 | if (lastBest == null) { |
38 | if(lastVisited == null) { | ||
39 | return; | 38 | return; |
40 | } | 39 | } |
41 | } | 40 | } |
42 | |||
43 | boolean tryActivation = true; | 41 | boolean tryActivation = true; |
44 | while(tryActivation && shouldRun()) { | 42 | while (tryActivation && shouldRun()) { |
45 | RandomVisitResult randomVisitResult = this.visitRandomUnvisited(random); | 43 | var randomVisitResult = this.visitRandomUnvisited(random); |
46 | |||
47 | tryActivation = randomVisitResult.shouldRetry(); | 44 | tryActivation = randomVisitResult.shouldRetry(); |
48 | var newSubmit = randomVisitResult.submitResult(); | 45 | var newSubmit = randomVisitResult.submitResult(); |
49 | if(newSubmit != null) { | 46 | if (newSubmit != null) { |
50 | if(!newSubmit.include()) { | 47 | if (!newSubmit.include()) { |
51 | restoreToLast(); | 48 | restoreToLast(); |
52 | } else { | 49 | } else { |
53 | var newVisit = newSubmit.newVersion(); | 50 | var newVisit = newSubmit.newVersion(); |
54 | int compareResult = compare(lastVisited,newVisit); | 51 | int compareResult = compare(lastBest, newVisit); |
55 | if(compareResult >= 0) { | 52 | if (compareResult >= 0) { |
56 | lastVisited = newVisit; | 53 | lastBest = newVisit; |
57 | break; | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | else { | ||
62 | lastVisited = null; | ||
63 | break; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | //final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); | ||
68 | |||
69 | /*boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); | ||
70 | if (!globalConstraintsAreSatisfied) { | ||
71 | // Global constraint is not satisfied in the first state. Terminate. | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | final Fitness firstFitness = dseAdapter.getFitness(); | ||
76 | if (firstFitness.isSatisfiesHardObjectives()) { | ||
77 | dseAdapter.newSolution(); | ||
78 | // First state is a solution. Terminate. | ||
79 | if (backTrackIfSolution) { | ||
80 | return; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | if (maxDepth == 0) { | ||
85 | return; | ||
86 | }*/ | ||
87 | |||
88 | /* | ||
89 | var firstTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), firstFitness); | ||
90 | trajectoriesToExplore.add(firstTrajectoryWithFitness); | ||
91 | TrajectoryWithFitness currentTrajectoryWithFitness = null; | ||
92 | */ | ||
93 | /* | ||
94 | Collection<Activation> activations = dseAdapter.getUntraversedActivations(); | ||
95 | Iterator<Activation> iterator = activations.iterator(); | ||
96 | |||
97 | while (iterator.hasNext()) { | ||
98 | final Activation nextActivation = iterator.next(); | ||
99 | if (!iterator.hasNext()) { | ||
100 | // Last untraversed activation of the state. | ||
101 | trajectoriesToExplore.remove(currentTrajectoryWithFitness); | ||
102 | } | ||
103 | |||
104 | // Executing new activation | ||
105 | dseAdapter.fireActivation(nextActivation); | ||
106 | if (dseAdapter.isCurrentStateAlreadyTraversed()) { | ||
107 | // The new state is already visited. | ||
108 | dseAdapter.backtrack(); | ||
109 | } else if (!dseAdapter.checkGlobalConstraints()) { | ||
110 | // Global constraint is not satisfied. | ||
111 | dseAdapter.backtrack(); | ||
112 | } else { | ||
113 | final Fitness nextFitness = dseAdapter.getFitness(); | ||
114 | if (nextFitness.isSatisfiesHardObjectives()) { | ||
115 | dseAdapter.newSolution(); | ||
116 | var solutions = dseAdapter.getSolutions().size(); | ||
117 | if (solutions >= maxSolutions) { | ||
118 | return; | ||
119 | } | ||
120 | // Found a solution. | ||
121 | if (backTrackIfSolution) { | ||
122 | dseAdapter.backtrack(); | ||
123 | continue; | ||
124 | } | ||
125 | } | ||
126 | if (dseAdapter.getDepth() >= maxDepth) { | ||
127 | // Reached max depth. | ||
128 | dseAdapter.backtrack(); | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | TrajectoryWithFitness nextTrajectoryWithFitness = new TrajectoryWithFitness( | ||
133 | dseAdapter.getTrajectory(), nextFitness); | ||
134 | trajectoriesToExplore.add(nextTrajectoryWithFitness); | ||
135 | |||
136 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness, | ||
137 | nextTrajectoryWithFitness.fitness); | ||
138 | if (compare < 0) { | ||
139 | // Better fitness, moving on | ||
140 | currentTrajectoryWithFitness = nextTrajectoryWithFitness; | ||
141 | continue mainLoop; | ||
142 | } else if (compare == 0) { | ||
143 | if (onlyBetterFirst) { | ||
144 | // Equally good fitness, backtrack | ||
145 | dseAdapter.backtrack(); | ||
146 | } else { | 54 | } else { |
147 | // Equally good fitness, moving on | 55 | lastBest = null; |
148 | currentTrajectoryWithFitness = nextTrajectoryWithFitness; | ||
149 | continue mainLoop; | ||
150 | } | 56 | } |
151 | } else { | 57 | break; |
152 | //"Worse fitness | ||
153 | currentTrajectoryWithFitness = null; | ||
154 | continue mainLoop; | ||
155 | } | 58 | } |
59 | } else { | ||
60 | lastBest = null; | ||
61 | break; | ||
156 | } | 62 | } |
157 | } | 63 | } |
158 | |||
159 | // State is fully traversed. | ||
160 | currentTrajectoryWithFitness = null; | ||
161 | */ | ||
162 | } | 64 | } |
163 | // Interrupted. | ||
164 | |||
165 | } | 65 | } |
166 | } | 66 | } |
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 index 4ccba6f7..02634a02 100644 --- 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 | |||
@@ -17,9 +17,7 @@ import tools.refinery.store.dse.transition.statespace.internal.ObjectivePriority | |||
17 | import tools.refinery.store.dse.transition.statespace.internal.SolutionStoreImpl; | 17 | import tools.refinery.store.dse.transition.statespace.internal.SolutionStoreImpl; |
18 | import tools.refinery.store.map.Version; | 18 | import tools.refinery.store.map.Version; |
19 | import tools.refinery.store.model.ModelStore; | 19 | import tools.refinery.store.model.ModelStore; |
20 | import tools.refinery.store.statecoding.StateCoderResult; | ||
21 | import tools.refinery.store.statecoding.StateCoderStoreAdapter; | 20 | import tools.refinery.store.statecoding.StateCoderStoreAdapter; |
22 | import tools.refinery.visualization.ModelVisualizerStoreAdapter; | ||
23 | import tools.refinery.visualization.statespace.VisualizationStore; | 21 | import tools.refinery.visualization.statespace.VisualizationStore; |
24 | import tools.refinery.visualization.statespace.internal.VisualizationStoreImpl; | 22 | import tools.refinery.visualization.statespace.internal.VisualizationStoreImpl; |
25 | 23 | ||
@@ -34,7 +32,7 @@ public class BestFirstStoreManager { | |||
34 | EquivalenceClassStore equivalenceClassStore; | 32 | EquivalenceClassStore equivalenceClassStore; |
35 | VisualizationStore visualizationStore; | 33 | VisualizationStore visualizationStore; |
36 | 34 | ||
37 | public BestFirstStoreManager(ModelStore modelStore) { | 35 | public BestFirstStoreManager(ModelStore modelStore, int maxNumberOfSolutions) { |
38 | this.modelStore = modelStore; | 36 | this.modelStore = modelStore; |
39 | DesignSpaceExplorationStoreAdapter storeAdapter = | 37 | DesignSpaceExplorationStoreAdapter storeAdapter = |
40 | modelStore.getAdapter(DesignSpaceExplorationStoreAdapter.class); | 38 | modelStore.getAdapter(DesignSpaceExplorationStoreAdapter.class); |
@@ -42,7 +40,7 @@ public class BestFirstStoreManager { | |||
42 | objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives()); | 40 | objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives()); |
43 | Consumer<VersionWithObjectiveValue> whenAllActivationsVisited = x -> objectiveStore.remove(x); | 41 | Consumer<VersionWithObjectiveValue> whenAllActivationsVisited = x -> objectiveStore.remove(x); |
44 | activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited); | 42 | activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited); |
45 | solutionStore = new SolutionStoreImpl(50); | 43 | solutionStore = new SolutionStoreImpl(maxNumberOfSolutions); |
46 | equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) { | 44 | equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) { |
47 | @Override | 45 | @Override |
48 | protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) { | 46 | protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) { |
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 index f1bec14f..5d738297 100644 --- 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 | |||
@@ -40,11 +40,13 @@ public class BestFirstWorker { | |||
40 | isVisualizationEnabled = visualizationStore != null; | 40 | isVisualizationEnabled = visualizationStore != null; |
41 | } | 41 | } |
42 | 42 | ||
43 | private VersionWithObjectiveValue last = null; | 43 | protected VersionWithObjectiveValue last = null; |
44 | |||
45 | //public boolean isIncluded | ||
46 | 44 | ||
47 | public SubmitResult submit() { | 45 | public SubmitResult submit() { |
46 | checkSynchronized(); | ||
47 | if (queryAdapter.hasPendingChanges()) { | ||
48 | throw new AssertionError("Pending changes detected before model submission"); | ||
49 | } | ||
48 | if (explorationAdapter.checkExclude()) { | 50 | if (explorationAdapter.checkExclude()) { |
49 | return new SubmitResult(false, false, null, null); | 51 | return new SubmitResult(false, false, null, null); |
50 | } | 52 | } |
@@ -86,14 +88,11 @@ public class BestFirstWorker { | |||
86 | 88 | ||
87 | public VersionWithObjectiveValue restoreToBest() { | 89 | public VersionWithObjectiveValue restoreToBest() { |
88 | var bestVersion = storeManager.getObjectiveStore().getBest(); | 90 | var bestVersion = storeManager.getObjectiveStore().getBest(); |
91 | last = bestVersion; | ||
89 | if (bestVersion != null) { | 92 | if (bestVersion != null) { |
90 | var oldVersion = model.getState(); | ||
91 | this.model.restore(bestVersion.version()); | 93 | this.model.restore(bestVersion.version()); |
92 | if (isVisualizationEnabled) { | ||
93 | visualizationStore.addTransition(oldVersion, last.version(), ""); | ||
94 | } | ||
95 | } | 94 | } |
96 | return bestVersion; | 95 | return last; |
97 | } | 96 | } |
98 | 97 | ||
99 | public VersionWithObjectiveValue restoreToRandom(Random random) { | 98 | public VersionWithObjectiveValue restoreToRandom(Random random) { |
@@ -102,7 +101,7 @@ public class BestFirstWorker { | |||
102 | if (randomVersion != null) { | 101 | if (randomVersion != null) { |
103 | this.model.restore(randomVersion.version()); | 102 | this.model.restore(randomVersion.version()); |
104 | } | 103 | } |
105 | return randomVersion; | 104 | return last; |
106 | } | 105 | } |
107 | 106 | ||
108 | public int compare(VersionWithObjectiveValue s1, VersionWithObjectiveValue s2) { | 107 | public int compare(VersionWithObjectiveValue s1, VersionWithObjectiveValue s2) { |
@@ -121,9 +120,10 @@ public class BestFirstWorker { | |||
121 | } | 120 | } |
122 | 121 | ||
123 | public RandomVisitResult visitRandomUnvisited(Random random) { | 122 | public RandomVisitResult visitRandomUnvisited(Random random) { |
123 | checkSynchronized(); | ||
124 | if (!model.hasUncommittedChanges()) { | 124 | if (!model.hasUncommittedChanges()) { |
125 | queryAdapter.flushChanges(); | ||
126 | var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); | 125 | var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); |
126 | queryAdapter.flushChanges(); | ||
127 | 127 | ||
128 | if (visitResult.successfulVisit()) { | 128 | if (visitResult.successfulVisit()) { |
129 | Version oldVersion = null; | 129 | Version oldVersion = null; |
@@ -133,7 +133,8 @@ public class BestFirstWorker { | |||
133 | var submitResult = submit(); | 133 | var submitResult = submit(); |
134 | if (isVisualizationEnabled && submitResult.newVersion() != null) { | 134 | if (isVisualizationEnabled && submitResult.newVersion() != null) { |
135 | var newVersion = submitResult.newVersion().version(); | 135 | var newVersion = submitResult.newVersion().version(); |
136 | visualizationStore.addTransition(oldVersion, newVersion, ""); | 136 | visualizationStore.addTransition(oldVersion, newVersion, |
137 | "fire: " + visitResult.transformation() + ", " + visitResult.activation()); | ||
137 | } | 138 | } |
138 | return new RandomVisitResult(submitResult, visitResult.mayHaveMore()); | 139 | return new RandomVisitResult(submitResult, visitResult.mayHaveMore()); |
139 | } else { | 140 | } else { |
@@ -147,4 +148,10 @@ public class BestFirstWorker { | |||
147 | public boolean hasEnoughSolution() { | 148 | public boolean hasEnoughSolution() { |
148 | return storeManager.solutionStore.hasEnoughSolution(); | 149 | return storeManager.solutionStore.hasEnoughSolution(); |
149 | } | 150 | } |
151 | |||
152 | private void checkSynchronized() { | ||
153 | if (last != null && !last.version().equals(model.getState())) { | ||
154 | throw new AssertionError("Worker is not synchronized with model state"); | ||
155 | } | ||
156 | } | ||
150 | } | 157 | } |
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 index 24145d03..c204ae35 100644 --- 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 | |||
@@ -16,32 +16,35 @@ public class ActivationStoreBitVectorEntry extends ActivationStoreEntry { | |||
16 | @Override | 16 | @Override |
17 | public int getNumberOfVisitedActivations() { | 17 | public int getNumberOfVisitedActivations() { |
18 | int visited = 0; | 18 | int visited = 0; |
19 | for (int i : selected) { | 19 | // Use indexed for loop to avoid allocating an iterator. |
20 | visited += Integer.bitCount(i); | 20 | //noinspection ForLoopReplaceableByForEach |
21 | for (int i = 0; i < selected.length; i++) { | ||
22 | visited += Integer.bitCount(selected[i]); | ||
21 | } | 23 | } |
22 | return visited; | 24 | return visited; |
23 | } | 25 | } |
24 | 26 | ||
25 | private static final int ELEMENT_POSITION = 5; // size of Integer.SIZE | 27 | private static final int ELEMENT_POSITION = 5; // size of Integer.SIZE |
26 | private static final int ELEMENT_BITMASK = (1<<ELEMENT_POSITION)-1; | 28 | private static final int ELEMENT_BITMASK = (1 << ELEMENT_POSITION) - 1; |
29 | |||
27 | @Override | 30 | @Override |
28 | public int getAndAddActivationAfter(int index) { | 31 | public int getAndAddActivationAfter(int index) { |
29 | int position = index; | 32 | int position = index; |
30 | do { | 33 | do { |
31 | final int selectedElement = position >> ELEMENT_POSITION; | 34 | final int selectedElement = position >> ELEMENT_POSITION; |
32 | final int selectedBit = 1<<(position & ELEMENT_BITMASK); | 35 | final int selectedBit = 1 << (position & ELEMENT_BITMASK); |
33 | 36 | ||
34 | if((selected[selectedElement] & selectedBit) == 0) { | 37 | if ((selected[selectedElement] & selectedBit) == 0) { |
35 | selected[selectedElement] |= selectedBit; | 38 | selected[selectedElement] |= selectedBit; |
36 | return position; | 39 | return position; |
37 | } else { | 40 | } else { |
38 | if(position < this.numberOfActivations-1) { | 41 | if (position < this.numberOfActivations - 1) { |
39 | position++; | 42 | position++; |
40 | } else { | 43 | } else { |
41 | position = 0; | 44 | position = 0; |
42 | } | 45 | } |
43 | } | 46 | } |
44 | } while(position != index); | 47 | } while (position != index); |
45 | throw new IllegalArgumentException("There is are no unvisited activations!"); | 48 | throw new IllegalArgumentException("There is are no unvisited activations!"); |
46 | } | 49 | } |
47 | } | 50 | } |
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 index d7339805..7249751c 100644 --- 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 | |||
@@ -17,6 +17,11 @@ public abstract class ActivationStoreEntry { | |||
17 | public int getNumberOfUnvisitedActivations() { | 17 | public int getNumberOfUnvisitedActivations() { |
18 | return numberOfActivations - getNumberOfVisitedActivations(); | 18 | return numberOfActivations - getNumberOfVisitedActivations(); |
19 | } | 19 | } |
20 | |||
21 | public int getNumberOfActivations() { | ||
22 | return numberOfActivations; | ||
23 | } | ||
24 | |||
20 | public abstract int getAndAddActivationAfter(int index); | 25 | public abstract int getAndAddActivationAfter(int index); |
21 | 26 | ||
22 | // public abstract boolean contains(int activation) | 27 | // public abstract boolean contains(int activation) |
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 index 4d775b5a..d9e29eca 100644 --- 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 | |||
@@ -28,7 +28,7 @@ public class ActivationStoreImpl implements ActivationStore { | |||
28 | var entries = versionToActivations.computeIfAbsent(to, x -> { | 28 | var entries = versionToActivations.computeIfAbsent(to, x -> { |
29 | successful[0] = true; | 29 | successful[0] = true; |
30 | List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length); | 30 | List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length); |
31 | for(int emptyEntrySize : emptyEntrySizes) { | 31 | for (int emptyEntrySize : emptyEntrySizes) { |
32 | result.add(ActivationStoreEntry.create(emptyEntrySize)); | 32 | result.add(ActivationStoreEntry.create(emptyEntrySize)); |
33 | } | 33 | } |
34 | return result; | 34 | return result; |
@@ -40,13 +40,14 @@ public class ActivationStoreImpl implements ActivationStore { | |||
40 | break; | 40 | break; |
41 | } | 41 | } |
42 | } | 42 | } |
43 | if(!hasMore) { | 43 | if (!hasMore) { |
44 | actionWhenAllActivationVisited.accept(to); | 44 | actionWhenAllActivationVisited.accept(to); |
45 | } | 45 | } |
46 | return new VisitResult(successful[0], hasMore, -1, -1); | 46 | return new VisitResult(successful[0], hasMore, -1, -1); |
47 | } | 47 | } |
48 | 48 | ||
49 | public synchronized VisitResult visitActivation(VersionWithObjectiveValue from, int transformationIndex, int activationIndex) { | 49 | public synchronized VisitResult visitActivation(VersionWithObjectiveValue from, int transformationIndex, |
50 | int activationIndex) { | ||
50 | var entries = versionToActivations.get(from); | 51 | var entries = versionToActivations.get(from); |
51 | var entry = entries.get(transformationIndex); | 52 | var entry = entries.get(transformationIndex); |
52 | final int unvisited = entry.getNumberOfUnvisitedActivations(); | 53 | final int unvisited = entry.getNumberOfUnvisitedActivations(); |
@@ -66,7 +67,7 @@ public class ActivationStoreImpl implements ActivationStore { | |||
66 | activation = -1; | 67 | activation = -1; |
67 | } | 68 | } |
68 | 69 | ||
69 | if(!hasMoreInActivation) { | 70 | if (!hasMoreInActivation) { |
70 | boolean hasMoreInOtherTransformation = false; | 71 | boolean hasMoreInOtherTransformation = false; |
71 | for (var e : entries) { | 72 | for (var e : entries) { |
72 | if (e != entry && e.getNumberOfUnvisitedActivations() > 0) { | 73 | if (e != entry && e.getNumberOfUnvisitedActivations() > 0) { |
@@ -79,7 +80,7 @@ public class ActivationStoreImpl implements ActivationStore { | |||
79 | hasMore = true; | 80 | hasMore = true; |
80 | } | 81 | } |
81 | 82 | ||
82 | if(!hasMore) { | 83 | if (!hasMore) { |
83 | actionWhenAllActivationVisited.accept(from); | 84 | actionWhenAllActivationVisited.accept(from); |
84 | } | 85 | } |
85 | 86 | ||
@@ -103,34 +104,28 @@ public class ActivationStoreImpl implements ActivationStore { | |||
103 | public synchronized VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random) { | 104 | public synchronized VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random) { |
104 | var entries = versionToActivations.get(version); | 105 | var entries = versionToActivations.get(version); |
105 | 106 | ||
106 | int sum1 = 0; | 107 | int numberOfAllUnvisitedActivations = 0; |
107 | for (var entry : entries) { | 108 | for (var entry : entries) { |
108 | sum1 += entry.getNumberOfUnvisitedActivations(); | 109 | numberOfAllUnvisitedActivations += entry.getNumberOfUnvisitedActivations(); |
109 | } | 110 | } |
110 | 111 | ||
111 | if(sum1 == 0) { | 112 | if (numberOfAllUnvisitedActivations == 0) { |
112 | this.actionWhenAllActivationVisited.accept(version); | 113 | this.actionWhenAllActivationVisited.accept(version); |
113 | return new VisitResult(false, false, -1, -1); | 114 | return new VisitResult(false, false, -1, -1); |
114 | } | 115 | } |
115 | 116 | ||
116 | int selected = random.nextInt(sum1); | 117 | int offset = random.nextInt(numberOfAllUnvisitedActivations); |
117 | int sum2 = 0; | ||
118 | int transformation = 0; | 118 | int transformation = 0; |
119 | int activation = -1; | ||
120 | for (; transformation < entries.size(); transformation++) { | 119 | for (; transformation < entries.size(); transformation++) { |
121 | var entry = entries.get(transformation); | 120 | var entry = entries.get(transformation); |
122 | int unvisited = entry.getNumberOfUnvisitedActivations(); | 121 | int unvisited = entry.getNumberOfUnvisitedActivations(); |
123 | if (selected < sum2 + unvisited) { | 122 | if (unvisited > 0 && offset < unvisited) { |
124 | activation = sum2 + unvisited - selected - 1; | 123 | int activation = random.nextInt(entry.getNumberOfActivations()); |
125 | break; | 124 | return this.visitActivation(version, transformation, activation); |
126 | } else { | ||
127 | sum2 += unvisited; | ||
128 | } | 125 | } |
129 | } | 126 | offset -= unvisited; |
130 | if (activation == -1) { | ||
131 | throw new IllegalArgumentException("no unvisited"); | ||
132 | } | 127 | } |
133 | 128 | ||
134 | return this.visitActivation(version, transformation, activation); | 129 | throw new AssertionError("Unvisited activation %d not found".formatted(offset)); |
135 | } | 130 | } |
136 | } | 131 | } |
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 685b88bd..63da6cc3 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 | |||
@@ -11,10 +11,11 @@ import tools.refinery.store.dse.modification.DanglingEdges; | |||
11 | import tools.refinery.store.dse.modification.ModificationAdapter; | 11 | import tools.refinery.store.dse.modification.ModificationAdapter; |
12 | import tools.refinery.store.dse.strategy.BestFirstStoreManager; | 12 | import tools.refinery.store.dse.strategy.BestFirstStoreManager; |
13 | import tools.refinery.store.dse.tests.DummyCriterion; | 13 | import tools.refinery.store.dse.tests.DummyCriterion; |
14 | import tools.refinery.store.dse.tests.DummyRandomCriterion; | ||
15 | import tools.refinery.store.dse.tests.DummyRandomObjective; | 14 | import tools.refinery.store.dse.tests.DummyRandomObjective; |
16 | import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; | 15 | import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; |
17 | import tools.refinery.store.dse.transition.Rule; | 16 | import tools.refinery.store.dse.transition.Rule; |
17 | import tools.refinery.store.dse.transition.objectives.Criteria; | ||
18 | import tools.refinery.store.dse.transition.objectives.Objectives; | ||
18 | import tools.refinery.store.model.ModelStore; | 19 | import tools.refinery.store.model.ModelStore; |
19 | import tools.refinery.store.query.ModelQueryAdapter; | 20 | import tools.refinery.store.query.ModelQueryAdapter; |
20 | import tools.refinery.store.query.dnf.Query; | 21 | import tools.refinery.store.query.dnf.Query; |
@@ -59,6 +60,12 @@ class CRAExamplesTest { | |||
59 | methodView.call(f) | 60 | methodView.call(f) |
60 | )); | 61 | )); |
61 | 62 | ||
63 | private static final RelationalQuery unEncapsulatedFeature = Query.of("unEncapsulatedFeature", | ||
64 | (builder, f) -> builder.clause( | ||
65 | feature.call(f), | ||
66 | not(encapsulatesView.call(Variable.of(), f)) | ||
67 | )); | ||
68 | |||
62 | private static final Rule assignFeatureRule = Rule.of("AssignFeature", (builder, f, c1) -> builder | 69 | private static final Rule assignFeatureRule = Rule.of("AssignFeature", (builder, f, c1) -> builder |
63 | .clause( | 70 | .clause( |
64 | feature.call(f), | 71 | feature.call(f), |
@@ -66,24 +73,24 @@ class CRAExamplesTest { | |||
66 | not(encapsulatesView.call(Variable.of(), f)) | 73 | not(encapsulatesView.call(Variable.of(), f)) |
67 | ) | 74 | ) |
68 | .action( | 75 | .action( |
69 | add(encapsulates, f, c1) | 76 | add(encapsulates, c1, f) |
70 | )); | 77 | )); |
71 | 78 | ||
72 | private static final Rule deleteEmptyClassRule = Rule.of("DeleteEmptyClass", (builder, c) -> builder | 79 | private static final Rule deleteEmptyClassRule = Rule.of("DeleteEmptyClass", (builder, c) -> builder |
73 | .clause((f) -> List.of( | 80 | .clause( |
74 | classElementView.call(c), | 81 | classElementView.call(c), |
75 | not(encapsulatesView.call(c, f)) | 82 | not(encapsulatesView.call(c, Variable.of())) |
76 | )) | 83 | ) |
77 | .action( | 84 | .action( |
78 | remove(classElement, c), | 85 | remove(classElement, c), |
79 | delete(c, DanglingEdges.IGNORE) | 86 | delete(c, DanglingEdges.IGNORE) |
80 | )); | 87 | )); |
81 | 88 | ||
82 | private static final Rule createClassRule = Rule.of("CreateClass", (builder, f) -> builder | 89 | private static final Rule createClassRule = Rule.of("CreateClass", (builder, f) -> builder |
83 | .clause((c) -> List.of( | 90 | .clause( |
84 | feature.call(f), | 91 | feature.call(f), |
85 | not(encapsulatesView.call(f, c)) | 92 | not(encapsulatesView.call(Variable.of(), f)) |
86 | )) | 93 | ) |
87 | .action((newClass) -> List.of( | 94 | .action((newClass) -> List.of( |
88 | create(newClass), | 95 | create(newClass), |
89 | add(classElement, newClass), | 96 | add(classElement, newClass), |
@@ -110,7 +117,7 @@ class CRAExamplesTest { | |||
110 | .symbols(classElement, encapsulates, attribute, method, dataDependency, functionalDependency, name) | 117 | .symbols(classElement, encapsulates, attribute, method, dataDependency, functionalDependency, name) |
111 | .with(ViatraModelQueryAdapter.builder()) | 118 | .with(ViatraModelQueryAdapter.builder()) |
112 | .with(ModelVisualizerAdapter.builder() | 119 | .with(ModelVisualizerAdapter.builder() |
113 | .withOutputpath("test_output") | 120 | .withOutputPath("test_output") |
114 | .withFormat(FileFormat.DOT) | 121 | .withFormat(FileFormat.DOT) |
115 | .withFormat(FileFormat.SVG) | 122 | .withFormat(FileFormat.SVG) |
116 | .saveStates() | 123 | .saveStates() |
@@ -119,8 +126,11 @@ class CRAExamplesTest { | |||
119 | .with(ModificationAdapter.builder()) | 126 | .with(ModificationAdapter.builder()) |
120 | .with(DesignSpaceExplorationAdapter.builder() | 127 | .with(DesignSpaceExplorationAdapter.builder() |
121 | .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) | 128 | .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) |
122 | .objectives(new DummyRandomObjective()) | 129 | .objectives(Objectives.sum( |
123 | .accept(new DummyRandomCriterion()) | 130 | new DummyRandomObjective(), |
131 | Objectives.count(unEncapsulatedFeature) | ||
132 | )) | ||
133 | .accept(Criteria.whenNoMatch(unEncapsulatedFeature)) | ||
124 | .exclude(new DummyCriterion(false))) | 134 | .exclude(new DummyCriterion(false))) |
125 | .build(); | 135 | .build(); |
126 | 136 | ||
@@ -192,9 +202,10 @@ class CRAExamplesTest { | |||
192 | var initialVersion = model.commit(); | 202 | var initialVersion = model.commit(); |
193 | queryEngine.flushChanges(); | 203 | queryEngine.flushChanges(); |
194 | 204 | ||
195 | var bestFirst = new BestFirstStoreManager(store); | 205 | var bestFirst = new BestFirstStoreManager(store, 50); |
196 | bestFirst.startExploration(initialVersion); | 206 | bestFirst.startExploration(initialVersion); |
197 | var resultStore = bestFirst.getSolutionStore(); | 207 | var resultStore = bestFirst.getSolutionStore(); |
198 | System.out.println("states size: " + resultStore.getSolutions().size()); | 208 | System.out.println("states size: " + resultStore.getSolutions().size()); |
209 | model.getAdapter(ModelVisualizerAdapter.class).visualize(bestFirst.getVisualizationStore()); | ||
199 | } | 210 | } |
200 | } | 211 | } |
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 baa7c8a4..b912eba3 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 | |||
@@ -64,7 +64,7 @@ class DebugTest { | |||
64 | .symbols(classModel, classElement, feature, classes, features) | 64 | .symbols(classModel, classElement, feature, classes, features) |
65 | .with(ViatraModelQueryAdapter.builder()) | 65 | .with(ViatraModelQueryAdapter.builder()) |
66 | .with(ModelVisualizerAdapter.builder() | 66 | .with(ModelVisualizerAdapter.builder() |
67 | .withOutputpath("test_output") | 67 | .withOutputPath("test_output") |
68 | .withFormat(FileFormat.DOT) | 68 | .withFormat(FileFormat.DOT) |
69 | .withFormat(FileFormat.SVG) | 69 | .withFormat(FileFormat.SVG) |
70 | .saveStates() | 70 | .saveStates() |
@@ -91,7 +91,7 @@ class DebugTest { | |||
91 | var initialVersion = model.commit(); | 91 | var initialVersion = model.commit(); |
92 | queryEngine.flushChanges(); | 92 | queryEngine.flushChanges(); |
93 | 93 | ||
94 | var bestFirst = new BestFirstStoreManager(store); | 94 | var bestFirst = new BestFirstStoreManager(store, 50); |
95 | bestFirst.startExploration(initialVersion); | 95 | bestFirst.startExploration(initialVersion); |
96 | var resultStore = bestFirst.getSolutionStore(); | 96 | var resultStore = bestFirst.getSolutionStore(); |
97 | System.out.println("states size: " + resultStore.getSolutions().size()); | 97 | System.out.println("states size: " + resultStore.getSolutions().size()); |