aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-09-05 20:33:31 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-09-05 20:33:31 +0200
commite5f14a3e9d92194c3f972f90a2f78c9c3dacaef4 (patch)
treeff1ebefb45348be48a23a89fa12b4817bc52bf51 /subprojects/store-dse
parentfeat(web): control server settings with env vars (diff)
parentrestructured DSE framework, failing build (diff)
downloadrefinery-e5f14a3e9d92194c3f972f90a2f78c9c3dacaef4.tar.gz
refinery-e5f14a3e9d92194c3f972f90a2f78c9c3dacaef4.tar.zst
refinery-e5f14a3e9d92194c3f972f90a2f78c9c3dacaef4.zip
Merge remote-tracking branch 'OszkarSemerath/datastructure' into partial-interpretation
Diffstat (limited to 'subprojects/store-dse')
-rw-r--r--subprojects/store-dse/build.gradle.kts16
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java15
-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/strategy/BestFirstExplorer.java164
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java72
-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/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.java44
-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.java104
-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.java277
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java116
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java596
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java414
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java57
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/statespace/internal/ActivationUnitTest.java72
49 files changed, 3535 insertions, 0 deletions
diff --git a/subprojects/store-dse/build.gradle.kts b/subprojects/store-dse/build.gradle.kts
new file mode 100644
index 00000000..5734fa09
--- /dev/null
+++ b/subprojects/store-dse/build.gradle.kts
@@ -0,0 +1,16 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7plugins {
8 id("tools.refinery.gradle.java-library")
9}
10
11dependencies {
12 api(project(":refinery-store-query"))
13 implementation(libs.eclipseCollections.api)
14 runtimeOnly(libs.eclipseCollections)
15 testImplementation(project(":refinery-store-query-viatra"))
16}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java
new file mode 100644
index 00000000..48a508b4
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java
@@ -0,0 +1,15 @@
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.model.Model;
9import tools.refinery.store.tuple.Tuple;
10
11import java.util.function.Consumer;
12
13public interface ActionFactory {
14 Consumer<Tuple> prepare(Model model);
15}
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/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..693b0903
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.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.strategy;
7
8import tools.refinery.store.dse.transition.DesignSpaceExplorationStoreAdapter;
9import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
10import tools.refinery.store.dse.transition.statespace.ActivationStore;
11import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
12import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue;
13import tools.refinery.store.dse.transition.statespace.SolutionStore;
14import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreImpl;
15import tools.refinery.store.dse.transition.statespace.internal.FastEquivalenceClassStore;
16import tools.refinery.store.dse.transition.statespace.internal.ObjectivePriorityQueueImpl;
17import tools.refinery.store.dse.transition.statespace.internal.SolutionStoreImpl;
18import tools.refinery.store.map.Version;
19import tools.refinery.store.model.ModelStore;
20import tools.refinery.store.statecoding.StateCoderStoreAdapter;
21
22import java.util.function.Consumer;
23
24public class BestFirstStoreManager {
25 ModelStore modelStore;
26 ObjectivePriorityQueue objectiveStore;
27 ActivationStore activationStore;
28 SolutionStore solutionStore;
29 EquivalenceClassStore equivalenceClassStore;
30
31 public BestFirstStoreManager(ModelStore modelStore) {
32 this.modelStore = modelStore;
33 DesignSpaceExplorationStoreAdapter storeAdapter =
34 modelStore.getAdapter(DesignSpaceExplorationStoreAdapter.class);
35
36 objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives());
37 Consumer<VersionWithObjectiveValue> whenAllActivationsVisited = x -> objectiveStore.remove(x);
38 activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited);
39 solutionStore = new SolutionStoreImpl(1);
40 equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) {
41 @Override
42 protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) {
43 objectiveStore.submit(version);
44 activationStore.markNewAsVisited(version, emptyActivations);
45 if(accept) {
46 solutionStore.submit(version);
47 }
48 }
49 };
50 }
51
52 ObjectivePriorityQueue getObjectiveStore() {
53 return objectiveStore;
54 }
55
56 ActivationStore getActivationStore() {
57 return activationStore;
58 }
59
60 SolutionStore getSolutionStore() {
61 return solutionStore;
62 }
63
64 EquivalenceClassStore getEquivalenceClassStore() {
65 return equivalenceClassStore;
66 }
67
68 public void startExploration(Version initial) {
69 BestFirstExplorer bestFirstExplorer = new BestFirstExplorer(this, modelStore.createModelForState(initial), 1);
70 bestFirstExplorer.explore();
71 }
72}
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/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..ab9fda3e
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.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;
7
8import tools.refinery.store.query.resultset.OrderedResultSet;
9import tools.refinery.store.query.resultset.ResultSet;
10import tools.refinery.store.tuple.Tuple;
11
12import java.util.function.Consumer;
13
14public class Transformation {
15 private final TransformationRule definition;
16
17 private final OrderedResultSet<Boolean> activations;
18
19 private final Consumer<Tuple> action;
20
21 public Transformation(TransformationRule definition, OrderedResultSet<Boolean> activations, Consumer<Tuple> action) {
22 this.definition = definition;
23 this.activations = activations;
24 this.action = action;
25 }
26
27 public TransformationRule getDefinition() {
28 return definition;
29 }
30
31 public ResultSet<Boolean> getAllActivationsAsResultSet() {
32 return activations;
33 }
34
35 public Tuple getActivation(int index) {
36 return activations.getKey(index);
37 }
38
39 public boolean fireActivation(Tuple activation) {
40 action.accept(activation);
41 //queryEngine.flushChanges();
42 return true;
43 }
44}
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..3e59b21a
--- /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 tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.dse.transition.statespace.ActivationStore;
10
11import java.util.*;
12import java.util.function.Consumer;
13
14public class ActivationStoreImpl implements ActivationStore {
15 final int numberOfTransformations;
16 final Consumer<VersionWithObjectiveValue> actionWhenAllActivationVisited;
17 final Map<VersionWithObjectiveValue, List<ActivationStoreEntry>> versionToActivations;
18
19 public ActivationStoreImpl(final int numberOfTransformations,
20 Consumer<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..e560f8c5
--- /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.api.factory.primitive.IntLists;
9import org.eclipse.collections.api.list.primitive.MutableIntList;
10
11public class ActivationStoreListEntry extends ActivationStoreEntry {
12 private final MutableIntList visitedActivations = IntLists.mutable.empty();
13
14 ActivationStoreListEntry(int numberOfActivations) {
15 super(numberOfActivations);
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..20a026b6
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/CompleteEquivalenceClassStore.java
@@ -0,0 +1,104 @@
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.factory.primitive.IntObjectMaps;
9import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
10import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
11import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
12import tools.refinery.store.statecoding.StateCoderResult;
13import tools.refinery.store.statecoding.StateCoderStoreAdapter;
14import tools.refinery.store.statecoding.StateEquivalenceChecker;
15
16import java.util.ArrayList;
17
18public abstract class CompleteEquivalenceClassStore extends AbstractEquivalenceClassStore implements EquivalenceClassStore {
19
20 static class SymmetryStoreArray extends ArrayList<VersionWithObjectiveValue> {
21 final int[] activationSizes;
22 final boolean accept;
23
24 SymmetryStoreArray(int[] activationSizes, boolean accept) {
25 super();
26 this.activationSizes = activationSizes;
27 this.accept = accept;
28 }
29 }
30
31 private final MutableIntObjectMap<Object> modelCode2Versions = IntObjectMaps.mutable.empty();
32
33 protected CompleteEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) {
34 super(stateCoderStoreAdapter);
35 }
36
37 @Override
38 protected boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion,
39 int[] emptyActivations, boolean accept) {
40 int modelCode = stateCoderResult.modelCode();
41 Object old = modelCode2Versions.updateValue(
42 modelCode,
43 () -> newVersion,
44 x -> {
45 if (x instanceof SymmetryStoreArray array) {
46 if(array.accept != accept || array.activationSizes != emptyActivations) {
47 this.delegate(newVersion,emptyActivations,accept);
48 return x;
49 }
50 array.add(newVersion);
51 return array;
52 } else {
53 SymmetryStoreArray result = new SymmetryStoreArray(emptyActivations, accept);
54 result.add((VersionWithObjectiveValue) x);
55 result.add(newVersion);
56 return result;
57 }
58 });
59 return old == null;
60 }
61
62 @Override
63 public void resolveOneSymmetry() {
64 var unresolvedSimilarity = getOneUnresolvedSymmetry();
65 if (unresolvedSimilarity == null) {
66 return;
67 }
68 var outcome = this.stateCoderStoreAdapter.checkEquivalence(unresolvedSimilarity.get(0).version(),
69 unresolvedSimilarity.get(1).version());
70 if (outcome != StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC) {
71 delegate(unresolvedSimilarity.get(1), unresolvedSimilarity.activationSizes, unresolvedSimilarity.accept);
72 }
73 }
74
75 //record UnresolvedSymmetryResult
76
77 private synchronized SymmetryStoreArray getOneUnresolvedSymmetry() {
78 if (numberOfUnresolvedSymmetries <= 0) {
79 return null;
80 }
81
82 for (var entry : modelCode2Versions.keyValuesView()) {
83 int hash = entry.getOne();
84 var value = entry.getTwo();
85 if (value instanceof SymmetryStoreArray array) {
86 int size = array.size();
87 var representative = array.get(0);
88 var similar = array.get(size - 1);
89 array.remove(size - 1);
90
91 if (size <= 2) {
92 modelCode2Versions.put(hash, representative);
93 }
94
95 var result = new SymmetryStoreArray(array.activationSizes, array.accept);
96 result.add(representative);
97 result.add(similar);
98 return result;
99 }
100 }
101
102 return null;
103 }
104}
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..6ee8e196
--- /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.api.factory.primitive.IntSets;
9import org.eclipse.collections.api.set.primitive.MutableIntSet;
10import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
11import tools.refinery.store.dse.transition.statespace.EquivalenceClassStore;
12import tools.refinery.store.statecoding.StateCoderResult;
13import tools.refinery.store.statecoding.StateCoderStoreAdapter;
14
15public abstract class FastEquivalenceClassStore extends AbstractEquivalenceClassStore implements EquivalenceClassStore {
16
17 private final MutableIntSet codes = IntSets.mutable.empty();
18
19 public FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) {
20 super(stateCoderStoreAdapter);
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
new file mode 100644
index 00000000..36517709
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java
@@ -0,0 +1,277 @@
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.dse.transition.TransformationRule;
9import tools.refinery.store.query.dnf.Query;
10import tools.refinery.store.query.dnf.RelationalQuery;
11import tools.refinery.store.query.view.AnySymbolView;
12import tools.refinery.store.query.view.KeyOnlyView;
13import tools.refinery.store.representation.Symbol;
14import tools.refinery.store.tuple.Tuple;
15
16import java.util.List;
17
18import static tools.refinery.store.query.literal.Literals.not;
19
20class CRAExamplesTest {
21
22 private static final Symbol<String> name = Symbol.of("Name", 1, String.class);
23
24// private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
25 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
26// private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
27 private static final Symbol<Boolean> attribute = Symbol.of("Attribute", 1);
28 private static final Symbol<Boolean> method = Symbol.of("Method", 1);
29
30// private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
31 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
32 private static final Symbol<Boolean> dataDependency = Symbol.of("DataDependency", 2);
33 private static final Symbol<Boolean> functionalDependency = Symbol.of("FunctionalDependency", 2);
34
35 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
36 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
37
38// private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
39 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
40// private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
41 private static final AnySymbolView attributeView = new KeyOnlyView<>(attribute);
42 private static final AnySymbolView methodView = new KeyOnlyView<>(method);
43// private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
44 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
45 private static final AnySymbolView dataDependencyView = new KeyOnlyView<>(dataDependency);
46 private static final AnySymbolView functionalDependencyView = new KeyOnlyView<>(functionalDependency);
47 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
48 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
49
50 /*Example Transformation rules*/
51 private static final RelationalQuery feature = Query.of("Feature",
52 (builder, f) -> builder.clause(
53 attributeView.call(f))
54 .clause(
55 methodView.call(f))
56 );
57
58 private static final RelationalQuery assignFeaturePreconditionHelper = Query.of("AssignFeaturePreconditionHelper",
59 (builder, c, f) -> builder.clause(
60 classElementView.call(c),
61// classesView.call(model, c),
62 encapsulatesView.call(c, f)
63 ));
64
65 private static final RelationalQuery assignFeaturePrecondition = Query.of("AssignFeaturePrecondition",
66 (builder, f, c1) -> builder.clause((c2) -> List.of(
67// classModelView.call(model),
68 feature.call(f),
69 classElementView.call(c1),
70// featuresView.call(model, f),
71 not(assignFeaturePreconditionHelper.call(c2, f)),
72 not(encapsulatesView.call(c1, f))
73 )));
74
75 private static final RelationalQuery deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
76 (builder, c) -> builder.clause((f) -> List.of(
77// classModelView.call(model),
78 classElementView.call(c),
79// featuresView.call(model, f),
80 not(encapsulatesView.call(c, f))
81 )));
82
83 private static final RelationalQuery createClassPreconditionHelper = Query.of("CreateClassPreconditionHelper",
84 (builder, f, c) -> builder.clause(
85 classElementView.call(c),
86// classesView.call(model, c),
87 encapsulatesView.call(c, f)
88 ));
89
90 private static final RelationalQuery createClassPrecondition = Query.of("CreateClassPrecondition",
91 (builder, f) -> builder.clause((c) -> List.of(
92// classModelView.call(model),
93 feature.call(f),
94 not(createClassPreconditionHelper.call(f, c))
95 )));
96
97 private static final RelationalQuery moveFeaturePrecondition = Query.of("MoveFeature",
98 (builder, c1, c2, f) -> builder.clause(
99// classModelView.call(model),
100 classElementView.call(c1),
101 classElementView.call(c2),
102 c1.notEquivalent(c2),
103 feature.call(f),
104// classesView.call(model, c1),
105// classesView.call(model, c2),
106// featuresView.call(model, f),
107 encapsulatesView.call(c1, f)
108 ));
109
110 private static final TransformationRule assignFeatureRule = new TransformationRule("AssignFeature",
111 assignFeaturePrecondition,
112 (model) -> {
113// var isEncapsulatedByInterpretation = model.getInterpretation(isEncapsulatedBy);
114 var encapsulatesInterpretation = model.getInterpretation(encapsulates);
115 return ((Tuple activation) -> {
116 var feature = activation.get(0);
117 var classElement = activation.get(1);
118
119// isEncapsulatedByInterpretation.put(Tuple.of(feature, classElement), true);
120 encapsulatesInterpretation.put(Tuple.of(classElement, feature), true);
121 });
122 });
123
124// private static final TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
125// deleteEmptyClassPrecondition,
126// (model) -> {
127//// var classesInterpretation = model.getInterpretation(classes);
128// var classElementInterpretation = model.getInterpretation(classElement);
129// return ((Tuple activation) -> {
130// // TODO: can we move dseAdapter outside?
131// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
132//// var modelElement = activation.get(0);
133// var classElement = activation.get(0);
134//
135//// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
136// classElementInterpretation.put(Tuple.of(classElement), false);
137// dseAdapter.deleteObject(Tuple.of(classElement));
138// });
139// });
140
141// private static final TransformationRule createClassRule = new TransformationRule("CreateClass",
142// createClassPrecondition,
143// (model) -> {
144// var classElementInterpretation = model.getInterpretation(classElement);
145//// var classesInterpretation = model.getInterpretation(classes);
146// var encapsulatesInterpretation = model.getInterpretation(encapsulates);
147// return ((Tuple activation) -> {
148// // TODO: can we move dseAdapter outside?
149// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
150//// var modelElement = activation.get(0);
151// var feature = activation.get(0);
152//
153// var newClassElement = dseAdapter.createObject();
154// var newClassElementId = newClassElement.get(0);
155// classElementInterpretation.put(newClassElement, true);
156//// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
157// encapsulatesInterpretation.put(Tuple.of(newClassElementId, feature), true);
158// });
159// });
160
161 private static final TransformationRule moveFeatureRule = new TransformationRule("MoveFeature",
162 moveFeaturePrecondition,
163 (model) -> {
164 var encapsulatesInterpretation = model.getInterpretation(encapsulates);
165 return ((Tuple activation) -> {
166 var classElement1 = activation.get(0);
167 var classElement2 = activation.get(1);
168 var feature = activation.get(2);
169
170 encapsulatesInterpretation.put(Tuple.of(classElement1, feature), false);
171 encapsulatesInterpretation.put(Tuple.of(classElement2, feature), true);
172 });
173 });
174
175// @Test
176// @Disabled("This test is only for debugging purposes")
177// void craTest() {
178// var store = ModelStore.builder()
179// .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency,
180// functionalDependency, name)
181// .with(ViatraModelQueryAdapter.builder()
182// .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition,
183// deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition,
184// moveFeaturePrecondition))
185// .with(ModelVisualizerAdapter.builder()
186// .withOutputpath("test_output")
187// .withFormat(FileFormat.DOT)
188// .withFormat(FileFormat.SVG)
189// .saveStates()
190// .saveDesignSpace()
191// )
192// .with(DesignSpaceExplorationAdapter.builder()
193// .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule)
194// .objectives(new AlwaysSatisfiedRandomHardObjective())
195//// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled()
196// .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled()
197//// .goOnOnlyIfFitnessIsBetter()
198// ))
199// .build();
200//
201// var model = store.createEmptyModel();
202// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
203//// dseAdapter.setRandom(1);
204// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
205//
206//// var modelInterpretation = model.getInterpretation(classModel);
207// var nameInterpretation = model.getInterpretation(name);
208// var methodInterpretation = model.getInterpretation(method);
209// var attributeInterpretation = model.getInterpretation(attribute);
210// var dataDependencyInterpretation = model.getInterpretation(dataDependency);
211// var functionalDependencyInterpretation = model.getInterpretation(functionalDependency);
212//
213//// var modelElement = dseAdapter.createObject();
214// var method1 = dseAdapter.createObject();
215// var method1Id = method1.get(0);
216// var method2 = dseAdapter.createObject();
217// var method2Id = method2.get(0);
218// var method3 = dseAdapter.createObject();
219// var method3Id = method3.get(0);
220// var method4 = dseAdapter.createObject();
221// var method4Id = method4.get(0);
222// var attribute1 = dseAdapter.createObject();
223// var attribute1Id = attribute1.get(0);
224// var attribute2 = dseAdapter.createObject();
225// var attribute2Id = attribute2.get(0);
226// var attribute3 = dseAdapter.createObject();
227// var attribute3Id = attribute3.get(0);
228// var attribute4 = dseAdapter.createObject();
229// var attribute4Id = attribute4.get(0);
230// var attribute5 = dseAdapter.createObject();
231// var attribute5Id = attribute5.get(0);
232//
233// nameInterpretation.put(method1, "M1");
234// nameInterpretation.put(method2, "M2");
235// nameInterpretation.put(method3, "M3");
236// nameInterpretation.put(method4, "M4");
237// nameInterpretation.put(attribute1, "A1");
238// nameInterpretation.put(attribute2, "A2");
239// nameInterpretation.put(attribute3, "A3");
240// nameInterpretation.put(attribute4, "A4");
241// nameInterpretation.put(attribute5, "A5");
242//
243//
244//
245//// modelInterpretation.put(modelElement, true);
246// methodInterpretation.put(method1, true);
247// methodInterpretation.put(method2, true);
248// methodInterpretation.put(method3, true);
249// methodInterpretation.put(method4, true);
250// attributeInterpretation.put(attribute1, true);
251// attributeInterpretation.put(attribute2, true);
252// attributeInterpretation.put(attribute3, true);
253// attributeInterpretation.put(attribute4, true);
254// attributeInterpretation.put(attribute5, true);
255//
256// dataDependencyInterpretation.put(Tuple.of(method1Id, attribute1Id), true);
257// dataDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true);
258// dataDependencyInterpretation.put(Tuple.of(method2Id, attribute2Id), true);
259// dataDependencyInterpretation.put(Tuple.of(method3Id, attribute3Id), true);
260// dataDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true);
261// dataDependencyInterpretation.put(Tuple.of(method4Id, attribute3Id), true);
262// dataDependencyInterpretation.put(Tuple.of(method4Id, attribute5Id), true);
263//
264// functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true);
265// functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute4Id), true);
266// functionalDependencyInterpretation.put(Tuple.of(method2Id, attribute1Id), true);
267// functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute1Id), true);
268// functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true);
269// functionalDependencyInterpretation.put(Tuple.of(method4Id, attribute2Id), true);
270//
271// queryEngine.flushChanges();
272//
273// var states = dseAdapter.explore();
274// System.out.println("states size: " + states.size());
275// }
276//*/
277}
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
new file mode 100644
index 00000000..1d757a5f
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java
@@ -0,0 +1,116 @@
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.query.view.AnySymbolView;
9import tools.refinery.store.query.view.KeyOnlyView;
10import tools.refinery.store.representation.Symbol;
11
12class DebugTest {
13 private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
14 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
15 private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
16
17 private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
18 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
19
20 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
21 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
22
23 private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
24 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
25 private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
26 private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
27 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
28 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
29 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
30
31
32// @Test
33// @Disabled("This test is only for debugging purposes")
34// void BFSTest() {
35// var createClassPrecondition = Query.of("CreateClassPrecondition",
36// (builder, model) -> builder.clause(
37// classModelView.call(model)
38// ));
39//
40// var createClassRule = new TransformationRule("CreateClass",
41// createClassPrecondition,
42// (model) -> {
43// var classesInterpretation = model.getInterpretation(classes);
44// var classElementInterpretation = model.getInterpretation(classElement);
45// return ((Tuple activation) -> {
46// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
47// var modelElement = activation.get(0);
48//
49// var newClassElement = dseAdapter.createObject();
50// var newClassElementId = newClassElement.get(0);
51//
52// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
53// classElementInterpretation.put(Tuple.of(newClassElementId), true);
54// });
55// });
56//
57// var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
58// (builder, model) -> builder.clause(
59// classModelView.call(model)
60// ));
61//
62// var createFeatureRule = new TransformationRule("CreateFeature",
63// createFeaturePrecondition,
64// (model) -> {
65// var featuresInterpretation = model.getInterpretation(features);
66// var featureInterpretation = model.getInterpretation(feature);
67// return ((Tuple activation) -> {
68// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
69// var modelElement = activation.get(0);
70//
71// var newClassElement = dseAdapter.createObject();
72// var newClassElementId = newClassElement.get(0);
73//
74// featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
75// featureInterpretation.put(Tuple.of(newClassElementId), true);
76// });
77// });
78//
79// var store = ModelStore.builder()
80// .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
81// .with(ViatraModelQueryAdapter.builder()
82// .queries(createClassPrecondition, createFeaturePrecondition))
83// .with(ModelVisualizerAdapter.builder()
84// .withOutputpath("test_output")
85// .withFormat(FileFormat.DOT)
86// .withFormat(FileFormat.SVG)
87// .saveStates()
88// .saveDesignSpace()
89// )
90// .with(DesignSpaceExplorationAdapter.builder()
91// .transformations(createClassRule, createFeatureRule)
92// .objectives(new AlwaysSatisfiedRandomHardObjective())
93// .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
94//// .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
95//// .goOnOnlyIfFitnessIsBetter()
96// ))
97// .build();
98//
99// var model = store.createEmptyModel();
100// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
101//// dseAdapter.setRandom(1);
102// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
103//
104// var modelElementInterpretation = model.getInterpretation(classModel);
105// var classElementInterpretation = model.getInterpretation(classElement);
106// var modelElement = dseAdapter.createObject();
107// modelElementInterpretation.put(modelElement, true);
108// classElementInterpretation.put(modelElement, true);
109// queryEngine.flushChanges();
110//
111//
112// var states = dseAdapter.explore();
113// System.out.println("states size: " + states.size());
114//
115// }
116}
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
new file mode 100644
index 00000000..f5f13433
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java
@@ -0,0 +1,596 @@
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.query.view.AnySymbolView;
9import tools.refinery.store.query.view.KeyOnlyView;
10import tools.refinery.store.representation.Symbol;
11
12class DesignSpaceExplorationTest {
13// private static final Symbol<Boolean> namedElement = Symbol.of("NamedElement", 1);
14// private static final Symbol<Boolean> attribute = Symbol.of("Attribute", 1);
15// private static final Symbol<Boolean> method = Symbol.of("Method", 1);
16// private static final Symbol<Boolean> dataDependency = Symbol.of("DataDependency", 2);
17// private static final Symbol<Boolean> functionalDependency = Symbol.of("FunctionalDependency", 2);
18
19 private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
20 private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
21 private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
22
23 private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
24 private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
25
26 private static final Symbol<Boolean> features = Symbol.of("Features", 2);
27 private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
28
29 private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
30 private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
31 private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
32 private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
33 private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
34 private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
35 private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
36
37// @Test
38// void createObjectTest() {
39// var store = ModelStore.builder()
40// .with(ViatraModelQueryAdapter.builder())
41// .with(DesignSpaceExplorationAdapter.builder()
42// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
43// .build();
44//
45// var model = store.createEmptyModel();
46// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
47//
48// assertEquals(0, dseAdapter.getModelSize());
49//
50// var newModel = dseAdapter.createObject();
51// var newModelId = newModel.get(0);
52// var newClass1 = dseAdapter.createObject();
53// var newClass1Id = newClass1.get(0);
54// var newClass2 = dseAdapter.createObject();
55// var newClass2Id = newClass2.get(0);
56// var newField = dseAdapter.createObject();
57// var newFieldId = newField.get(0);
58//
59// assertEquals(0, newModelId);
60// assertEquals(1, newClass1Id);
61// assertEquals(2, newClass2Id);
62// assertEquals(3, newFieldId);
63// assertEquals(4, dseAdapter.getModelSize());
64// }
65
66// @Test
67// void deleteMiddleObjectTest() {
68// var store = ModelStore.builder()
69// .with(ViatraModelQueryAdapter.builder())
70// .with(DesignSpaceExplorationAdapter.builder()
71// .strategy(new DepthFirstStrategy()))
72// .build();
73//
74// var model = store.createEmptyModel();
75// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
76//
77// assertEquals(0, dseAdapter.getModelSize());
78//
79// var newObject0 = dseAdapter.createObject();
80// var newObject0Id = newObject0.get(0);
81// var newObject1 = dseAdapter.createObject();
82// var newObject1Id = newObject1.get(0);
83// var newObject2 = dseAdapter.createObject();
84// var newObject2Id = newObject2.get(0);
85// var newObject3 = dseAdapter.createObject();
86// var newObject3Id = newObject3.get(0);
87//
88// assertEquals(0, newObject0Id);
89// assertEquals(1, newObject1Id);
90// assertEquals(2, newObject2Id);
91// assertEquals(3, newObject3Id);
92// assertEquals(4, dseAdapter.getModelSize());
93//
94// dseAdapter.deleteObject(newObject1);
95// assertEquals(4, dseAdapter.getModelSize());
96//
97// var newObject4 = dseAdapter.createObject();
98// var newObject4Id = newObject4.get(0);
99// assertEquals(4, newObject4Id);
100// assertEquals(5, dseAdapter.getModelSize());
101//
102// dseAdapter.deleteObject(newObject4);
103// assertEquals(5, dseAdapter.getModelSize());
104// }
105//
106// @Test
107// void DFSTrivialTest() {
108// var store = ModelStore.builder()
109// .symbols(classModel)
110// .with(ViatraModelQueryAdapter.builder())
111// .with(DesignSpaceExplorationAdapter.builder()
112// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
113// .build();
114//
115// var model = store.createEmptyModel();
116// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
117//
118// var states = dseAdapter.explore();
119// assertEquals(1, states.size());
120// }
121//
122// @Test
123// void DFSOneRuleTest() {
124// var createClassPrecondition = Query.of("CreateClassPrecondition",
125// (builder, model) -> builder.clause(
126// classModelView.call(model)
127// ));
128//
129// var createClassRule = new TransformationRule("CreateClass",
130// createClassPrecondition,
131// (model) -> {
132// var classesInterpretation = model.getInterpretation(classes);
133// var classElementInterpretation = model.getInterpretation(classElement);
134// return ((Tuple activation) -> {
135// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
136// var modelElement = activation.get(0);
137//
138// var newClassElement = dseAdapter.createObject();
139// var newClassElementId = newClassElement.get(0);
140//
141// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
142// classElementInterpretation.put(Tuple.of(newClassElementId), true);
143// });
144// });
145//
146// var store = ModelStore.builder()
147// .symbols(classModel, classElement, classes)
148// .with(ViatraModelQueryAdapter.builder()
149// .queries(createClassPrecondition))
150// .with(DesignSpaceExplorationAdapter.builder()
151// .transformations(createClassRule)
152// .strategy(new DepthFirstStrategy().withDepthLimit(0)
153// ))
154// .build();
155//
156// var model = store.createEmptyModel();
157// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
158// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
159//
160// var modelElementInterpretation = model.getInterpretation(classModel);
161// modelElementInterpretation.put(dseAdapter.createObject(), true);
162// queryEngine.flushChanges();
163//
164// var states = dseAdapter.explore();
165// assertEquals(1, states.size());
166// }
167//
168// @Test
169// void DFSContinueTest() {
170// var createClassPrecondition = Query.of("CreateClassPrecondition",
171// (builder, model) -> builder.clause(
172// classModelView.call(model)
173// ));
174//
175// var createClassRule = new TransformationRule("CreateClass",
176// createClassPrecondition,
177// (model) -> {
178// var classesInterpretation = model.getInterpretation(classes);
179// var classElementInterpretation = model.getInterpretation(classElement);
180// return ((Tuple activation) -> {
181// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
182// var modelElement = activation.get(0);
183//
184// var newClassElement = dseAdapter.createObject();
185// var newClassElementId = newClassElement.get(0);
186//
187// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
188// classElementInterpretation.put(Tuple.of(newClassElementId), true);
189// });
190// });
191//
192// var store = ModelStore.builder()
193// .symbols(classModel, classElement, classes)
194// .with(ViatraModelQueryAdapter.builder()
195// .queries(createClassPrecondition))
196// .with(DesignSpaceExplorationAdapter.builder()
197// .transformations(createClassRule)
198// .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
199// ))
200// .build();
201//
202// var model = store.createEmptyModel();
203// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
204// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
205//
206// var modelElementInterpretation = model.getInterpretation(classModel);
207// modelElementInterpretation.put(dseAdapter.createObject(), true);
208// queryEngine.flushChanges();
209//
210// var states = dseAdapter.explore();
211// assertEquals(5, states.size());
212// }
213//
214// @Test
215// void DFSCompletenessTest() {
216// var createClassPrecondition = Query.of("CreateClassPrecondition",
217// (builder, model) -> builder.clause(
218// classModelView.call(model)
219// ));
220//
221// var createClassRule = new TransformationRule("CreateClass",
222// createClassPrecondition,
223// (model) -> {
224// var classesInterpretation = model.getInterpretation(classes);
225// var classElementInterpretation = model.getInterpretation(classElement);
226// return ((Tuple activation) -> {
227// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
228// var modelElement = activation.get(0);
229//
230// var newClassElement = dseAdapter.createObject();
231// var newClassElementId = newClassElement.get(0);
232//
233// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
234// classElementInterpretation.put(Tuple.of(newClassElementId), true);
235// });
236// });
237//
238// var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
239// (builder, model) -> builder.clause(
240// classModelView.call(model)
241// ));
242//
243// var createFeatureRule = new TransformationRule("CreateFeature",
244// createFeaturePrecondition,
245// (model) -> {
246// var featuresInterpretation = model.getInterpretation(features);
247// var featureInterpretation = model.getInterpretation(feature);
248// return ((Tuple activation) -> {
249// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
250// var modelElement = activation.get(0);
251//
252// var newClassElement = dseAdapter.createObject();
253// var newClassElementId = newClassElement.get(0);
254//
255// featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
256// featureInterpretation.put(Tuple.of(newClassElementId), true);
257// });
258// });
259//
260// var store = ModelStore.builder()
261// .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
262// .with(ViatraModelQueryAdapter.builder()
263// .queries(createClassPrecondition, createFeaturePrecondition))
264// .with(DesignSpaceExplorationAdapter.builder()
265// .transformations(createClassRule, createFeatureRule)
266// .strategy(new DepthFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
267// ))
268// .build();
269//
270// var model = store.createEmptyModel();
271// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
272// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
273//
274// var modelElementInterpretation = model.getInterpretation(classModel);
275// modelElementInterpretation.put(dseAdapter.createObject(), true);
276// queryEngine.flushChanges();
277//
278// var states = dseAdapter.explore();
279// assertEquals(2047, states.size());
280// }
281//
282// @Test
283// void DFSSolutionLimitTest() {
284// var createClassPrecondition = Query.of("CreateClassPrecondition",
285// (builder, model) -> builder.clause(
286// classModelView.call(model)
287// ));
288//
289// var createClassRule = new TransformationRule("CreateClass",
290// createClassPrecondition,
291// (model) -> {
292// var classesInterpretation = model.getInterpretation(classes);
293// var classElementInterpretation = model.getInterpretation(classElement);
294// return ((Tuple activation) -> {
295// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
296// var modelElement = activation.get(0);
297//
298// var newClassElement = dseAdapter.createObject();
299// var newClassElementId = newClassElement.get(0);
300//
301// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
302// classElementInterpretation.put(Tuple.of(newClassElementId), true);
303// });
304// });
305//
306// var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
307// (builder, model) -> builder.clause(
308// classModelView.call(model)
309// ));
310//
311// var createFeatureRule = new TransformationRule("CreateFeature",
312// createFeaturePrecondition,
313// (model) -> {
314// var featuresInterpretation = model.getInterpretation(features);
315// var featureInterpretation = model.getInterpretation(feature);
316// return ((Tuple activation) -> {
317// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
318// var modelElement = activation.get(0);
319//
320// var newClassElement = dseAdapter.createObject();
321// var newClassElementId = newClassElement.get(0);
322//
323// featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
324// featureInterpretation.put(Tuple.of(newClassElementId), true);
325// });
326// });
327//
328// var store = ModelStore.builder()
329// .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
330// .with(ViatraModelQueryAdapter.builder()
331// .queries(createClassPrecondition, createFeaturePrecondition))
332// .with(DesignSpaceExplorationAdapter.builder()
333// .transformations(createClassRule, createFeatureRule)
334// .strategy(new DepthFirstStrategy().withSolutionLimit(222)
335// .continueIfHardObjectivesFulfilled()
336// ))
337// .build();
338//
339// var model = store.createEmptyModel();
340// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
341// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
342//
343// var modelElementInterpretation = model.getInterpretation(classModel);
344// modelElementInterpretation.put(dseAdapter.createObject(), true);
345// queryEngine.flushChanges();
346//
347// var states = dseAdapter.explore();
348// assertEquals(222, states.size());
349// }
350//
351// @Test
352// void BeFSTrivialTest() {
353// var store = ModelStore.builder()
354// .symbols(classModel)
355// .with(ViatraModelQueryAdapter.builder())
356// .with(DesignSpaceExplorationAdapter.builder()
357// .strategy(new BestFirstStrategy().withDepthLimit(0)))
358// .build();
359//
360// var model = store.createEmptyModel();
361// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
362//
363// var states = dseAdapter.explore();
364// assertEquals(1, states.size());
365// }
366//
367// @Test
368// void BeFSOneRuleTest() {
369// var createClassPrecondition = Query.of("CreateClassPrecondition",
370// (builder, model) -> builder.clause(
371// classModelView.call(model)
372// ));
373//
374// var createClassRule = new TransformationRule("CreateClass",
375// createClassPrecondition,
376// (model) -> {
377// var classesInterpretation = model.getInterpretation(classes);
378// var classElementInterpretation = model.getInterpretation(classElement);
379// return ((Tuple activation) -> {
380// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
381// var modelElement = activation.get(0);
382//
383// var newClassElement = dseAdapter.createObject();
384// var newClassElementId = newClassElement.get(0);
385//
386// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
387// classElementInterpretation.put(Tuple.of(newClassElementId), true);
388// });
389// });
390//
391// var store = ModelStore.builder()
392// .symbols(classModel, classElement, classes)
393// .with(ViatraModelQueryAdapter.builder()
394// .queries(createClassPrecondition))
395// .with(DesignSpaceExplorationAdapter.builder()
396// .transformations(createClassRule)
397// .strategy(new BestFirstStrategy().withDepthLimit(4)
398// ))
399// .build();
400//
401// var model = store.createEmptyModel();
402// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
403// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
404//
405// var modelElementInterpretation = model.getInterpretation(classModel);
406// modelElementInterpretation.put(dseAdapter.createObject(), true);
407// queryEngine.flushChanges();
408//
409// var states = dseAdapter.explore();
410// assertEquals(1, states.size());
411// }
412//
413// @Test
414// void BeFSContinueTest() {
415// var createClassPrecondition = Query.of("CreateClassPrecondition",
416// (builder, model) -> builder.clause(
417// classModelView.call(model)
418// ));
419//
420// var createClassRule = new TransformationRule("CreateClass",
421// createClassPrecondition,
422// (model) -> {
423// var classesInterpretation = model.getInterpretation(classes);
424// var classElementInterpretation = model.getInterpretation(classElement);
425// return ((Tuple activation) -> {
426// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
427// var modelElement = activation.get(0);
428//
429// var newClassElement = dseAdapter.createObject();
430// var newClassElementId = newClassElement.get(0);
431//
432// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
433// classElementInterpretation.put(Tuple.of(newClassElementId), true);
434// });
435// });
436//
437// var store = ModelStore.builder()
438// .symbols(classModel, classElement, classes)
439// .with(ViatraModelQueryAdapter.builder()
440// .queries(createClassPrecondition))
441// .with(DesignSpaceExplorationAdapter.builder()
442// .transformations(createClassRule)
443// .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled()
444// ))
445// .build();
446//
447// var model = store.createEmptyModel();
448// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
449// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
450//
451// var modelElementInterpretation = model.getInterpretation(classModel);
452// modelElementInterpretation.put(dseAdapter.createObject(), true);
453// queryEngine.flushChanges();
454//
455// var states = dseAdapter.explore();
456// assertEquals(5, states.size());
457// }
458//
459// @Test
460// void BeFSCompletenessTest() {
461// var createClassPrecondition = Query.of("CreateClassPrecondition",
462// (builder, model) -> builder.clause(
463// classModelView.call(model)
464// ));
465//
466// var createClassRule = new TransformationRule("CreateClass",
467// createClassPrecondition,
468// (model) -> {
469// var classesInterpretation = model.getInterpretation(classes);
470// var classElementInterpretation = model.getInterpretation(classElement);
471// return ((Tuple activation) -> {
472// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
473// var modelElement = activation.get(0);
474//
475// var newClassElement = dseAdapter.createObject();
476// var newClassElementId = newClassElement.get(0);
477//
478// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
479// classElementInterpretation.put(Tuple.of(newClassElementId), true);
480// });
481// });
482//
483// var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
484// (builder, model) -> builder.clause(
485// classModelView.call(model)
486// ));
487//
488// var createFeatureRule = new TransformationRule("CreateFeature",
489// createFeaturePrecondition,
490// (model) -> {
491// var featuresInterpretation = model.getInterpretation(features);
492// var featureInterpretation = model.getInterpretation(feature);
493// return ((Tuple activation) -> {
494// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
495// var modelElement = activation.get(0);
496//
497// var newClassElement = dseAdapter.createObject();
498// var newClassElementId = newClassElement.get(0);
499//
500// featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
501// featureInterpretation.put(Tuple.of(newClassElementId), true);
502// });
503// });
504//
505// var store = ModelStore.builder()
506// .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
507// .with(ViatraModelQueryAdapter.builder()
508// .queries(createClassPrecondition, createFeaturePrecondition))
509// .with(DesignSpaceExplorationAdapter.builder()
510// .transformations(createClassRule, createFeatureRule)
511// .strategy(new BestFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled()
512// ))
513// .build();
514//
515// var model = store.createEmptyModel();
516// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
517// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
518//
519// var modelElementInterpretation = model.getInterpretation(classModel);
520// modelElementInterpretation.put(dseAdapter.createObject(), true);
521// queryEngine.flushChanges();
522//
523// var states = dseAdapter.explore();
524// assertEquals(2047, states.size());
525// }
526//
527// @Test
528// void BeFSSolutionLimitTest() {
529// var createClassPrecondition = Query.of("CreateClassPrecondition",
530// (builder, model) -> builder.clause(
531// classModelView.call(model)
532// ));
533//
534// var createClassRule = new TransformationRule("CreateClass",
535// createClassPrecondition,
536// (model) -> {
537// var classesInterpretation = model.getInterpretation(classes);
538// var classElementInterpretation = model.getInterpretation(classElement);
539// return ((Tuple activation) -> {
540// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
541// var modelElement = activation.get(0);
542//
543// var newClassElement = dseAdapter.createObject();
544// var newClassElementId = newClassElement.get(0);
545//
546// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
547// classElementInterpretation.put(Tuple.of(newClassElementId), true);
548// });
549// });
550//
551// var createFeaturePrecondition = Query.of("CreateFeaturePrecondition",
552// (builder, model) -> builder.clause(
553// classModelView.call(model)
554// ));
555//
556// var createFeatureRule = new TransformationRule("CreateFeature",
557// createFeaturePrecondition,
558// (model) -> {
559// var featuresInterpretation = model.getInterpretation(features);
560// var featureInterpretation = model.getInterpretation(feature);
561// return ((Tuple activation) -> {
562// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
563// var modelElement = activation.get(0);
564//
565// var newClassElement = dseAdapter.createObject();
566// var newClassElementId = newClassElement.get(0);
567//
568// featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true);
569// featureInterpretation.put(Tuple.of(newClassElementId), true);
570// });
571// });
572//
573// var store = ModelStore.builder()
574// .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates)
575// .with(ViatraModelQueryAdapter.builder()
576// .queries(createClassPrecondition, createFeaturePrecondition))
577// .with(DesignSpaceExplorationAdapter.builder()
578// .transformations(createClassRule, createFeatureRule)
579// .strategy(new BestFirstStrategy().withSolutionLimit(222)
580// .continueIfHardObjectivesFulfilled()
581// ))
582// .build();
583//
584// var model = store.createEmptyModel();
585// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
586// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
587//
588// var modelElementInterpretation = model.getInterpretation(classModel);
589// modelElementInterpretation.put(dseAdapter.createObject(), true);
590// queryEngine.flushChanges();
591//
592// var states = dseAdapter.explore();
593// assertEquals(222, states.size());
594// }
595
596}
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
new file mode 100644
index 00000000..43b04e0d
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java
@@ -0,0 +1,414 @@
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 org.junit.jupiter.api.Test;
9//
10//import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
11//import tools.refinery.store.model.ModelStore;
12//import tools.refinery.store.query.ModelQueryAdapter;
13//import tools.refinery.store.query.dnf.Query;
14//import tools.refinery.store.dse.transition.TransformationRule;
15//import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
16//import tools.refinery.store.query.view.AnySymbolView;
17//import tools.refinery.store.query.view.KeyOnlyView;
18//import tools.refinery.store.representation.Symbol;
19//import tools.refinery.store.tuple.Tuple;
20//
21//import java.util.List;
22//import java.util.Map;
23//
24//import static org.junit.jupiter.api.Assertions.assertEquals;
25//import static tools.refinery.store.query.literal.Literals.not;
26//import static tools.refinery.store.dse.tests.QueryAssertions.assertResults;
27//
28class TransformationRuleTest {
29//
30// private static final Symbol<Boolean> classModel = Symbol.of("ClassModel", 1);
31// private static final Symbol<Boolean> classElement = Symbol.of("ClassElement", 1);
32// private static final Symbol<Boolean> feature = Symbol.of("Feature", 1);
33//
34// private static final Symbol<Boolean> isEncapsulatedBy = Symbol.of("IsEncapsulatedBy", 2);
35// private static final Symbol<Boolean> encapsulates = Symbol.of("Encapsulates", 2);
36//
37// private static final Symbol<Boolean> features = Symbol.of("Features", 2);
38// private static final Symbol<Boolean> classes = Symbol.of("Classes", 2);
39//
40// private static final AnySymbolView classModelView = new KeyOnlyView<>(classModel);
41// private static final AnySymbolView classElementView = new KeyOnlyView<>(classElement);
42// private static final AnySymbolView featureView = new KeyOnlyView<>(feature);
43// private static final AnySymbolView isEncapsulatedByView = new KeyOnlyView<>(isEncapsulatedBy);
44// private static final AnySymbolView encapsulatesView = new KeyOnlyView<>(encapsulates);
45// private static final AnySymbolView featuresView = new KeyOnlyView<>(features);
46// private static final AnySymbolView classesView = new KeyOnlyView<>(classes);
47//
48// @Test
49// void activationsTest() {
50// var assignFeaturePreconditionHelper = Query.of("AssignFeaturePreconditionHelper",
51// (builder, model, c, f) -> builder.clause(
52// classElementView.call(c),
53// classesView.call(model, c),
54// encapsulatesView.call(c, f)
55// ));
56//
57// var assignFeaturePrecondition = Query.of("AssignFeaturePrecondition", (builder, c2, f)
58// -> builder.clause((model, c1) -> List.of(
59// classModelView.call(model),
60// featureView.call(f),
61// classElementView.call(c2),
62// featuresView.call(model, f),
63// classesView.call(model, c1),
64// not(assignFeaturePreconditionHelper.call(model, c2, f)),
65// not(encapsulatesView.call(c2, f))
66// )));
67//
68// var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
69// (builder, model, c) -> builder.clause((f) -> List.of(
70// classModelView.call(model),
71// classElementView.call(c),
72// featuresView.call(model, f),
73// not(encapsulatesView.call(c, f))
74// )));
75//
76// TransformationRule assignFeatureRule = new TransformationRule("AssignFeature",
77// assignFeaturePrecondition,
78// (model) -> {
79// var isEncapsulatedByInterpretation = model.getInterpretation(isEncapsulatedBy);
80// return ((Tuple activation) -> {
81// var feature = activation.get(0);
82// var classElement = activation.get(1);
83//
84// isEncapsulatedByInterpretation.put(Tuple.of(feature, classElement), true);
85// });
86// });
87//
88// TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
89// deleteEmptyClassPrecondition,
90// (model) -> {
91// var classesInterpretation = model.getInterpretation(classes);
92// var classElementInterpretation = model.getInterpretation(classElement);
93// return ((Tuple activation) -> {
94// var modelElement = activation.get(0);
95// var classElement = activation.get(1);
96//
97// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
98// classElementInterpretation.put(Tuple.of(classElement), false);
99// });
100// });
101//
102//
103// var store = ModelStore.builder()
104// .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
105// .with(ViatraModelQueryAdapter.builder()
106// .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper,
107// deleteEmptyClassPrecondition))
108// .with(DesignSpaceExplorationAdapter.builder()
109// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
110// .build();
111//
112// var model = store.createEmptyModel();
113// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
114// assignFeatureRule.prepare(model, queryEngine);
115// deleteEmptyClassRule.prepare(model, queryEngine);
116//
117// var classModelInterpretation = model.getInterpretation(classModel);
118// var classElementInterpretation = model.getInterpretation(classElement);
119// var featureInterpretation = model.getInterpretation(feature);
120// var featuresInterpretation = model.getInterpretation(features);
121// var classesInterpretation = model.getInterpretation(classes);
122//
123// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
124// var newModel = dseAdapter.createObject();
125// var newModelId = newModel.get(0);
126// var newClass1 = dseAdapter.createObject();
127// var newClass1Id = newClass1.get(0);
128// var newClass2 = dseAdapter.createObject();
129// var newClass2Id = newClass2.get(0);
130// var newField = dseAdapter.createObject();
131// var newFieldId = newField.get(0);
132//
133// classModelInterpretation.put(newModel, true);
134// classElementInterpretation.put(newClass1, true);
135// classElementInterpretation.put(newClass2, true);
136// featureInterpretation.put(newField, true);
137// classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
138// classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
139// featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
140//
141// queryEngine.flushChanges();
142//
143// var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsResultSet();
144// var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsResultSet();
145//
146// assertResults(Map.of(
147// Tuple.of(newClass1Id, newFieldId), true,
148// Tuple.of(newClass2Id, newFieldId), true
149// ), assignFeatureRuleActivations);
150//
151// assertResults(Map.of(
152// Tuple.of(newModelId, newClass1Id), true,
153// Tuple.of(newModelId, newClass2Id), true
154// ), deleteEmptyClassRuleActivations);
155// }
156//
157// @Test
158// void randomActivationTest() {
159// var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
160// (builder, model, c) -> builder.clause((f) -> List.of(
161// classModelView.call(model),
162// classElementView.call(c),
163// featuresView.call(model, f),
164// not(encapsulatesView.call(c, f))
165// )));
166//
167// TransformationRule deleteEmptyClassRule0 = new TransformationRule("DeleteEmptyClass0",
168// deleteEmptyClassPrecondition,
169// (model) -> {
170// var classesInterpretation = model.getInterpretation(classes);
171// var classElementInterpretation = model.getInterpretation(classElement);
172// return ((Tuple activation) -> {
173// var modelElement = activation.get(0);
174// var classElement = activation.get(1);
175//
176// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
177// classElementInterpretation.put(Tuple.of(classElement), false);
178// });
179// },
180// 0L);
181//
182// TransformationRule deleteEmptyClassRule1 = new TransformationRule("DeleteEmptyClass1",
183// deleteEmptyClassPrecondition,
184// (model) -> {
185// var classesInterpretation = model.getInterpretation(classes);
186// var classElementInterpretation = model.getInterpretation(classElement);
187// return ((Tuple activation) -> {
188// var modelElement = activation.get(0);
189// var classElement = activation.get(1);
190//
191// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
192// classElementInterpretation.put(Tuple.of(classElement), false);
193// });
194// },
195// 78634L);
196//
197// var store = ModelStore.builder()
198// .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
199// .with(ViatraModelQueryAdapter.builder()
200// .queries(deleteEmptyClassPrecondition))
201// .with(DesignSpaceExplorationAdapter.builder()
202// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
203// .build();
204//
205// var model = store.createEmptyModel();
206// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
207// deleteEmptyClassRule0.prepare(model, queryEngine);
208// deleteEmptyClassRule1.prepare(model, queryEngine);
209//
210// var classModelInterpretation = model.getInterpretation(classModel);
211// var classElementInterpretation = model.getInterpretation(classElement);
212// var featureInterpretation = model.getInterpretation(feature);
213// var featuresInterpretation = model.getInterpretation(features);
214// var classesInterpretation = model.getInterpretation(classes);
215//
216// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
217// var newModel = dseAdapter.createObject();
218// var newModelId = newModel.get(0);
219// var newClass1 = dseAdapter.createObject();
220// var newClass1Id = newClass1.get(0);
221// var newClass2 = dseAdapter.createObject();
222// var newClass2Id = newClass2.get(0);
223// var newField = dseAdapter.createObject();
224// var newFieldId = newField.get(0);
225//
226// classModelInterpretation.put(newModel, true);
227// classElementInterpretation.put(newClass1, true);
228// classElementInterpretation.put(newClass2, true);
229// featureInterpretation.put(newField, true);
230// classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
231// classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
232// featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
233//
234// queryEngine.flushChanges();
235//
236//
237// var activation0 = deleteEmptyClassRule0.getRandomActivation().activation();
238// var activation1 = deleteEmptyClassRule1.getRandomActivation().activation();
239//
240// assertResults(Map.of(
241// Tuple.of(newModelId, newClass1Id), true,
242// Tuple.of(newModelId, newClass2Id), true
243// ), deleteEmptyClassRule0.getAllActivationsAsResultSet());
244//
245// assertResults(Map.of(
246// Tuple.of(newModelId, newClass1Id), true,
247// Tuple.of(newModelId, newClass2Id), true
248// ), deleteEmptyClassRule1.getAllActivationsAsResultSet());
249//
250// assertEquals(Tuple.of(newModelId, newClass2Id), activation0);
251// assertEquals(Tuple.of(newModelId, newClass1Id), activation1);
252//
253// }
254//
255// @Test
256// void fireTest() {
257// var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
258// (builder, model, c) -> builder.clause((f) -> List.of(
259// classModelView.call(model),
260// classElementView.call(c),
261// featuresView.call(model, f),
262// not(encapsulatesView.call(c, f))
263// )));
264//
265// TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass",
266// deleteEmptyClassPrecondition,
267// (model) -> {
268// var classesInterpretation = model.getInterpretation(classes);
269// var classElementInterpretation = model.getInterpretation(classElement);
270// return ((Tuple activation) -> {
271// var modelElement = activation.get(0);
272// var classElement = activation.get(1);
273//
274// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
275// classElementInterpretation.put(Tuple.of(classElement), false);
276// });
277// });
278//
279// var store = ModelStore.builder()
280// .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
281// .with(ViatraModelQueryAdapter.builder()
282// .queries(deleteEmptyClassPrecondition))
283// .with(DesignSpaceExplorationAdapter.builder()
284// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
285// .build();
286//
287// var model = store.createEmptyModel();
288// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
289// deleteEmptyClassRule.prepare(model, queryEngine);
290//
291// var classModelInterpretation = model.getInterpretation(classModel);
292// var classElementInterpretation = model.getInterpretation(classElement);
293// var featureInterpretation = model.getInterpretation(feature);
294// var featuresInterpretation = model.getInterpretation(features);
295// var classesInterpretation = model.getInterpretation(classes);
296//
297// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
298// var newModel = dseAdapter.createObject();
299// var newModelId = newModel.get(0);
300// var newClass1 = dseAdapter.createObject();
301// var newClass1Id = newClass1.get(0);
302// var newClass2 = dseAdapter.createObject();
303// var newClass2Id = newClass2.get(0);
304// var newField = dseAdapter.createObject();
305// var newFieldId = newField.get(0);
306//
307// classModelInterpretation.put(newModel, true);
308// classElementInterpretation.put(newClass1, true);
309// classElementInterpretation.put(newClass2, true);
310// featureInterpretation.put(newField, true);
311// classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
312// classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
313// featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
314//
315// queryEngine.flushChanges();
316//
317// assertResults(Map.of(
318// Tuple.of(newModelId, newClass1Id), true,
319// Tuple.of(newModelId, newClass2Id), true
320// ), deleteEmptyClassRule.getAllActivationsAsResultSet());
321//
322//
323// deleteEmptyClassRule.fireActivation(Tuple.of(0, 1));
324//
325// assertResults(Map.of(
326// Tuple.of(newModelId, newClass1Id), false,
327// Tuple.of(newModelId, newClass2Id), true
328// ), deleteEmptyClassRule.getAllActivationsAsResultSet());
329// }
330//
331// @Test
332// void randomFireTest() {
333// var deleteEmptyClassPrecondition = Query.of("DeleteEmptyClassPrecondition",
334// (builder, model, c) -> builder.clause((f) -> List.of(
335// classModelView.call(model),
336// classElementView.call(c),
337// featuresView.call(model, f),
338// not(encapsulatesView.call(c, f))
339// )));
340//
341// TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass0",
342// deleteEmptyClassPrecondition,
343// (model) -> {
344// var classesInterpretation = model.getInterpretation(classes);
345// var classElementInterpretation = model.getInterpretation(classElement);
346// return ((Tuple activation) -> {
347// var modelElement = activation.get(0);
348// var classElement = activation.get(1);
349//
350// classesInterpretation.put(Tuple.of(modelElement, classElement), false);
351// classElementInterpretation.put(Tuple.of(classElement), false);
352// });
353// },
354// 0L);
355//
356// var store = ModelStore.builder()
357// .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features)
358// .with(ViatraModelQueryAdapter.builder()
359// .queries(deleteEmptyClassPrecondition))
360// .with(DesignSpaceExplorationAdapter.builder()
361// .strategy(new DepthFirstStrategy().withDepthLimit(0)))
362// .build();
363//
364// var model = store.createEmptyModel();
365// var queryEngine = model.getAdapter(ModelQueryAdapter.class);
366// deleteEmptyClassRule.prepare(model, queryEngine);
367//
368// var classModelInterpretation = model.getInterpretation(classModel);
369// var classElementInterpretation = model.getInterpretation(classElement);
370// var featureInterpretation = model.getInterpretation(feature);
371// var featuresInterpretation = model.getInterpretation(features);
372// var classesInterpretation = model.getInterpretation(classes);
373//
374// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
375// var newModel = dseAdapter.createObject();
376// var newModelId = newModel.get(0);
377// var newClass1 = dseAdapter.createObject();
378// var newClass1Id = newClass1.get(0);
379// var newClass2 = dseAdapter.createObject();
380// var newClass2Id = newClass2.get(0);
381// var newField = dseAdapter.createObject();
382// var newFieldId = newField.get(0);
383//
384// classModelInterpretation.put(newModel, true);
385// classElementInterpretation.put(newClass1, true);
386// classElementInterpretation.put(newClass2, true);
387// featureInterpretation.put(newField, true);
388// classesInterpretation.put(Tuple.of(newModelId, newClass1Id), true);
389// classesInterpretation.put(Tuple.of(newModelId, newClass2Id), true);
390// featuresInterpretation.put(Tuple.of(newModelId, newFieldId), true);
391//
392// queryEngine.flushChanges();
393//
394// assertResults(Map.of(
395// Tuple.of(newModelId, newClass1Id), true,
396// Tuple.of(newModelId, newClass2Id), true
397// ), deleteEmptyClassRule.getAllActivationsAsResultSet());
398//
399// deleteEmptyClassRule.fireRandomActivation();
400//
401// assertResults(Map.of(
402// Tuple.of(newModelId, newClass1Id), true,
403// Tuple.of(newModelId, newClass2Id), false
404// ), deleteEmptyClassRule.getAllActivationsAsResultSet());
405//
406// deleteEmptyClassRule.fireRandomActivation();
407//
408// assertResults(Map.of(
409// Tuple.of(newModelId, newClass1Id), false,
410// Tuple.of(newModelId, newClass2Id), false
411// ), deleteEmptyClassRule.getAllActivationsAsResultSet());
412//
413// }
414}
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java
new file mode 100644
index 00000000..f0a20720
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/QueryAssertions.java
@@ -0,0 +1,57 @@
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.tests;
7
8import org.junit.jupiter.api.function.Executable;
9import tools.refinery.store.query.resultset.ResultSet;
10import tools.refinery.store.tuple.Tuple;
11
12import java.util.*;
13
14import static org.hamcrest.MatcherAssert.assertThat;
15import static org.hamcrest.Matchers.is;
16import static org.hamcrest.Matchers.nullValue;
17import static org.junit.jupiter.api.Assertions.assertAll;
18
19public final class QueryAssertions {
20 private QueryAssertions() {
21 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
22 }
23
24 public static <T> void assertNullableResults(Map<Tuple, Optional<T>> expected, ResultSet<T> resultSet) {
25 var nullableValuesMap = new LinkedHashMap<Tuple, T>(expected.size());
26 for (var entry : expected.entrySet()) {
27 nullableValuesMap.put(entry.getKey(), entry.getValue().orElse(null));
28 }
29 assertResults(nullableValuesMap, resultSet);
30 }
31
32 public static <T> void assertResults(Map<Tuple, T> expected, ResultSet<T> resultSet) {
33 var defaultValue = resultSet.getCanonicalQuery().defaultValue();
34 var filteredExpected = new LinkedHashMap<Tuple, T>();
35 var executables = new ArrayList<Executable>();
36 for (var entry : expected.entrySet()) {
37 var key = entry.getKey();
38 var value = entry.getValue();
39 if (!Objects.equals(value, defaultValue)) {
40 filteredExpected.put(key, value);
41 }
42 executables.add(() -> assertThat("value for key " + key,resultSet.get(key), is(value)));
43 }
44 executables.add(() -> assertThat("results size", resultSet.size(), is(filteredExpected.size())));
45
46 var actual = new LinkedHashMap<Tuple, T>();
47 var cursor = resultSet.getAll();
48 while (cursor.move()) {
49 var key = cursor.getKey();
50 var previous = actual.put(key, cursor.getValue());
51 assertThat("duplicate value for key " + key, previous, nullValue());
52 }
53 executables.add(() -> assertThat("results cursor", actual, is(filteredExpected)));
54
55 assertAll(executables);
56 }
57}
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}