diff options
author | Attila Ficsor <ficsorattila96@gmail.com> | 2023-08-08 13:57:19 +0200 |
---|---|---|
committer | Attila Ficsor <ficsorattila96@gmail.com> | 2023-08-08 14:33:16 +0200 |
commit | 1f853e4590d7f235bf8a63fa017fc92369a80a5a (patch) | |
tree | bd586d45d473b68a8d26fba2808e0489ab469217 /subprojects/store-dse | |
parent | Improve performance of best first earch (diff) | |
download | refinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.tar.gz refinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.tar.zst refinery-1f853e4590d7f235bf8a63fa017fc92369a80a5a.zip |
Refactor search strategy to improve readability
Diffstat (limited to 'subprojects/store-dse')
8 files changed, 201 insertions, 84 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java index 409fe8a6..c60a4410 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/Strategy.java | |||
@@ -7,7 +7,7 @@ package tools.refinery.store.dse; | |||
7 | 7 | ||
8 | public interface Strategy { | 8 | public interface Strategy { |
9 | 9 | ||
10 | void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); | 10 | void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); |
11 | 11 | ||
12 | void explore(); | 12 | void explore(); |
13 | } | 13 | } |
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java index 008b2dab..04bba885 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java | |||
@@ -52,10 +52,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration | |||
52 | 52 | ||
53 | private final Map<Version, Fitness> fitnessCache = new HashMap<>(); | 53 | private final Map<Version, Fitness> fitnessCache = new HashMap<>(); |
54 | 54 | ||
55 | public List<Version> getTrajectory() { | ||
56 | return new ArrayList<>(trajectory); | ||
57 | } | ||
58 | |||
59 | public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { | 55 | public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { |
60 | this.model = model; | 56 | this.model = model; |
61 | this.storeAdapter = storeAdapter; | 57 | this.storeAdapter = storeAdapter; |
@@ -75,11 +71,16 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration | |||
75 | objectives = storeAdapter.getObjectives(); | 71 | objectives = storeAdapter.getObjectives(); |
76 | statesAndTraversedActivations = new HashMap<>(); | 72 | statesAndTraversedActivations = new HashMap<>(); |
77 | strategy = storeAdapter.getStrategy(); | 73 | strategy = storeAdapter.getStrategy(); |
74 | strategy.initialize(this); | ||
78 | modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); | 75 | modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); |
79 | isVisualizationEnabled = modelVisualizerAdapter != null; | 76 | isVisualizationEnabled = modelVisualizerAdapter != null; |
80 | 77 | ||
81 | } | 78 | } |
82 | 79 | ||
80 | public List<Version> getTrajectory() { | ||
81 | return new ArrayList<>(trajectory); | ||
82 | } | ||
83 | |||
83 | @Override | 84 | @Override |
84 | public Model getModel() { | 85 | public Model getModel() { |
85 | return model; | 86 | return model; |
@@ -94,7 +95,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration | |||
94 | public List<Version> explore() { | 95 | public List<Version> explore() { |
95 | var state = model.commit(); | 96 | var state = model.commit(); |
96 | trajectory.add(state); | 97 | trajectory.add(state); |
97 | strategy.initStrategy(this); | ||
98 | strategy.explore(); | 98 | strategy.explore(); |
99 | if (isVisualizationEnabled) { | 99 | if (isVisualizationEnabled) { |
100 | modelVisualizerAdapter.visualize(); | 100 | modelVisualizerAdapter.visualize(); |
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java index 0883d3d7..047b204a 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java | |||
@@ -22,8 +22,8 @@ public class BestFirstStrategy implements Strategy { | |||
22 | 22 | ||
23 | private DesignSpaceExplorationAdapter dseAdapter; | 23 | private DesignSpaceExplorationAdapter dseAdapter; |
24 | 24 | ||
25 | private final int maxDepth; | 25 | private int maxDepth = Integer.MAX_VALUE; |
26 | private final int maxSolutions; | 26 | private int maxSolutions = Integer.MAX_VALUE; |
27 | private boolean backTrackIfSolution = true; | 27 | private boolean backTrackIfSolution = true; |
28 | private boolean onlyBetterFirst = false; | 28 | private boolean onlyBetterFirst = false; |
29 | 29 | ||
@@ -50,25 +50,18 @@ public class BestFirstStrategy implements Strategy { | |||
50 | } | 50 | } |
51 | } | 51 | } |
52 | 52 | ||
53 | public BestFirstStrategy() { | 53 | public BestFirstStrategy withDepthLimit(int maxDepth) { |
54 | this(-1); | 54 | if (maxDepth >= 0) { |
55 | } | ||
56 | |||
57 | public BestFirstStrategy(int maxDepth) { | ||
58 | this(maxDepth, -1); | ||
59 | } | ||
60 | |||
61 | public BestFirstStrategy(int maxDepth, int maxSolutions) { | ||
62 | if (maxDepth < 0) { | ||
63 | this.maxDepth = Integer.MAX_VALUE; | ||
64 | } else { | ||
65 | this.maxDepth = maxDepth; | 55 | this.maxDepth = maxDepth; |
66 | } | 56 | } |
67 | if (maxSolutions < 0) { | 57 | return this; |
68 | this.maxSolutions = Integer.MAX_VALUE; | 58 | } |
69 | } else { | 59 | |
60 | public BestFirstStrategy withSolutionLimit(int maxSolutions) { | ||
61 | if (maxSolutions >= 0) { | ||
70 | this.maxSolutions = maxSolutions; | 62 | this.maxSolutions = maxSolutions; |
71 | } | 63 | } |
64 | return this; | ||
72 | } | 65 | } |
73 | 66 | ||
74 | public BestFirstStrategy continueIfHardObjectivesFulfilled() { | 67 | public BestFirstStrategy continueIfHardObjectivesFulfilled() { |
@@ -82,7 +75,7 @@ public class BestFirstStrategy implements Strategy { | |||
82 | } | 75 | } |
83 | 76 | ||
84 | @Override | 77 | @Override |
85 | public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { | 78 | public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { |
86 | this.dseAdapter = designSpaceExplorationAdapter; | 79 | this.dseAdapter = designSpaceExplorationAdapter; |
87 | final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); | 80 | final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); |
88 | 81 | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java index 425e1e01..5f7f61b8 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/DepthFirstStrategy.java | |||
@@ -1,12 +1,8 @@ | |||
1 | /******************************************************************************* | 1 | /* |
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | 2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * This program and the accompanying materials are made available under the | ||
5 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
6 | * http://www.eclipse.org/legal/epl-v20.html. | ||
7 | * | 3 | * |
8 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
9 | *******************************************************************************/ | 5 | */ |
10 | package tools.refinery.store.dse.strategy; | 6 | package tools.refinery.store.dse.strategy; |
11 | 7 | ||
12 | import tools.refinery.store.dse.DesignSpaceExplorationAdapter; | 8 | import tools.refinery.store.dse.DesignSpaceExplorationAdapter; |
@@ -17,38 +13,31 @@ public class DepthFirstStrategy implements Strategy { | |||
17 | 13 | ||
18 | private DesignSpaceExplorationAdapter dseAdapter; | 14 | private DesignSpaceExplorationAdapter dseAdapter; |
19 | 15 | ||
20 | private int maxDepth; | 16 | private int maxDepth = Integer.MAX_VALUE; |
21 | private int maxSolutions; | 17 | private int maxSolutions = Integer.MAX_VALUE; |
22 | private boolean backTrackIfSolution = true; | 18 | private boolean backtrackFromSolution = true; |
23 | 19 | ||
24 | public DepthFirstStrategy() { | 20 | public DepthFirstStrategy withDepthLimit(int maxDepth) { |
25 | this(-1); | 21 | if (maxDepth >= 0) { |
26 | } | ||
27 | |||
28 | public DepthFirstStrategy(int maxDepth) { | ||
29 | this(maxDepth, -1); | ||
30 | } | ||
31 | |||
32 | public DepthFirstStrategy(int maxDepth, int maxSolutions) { | ||
33 | if (maxDepth < 0) { | ||
34 | this.maxDepth = Integer.MAX_VALUE; | ||
35 | } else { | ||
36 | this.maxDepth = maxDepth; | 22 | this.maxDepth = maxDepth; |
37 | } | 23 | } |
38 | if (maxSolutions < 0) { | 24 | return this; |
39 | this.maxSolutions = Integer.MAX_VALUE; | 25 | } |
40 | } else { | 26 | |
27 | public DepthFirstStrategy withSolutionLimit(int maxSolutions) { | ||
28 | if (maxSolutions >= 0) { | ||
41 | this.maxSolutions = maxSolutions; | 29 | this.maxSolutions = maxSolutions; |
42 | } | 30 | } |
31 | return this; | ||
43 | } | 32 | } |
44 | 33 | ||
45 | public DepthFirstStrategy continueIfHardObjectivesFulfilled() { | 34 | public DepthFirstStrategy continueIfHardObjectivesFulfilled() { |
46 | backTrackIfSolution = false; | 35 | backtrackFromSolution = false; |
47 | return this; | 36 | return this; |
48 | } | 37 | } |
49 | 38 | ||
50 | @Override | 39 | @Override |
51 | public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { | 40 | public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { |
52 | this.dseAdapter = designSpaceExplorationAdapter; | 41 | this.dseAdapter = designSpaceExplorationAdapter; |
53 | } | 42 | } |
54 | 43 | ||
@@ -59,22 +48,18 @@ public class DepthFirstStrategy implements Strategy { | |||
59 | } | 48 | } |
60 | while (dseAdapter.getSolutions().size() < maxSolutions) { | 49 | while (dseAdapter.getSolutions().size() < maxSolutions) { |
61 | if (!checkAndHandleGlobalConstraints()) { | 50 | if (!checkAndHandleGlobalConstraints()) { |
62 | // Global constraint is not satisfied and cannot backtrack. | ||
63 | return; | 51 | return; |
64 | } | 52 | } |
65 | // Global constraint is not satisfied, backtrack. | ||
66 | 53 | ||
67 | Fitness fitness = dseAdapter.getFitness(); | 54 | Fitness fitness = dseAdapter.getFitness(); |
68 | if (fitness.isSatisfiesHardObjectives()) { | 55 | if (fitness.isSatisfiesHardObjectives()) { |
69 | dseAdapter.newSolution(); | 56 | dseAdapter.newSolution(); |
70 | if (backTrackIfSolution && !dseAdapter.backtrack()) { | 57 | if (backtrackFromSolution && !dseAdapter.backtrack()) { |
71 | // Found a solution but cannot backtrack. | ||
72 | return; | 58 | return; |
73 | } | 59 | } |
74 | } | 60 | } |
75 | 61 | ||
76 | if (!checkAndHandleDepth()) { | 62 | if (!checkAndHandleDepth()) { |
77 | // Reached max depth but cannot backtrack. | ||
78 | return; | 63 | return; |
79 | } | 64 | } |
80 | 65 | ||
@@ -87,24 +72,18 @@ public class DepthFirstStrategy implements Strategy { | |||
87 | } | 72 | } |
88 | 73 | ||
89 | private boolean checkAndHandleGlobalConstraints() { | 74 | private boolean checkAndHandleGlobalConstraints() { |
90 | // Global constraint is not satisfied and cannot backtrack. | ||
91 | return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack(); | 75 | return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack(); |
92 | // Global constraint is satisfied or backtrack. | ||
93 | } | 76 | } |
94 | 77 | ||
95 | private boolean checkAndHandleDepth() { | 78 | private boolean checkAndHandleDepth() { |
96 | // Reached max depth but cannot backtrack. | ||
97 | return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack(); | 79 | return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack(); |
98 | // Reached max depth or backtrack. | ||
99 | } | 80 | } |
100 | 81 | ||
101 | private boolean backtrackToLastUntraversed() { | 82 | private boolean backtrackToLastUntraversed() { |
102 | while (dseAdapter.getUntraversedActivations().isEmpty()) { | 83 | while (dseAdapter.getUntraversedActivations().isEmpty()) { |
103 | if (!dseAdapter.backtrack()) { | 84 | if (!dseAdapter.backtrack()) { |
104 | // No more transitions from current state and cannot backtrack. | ||
105 | return false; | 85 | return false; |
106 | } | 86 | } |
107 | // No more transitions from current state, backtrack. | ||
108 | } | 87 | } |
109 | return true; | 88 | return true; |
110 | } | 89 | } |
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java index d761db02..225de32e 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java | |||
@@ -201,8 +201,8 @@ class CRAExamplesTest { | |||
201 | .with(DesignSpaceExplorationAdapter.builder() | 201 | .with(DesignSpaceExplorationAdapter.builder() |
202 | .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) | 202 | .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) |
203 | .objectives(new AlwaysSatisfiedRandomHardObjective()) | 203 | .objectives(new AlwaysSatisfiedRandomHardObjective()) |
204 | // .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled() | 204 | // .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled() |
205 | .strategy(new BestFirstStrategy(6).continueIfHardObjectivesFulfilled() | 205 | .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled() |
206 | // .goOnOnlyIfFitnessIsBetter() | 206 | // .goOnOnlyIfFitnessIsBetter() |
207 | )) | 207 | )) |
208 | .build(); | 208 | .build(); |
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java index 36bc6cce..c6da896c 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java | |||
@@ -103,8 +103,8 @@ class DebugTest { | |||
103 | .with(DesignSpaceExplorationAdapter.builder() | 103 | .with(DesignSpaceExplorationAdapter.builder() |
104 | .transformations(createClassRule, createFeatureRule) | 104 | .transformations(createClassRule, createFeatureRule) |
105 | .objectives(new AlwaysSatisfiedRandomHardObjective()) | 105 | .objectives(new AlwaysSatisfiedRandomHardObjective()) |
106 | .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() | 106 | .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() |
107 | // .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() | 107 | // .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() |
108 | // .goOnOnlyIfFitnessIsBetter() | 108 | // .goOnOnlyIfFitnessIsBetter() |
109 | )) | 109 | )) |
110 | .build(); | 110 | .build(); |
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java index 89adbf65..91e33f4a 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DesignSpaceExplorationTest.java | |||
@@ -49,7 +49,8 @@ class DesignSpaceExplorationTest { | |||
49 | void createObjectTest() { | 49 | void createObjectTest() { |
50 | var store = ModelStore.builder() | 50 | var store = ModelStore.builder() |
51 | .with(ViatraModelQueryAdapter.builder()) | 51 | .with(ViatraModelQueryAdapter.builder()) |
52 | .with(DesignSpaceExplorationAdapter.builder()) | 52 | .with(DesignSpaceExplorationAdapter.builder() |
53 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) | ||
53 | .build(); | 54 | .build(); |
54 | 55 | ||
55 | var model = store.createEmptyModel(); | 56 | var model = store.createEmptyModel(); |
@@ -77,7 +78,8 @@ class DesignSpaceExplorationTest { | |||
77 | void deleteMiddleObjectTest() { | 78 | void deleteMiddleObjectTest() { |
78 | var store = ModelStore.builder() | 79 | var store = ModelStore.builder() |
79 | .with(ViatraModelQueryAdapter.builder()) | 80 | .with(ViatraModelQueryAdapter.builder()) |
80 | .with(DesignSpaceExplorationAdapter.builder()) | 81 | .with(DesignSpaceExplorationAdapter.builder() |
82 | .strategy(new DepthFirstStrategy())) | ||
81 | .build(); | 83 | .build(); |
82 | 84 | ||
83 | var model = store.createEmptyModel(); | 85 | var model = store.createEmptyModel(); |
@@ -118,7 +120,7 @@ class DesignSpaceExplorationTest { | |||
118 | .symbols(classModel) | 120 | .symbols(classModel) |
119 | .with(ViatraModelQueryAdapter.builder()) | 121 | .with(ViatraModelQueryAdapter.builder()) |
120 | .with(DesignSpaceExplorationAdapter.builder() | 122 | .with(DesignSpaceExplorationAdapter.builder() |
121 | .strategy(new DepthFirstStrategy(0))) | 123 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) |
122 | .build(); | 124 | .build(); |
123 | 125 | ||
124 | var model = store.createEmptyModel(); | 126 | var model = store.createEmptyModel(); |
@@ -158,7 +160,7 @@ class DesignSpaceExplorationTest { | |||
158 | .queries(createClassPrecondition)) | 160 | .queries(createClassPrecondition)) |
159 | .with(DesignSpaceExplorationAdapter.builder() | 161 | .with(DesignSpaceExplorationAdapter.builder() |
160 | .transformations(createClassRule) | 162 | .transformations(createClassRule) |
161 | .strategy(new DepthFirstStrategy(4) | 163 | .strategy(new DepthFirstStrategy().withDepthLimit(0) |
162 | )) | 164 | )) |
163 | .build(); | 165 | .build(); |
164 | 166 | ||
@@ -204,7 +206,7 @@ class DesignSpaceExplorationTest { | |||
204 | .queries(createClassPrecondition)) | 206 | .queries(createClassPrecondition)) |
205 | .with(DesignSpaceExplorationAdapter.builder() | 207 | .with(DesignSpaceExplorationAdapter.builder() |
206 | .transformations(createClassRule) | 208 | .transformations(createClassRule) |
207 | .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() | 209 | .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() |
208 | )) | 210 | )) |
209 | .build(); | 211 | .build(); |
210 | 212 | ||
@@ -272,7 +274,7 @@ class DesignSpaceExplorationTest { | |||
272 | .queries(createClassPrecondition, createFeaturePrecondition)) | 274 | .queries(createClassPrecondition, createFeaturePrecondition)) |
273 | .with(DesignSpaceExplorationAdapter.builder() | 275 | .with(DesignSpaceExplorationAdapter.builder() |
274 | .transformations(createClassRule, createFeatureRule) | 276 | .transformations(createClassRule, createFeatureRule) |
275 | .strategy(new DepthFirstStrategy(10).continueIfHardObjectivesFulfilled() | 277 | .strategy(new DepthFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled() |
276 | )) | 278 | )) |
277 | .build(); | 279 | .build(); |
278 | 280 | ||
@@ -289,12 +291,81 @@ class DesignSpaceExplorationTest { | |||
289 | } | 291 | } |
290 | 292 | ||
291 | @Test | 293 | @Test |
292 | void BFSTrivialTest() { | 294 | void DFSSolutionLimitTest() { |
295 | var createClassPrecondition = Query.of("CreateClassPrecondition", | ||
296 | (builder, model) -> builder.clause( | ||
297 | classModelView.call(model) | ||
298 | )); | ||
299 | |||
300 | var createClassRule = new TransformationRule("CreateClass", | ||
301 | createClassPrecondition, | ||
302 | (model) -> { | ||
303 | var classesInterpretation = model.getInterpretation(classes); | ||
304 | var classElementInterpretation = model.getInterpretation(classElement); | ||
305 | return ((Tuple activation) -> { | ||
306 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
307 | var modelElement = activation.get(0); | ||
308 | |||
309 | var newClassElement = dseAdapter.createObject(); | ||
310 | var newClassElementId = newClassElement.get(0); | ||
311 | |||
312 | classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); | ||
313 | classElementInterpretation.put(Tuple.of(newClassElementId), true); | ||
314 | }); | ||
315 | }); | ||
316 | |||
317 | var createFeaturePrecondition = Query.of("CreateFeaturePrecondition", | ||
318 | (builder, model) -> builder.clause( | ||
319 | classModelView.call(model) | ||
320 | )); | ||
321 | |||
322 | var createFeatureRule = new TransformationRule("CreateFeature", | ||
323 | createFeaturePrecondition, | ||
324 | (model) -> { | ||
325 | var featuresInterpretation = model.getInterpretation(features); | ||
326 | var featureInterpretation = model.getInterpretation(feature); | ||
327 | return ((Tuple activation) -> { | ||
328 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
329 | var modelElement = activation.get(0); | ||
330 | |||
331 | var newClassElement = dseAdapter.createObject(); | ||
332 | var newClassElementId = newClassElement.get(0); | ||
333 | |||
334 | featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true); | ||
335 | featureInterpretation.put(Tuple.of(newClassElementId), true); | ||
336 | }); | ||
337 | }); | ||
338 | |||
339 | var store = ModelStore.builder() | ||
340 | .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) | ||
341 | .with(ViatraModelQueryAdapter.builder() | ||
342 | .queries(createClassPrecondition, createFeaturePrecondition)) | ||
343 | .with(DesignSpaceExplorationAdapter.builder() | ||
344 | .transformations(createClassRule, createFeatureRule) | ||
345 | .strategy(new DepthFirstStrategy().withSolutionLimit(222) | ||
346 | .continueIfHardObjectivesFulfilled() | ||
347 | )) | ||
348 | .build(); | ||
349 | |||
350 | var model = store.createEmptyModel(); | ||
351 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
352 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); | ||
353 | |||
354 | var modelElementInterpretation = model.getInterpretation(classModel); | ||
355 | modelElementInterpretation.put(dseAdapter.createObject(), true); | ||
356 | queryEngine.flushChanges(); | ||
357 | |||
358 | var states = dseAdapter.explore(); | ||
359 | assertEquals(222, states.size()); | ||
360 | } | ||
361 | |||
362 | @Test | ||
363 | void BeFSTrivialTest() { | ||
293 | var store = ModelStore.builder() | 364 | var store = ModelStore.builder() |
294 | .symbols(classModel) | 365 | .symbols(classModel) |
295 | .with(ViatraModelQueryAdapter.builder()) | 366 | .with(ViatraModelQueryAdapter.builder()) |
296 | .with(DesignSpaceExplorationAdapter.builder() | 367 | .with(DesignSpaceExplorationAdapter.builder() |
297 | .strategy(new BestFirstStrategy(0))) | 368 | .strategy(new BestFirstStrategy().withDepthLimit(0))) |
298 | .build(); | 369 | .build(); |
299 | 370 | ||
300 | var model = store.createEmptyModel(); | 371 | var model = store.createEmptyModel(); |
@@ -305,7 +376,7 @@ class DesignSpaceExplorationTest { | |||
305 | } | 376 | } |
306 | 377 | ||
307 | @Test | 378 | @Test |
308 | void BFSOneRuleTest() { | 379 | void BeFSOneRuleTest() { |
309 | var createClassPrecondition = Query.of("CreateClassPrecondition", | 380 | var createClassPrecondition = Query.of("CreateClassPrecondition", |
310 | (builder, model) -> builder.clause( | 381 | (builder, model) -> builder.clause( |
311 | classModelView.call(model) | 382 | classModelView.call(model) |
@@ -334,7 +405,7 @@ class DesignSpaceExplorationTest { | |||
334 | .queries(createClassPrecondition)) | 405 | .queries(createClassPrecondition)) |
335 | .with(DesignSpaceExplorationAdapter.builder() | 406 | .with(DesignSpaceExplorationAdapter.builder() |
336 | .transformations(createClassRule) | 407 | .transformations(createClassRule) |
337 | .strategy(new BestFirstStrategy(4) | 408 | .strategy(new BestFirstStrategy().withDepthLimit(4) |
338 | )) | 409 | )) |
339 | .build(); | 410 | .build(); |
340 | 411 | ||
@@ -351,7 +422,7 @@ class DesignSpaceExplorationTest { | |||
351 | } | 422 | } |
352 | 423 | ||
353 | @Test | 424 | @Test |
354 | void BFSContinueTest() { | 425 | void BeFSContinueTest() { |
355 | var createClassPrecondition = Query.of("CreateClassPrecondition", | 426 | var createClassPrecondition = Query.of("CreateClassPrecondition", |
356 | (builder, model) -> builder.clause( | 427 | (builder, model) -> builder.clause( |
357 | classModelView.call(model) | 428 | classModelView.call(model) |
@@ -380,7 +451,7 @@ class DesignSpaceExplorationTest { | |||
380 | .queries(createClassPrecondition)) | 451 | .queries(createClassPrecondition)) |
381 | .with(DesignSpaceExplorationAdapter.builder() | 452 | .with(DesignSpaceExplorationAdapter.builder() |
382 | .transformations(createClassRule) | 453 | .transformations(createClassRule) |
383 | .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() | 454 | .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() |
384 | )) | 455 | )) |
385 | .build(); | 456 | .build(); |
386 | 457 | ||
@@ -397,7 +468,7 @@ class DesignSpaceExplorationTest { | |||
397 | } | 468 | } |
398 | 469 | ||
399 | @Test | 470 | @Test |
400 | void BFSCompletenessTest() { | 471 | void BeFSCompletenessTest() { |
401 | var createClassPrecondition = Query.of("CreateClassPrecondition", | 472 | var createClassPrecondition = Query.of("CreateClassPrecondition", |
402 | (builder, model) -> builder.clause( | 473 | (builder, model) -> builder.clause( |
403 | classModelView.call(model) | 474 | classModelView.call(model) |
@@ -448,7 +519,7 @@ class DesignSpaceExplorationTest { | |||
448 | .queries(createClassPrecondition, createFeaturePrecondition)) | 519 | .queries(createClassPrecondition, createFeaturePrecondition)) |
449 | .with(DesignSpaceExplorationAdapter.builder() | 520 | .with(DesignSpaceExplorationAdapter.builder() |
450 | .transformations(createClassRule, createFeatureRule) | 521 | .transformations(createClassRule, createFeatureRule) |
451 | .strategy(new BestFirstStrategy(10).continueIfHardObjectivesFulfilled() | 522 | .strategy(new BestFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled() |
452 | )) | 523 | )) |
453 | .build(); | 524 | .build(); |
454 | 525 | ||
@@ -464,4 +535,73 @@ class DesignSpaceExplorationTest { | |||
464 | assertEquals(2047, states.size()); | 535 | assertEquals(2047, states.size()); |
465 | } | 536 | } |
466 | 537 | ||
538 | @Test | ||
539 | void BeFSSolutionLimitTest() { | ||
540 | var createClassPrecondition = Query.of("CreateClassPrecondition", | ||
541 | (builder, model) -> builder.clause( | ||
542 | classModelView.call(model) | ||
543 | )); | ||
544 | |||
545 | var createClassRule = new TransformationRule("CreateClass", | ||
546 | createClassPrecondition, | ||
547 | (model) -> { | ||
548 | var classesInterpretation = model.getInterpretation(classes); | ||
549 | var classElementInterpretation = model.getInterpretation(classElement); | ||
550 | return ((Tuple activation) -> { | ||
551 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
552 | var modelElement = activation.get(0); | ||
553 | |||
554 | var newClassElement = dseAdapter.createObject(); | ||
555 | var newClassElementId = newClassElement.get(0); | ||
556 | |||
557 | classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); | ||
558 | classElementInterpretation.put(Tuple.of(newClassElementId), true); | ||
559 | }); | ||
560 | }); | ||
561 | |||
562 | var createFeaturePrecondition = Query.of("CreateFeaturePrecondition", | ||
563 | (builder, model) -> builder.clause( | ||
564 | classModelView.call(model) | ||
565 | )); | ||
566 | |||
567 | var createFeatureRule = new TransformationRule("CreateFeature", | ||
568 | createFeaturePrecondition, | ||
569 | (model) -> { | ||
570 | var featuresInterpretation = model.getInterpretation(features); | ||
571 | var featureInterpretation = model.getInterpretation(feature); | ||
572 | return ((Tuple activation) -> { | ||
573 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
574 | var modelElement = activation.get(0); | ||
575 | |||
576 | var newClassElement = dseAdapter.createObject(); | ||
577 | var newClassElementId = newClassElement.get(0); | ||
578 | |||
579 | featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true); | ||
580 | featureInterpretation.put(Tuple.of(newClassElementId), true); | ||
581 | }); | ||
582 | }); | ||
583 | |||
584 | var store = ModelStore.builder() | ||
585 | .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) | ||
586 | .with(ViatraModelQueryAdapter.builder() | ||
587 | .queries(createClassPrecondition, createFeaturePrecondition)) | ||
588 | .with(DesignSpaceExplorationAdapter.builder() | ||
589 | .transformations(createClassRule, createFeatureRule) | ||
590 | .strategy(new BestFirstStrategy().withSolutionLimit(222) | ||
591 | .continueIfHardObjectivesFulfilled() | ||
592 | )) | ||
593 | .build(); | ||
594 | |||
595 | var model = store.createEmptyModel(); | ||
596 | var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
597 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); | ||
598 | |||
599 | var modelElementInterpretation = model.getInterpretation(classModel); | ||
600 | modelElementInterpretation.put(dseAdapter.createObject(), true); | ||
601 | queryEngine.flushChanges(); | ||
602 | |||
603 | var states = dseAdapter.explore(); | ||
604 | assertEquals(222, states.size()); | ||
605 | } | ||
606 | |||
467 | } | 607 | } |
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java index 3aa4c92e..5d24d712 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/TransformationRuleTest.java | |||
@@ -6,6 +6,7 @@ | |||
6 | package tools.refinery.store.dse; | 6 | package tools.refinery.store.dse; |
7 | 7 | ||
8 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
9 | import tools.refinery.store.dse.strategy.DepthFirstStrategy; | ||
9 | import tools.refinery.store.model.ModelStore; | 10 | import tools.refinery.store.model.ModelStore; |
10 | import tools.refinery.store.query.ModelQueryAdapter; | 11 | import tools.refinery.store.query.ModelQueryAdapter; |
11 | import tools.refinery.store.query.dnf.Query; | 12 | import tools.refinery.store.query.dnf.Query; |
@@ -103,7 +104,8 @@ class TransformationRuleTest { | |||
103 | .with(ViatraModelQueryAdapter.builder() | 104 | .with(ViatraModelQueryAdapter.builder() |
104 | .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper, | 105 | .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper, |
105 | deleteEmptyClassPrecondition)) | 106 | deleteEmptyClassPrecondition)) |
106 | .with(DesignSpaceExplorationAdapter.builder()) | 107 | .with(DesignSpaceExplorationAdapter.builder() |
108 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) | ||
107 | .build(); | 109 | .build(); |
108 | 110 | ||
109 | var model = store.createEmptyModel(); | 111 | var model = store.createEmptyModel(); |
@@ -195,7 +197,8 @@ class TransformationRuleTest { | |||
195 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) | 197 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) |
196 | .with(ViatraModelQueryAdapter.builder() | 198 | .with(ViatraModelQueryAdapter.builder() |
197 | .queries(deleteEmptyClassPrecondition)) | 199 | .queries(deleteEmptyClassPrecondition)) |
198 | .with(DesignSpaceExplorationAdapter.builder()) | 200 | .with(DesignSpaceExplorationAdapter.builder() |
201 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) | ||
199 | .build(); | 202 | .build(); |
200 | 203 | ||
201 | var model = store.createEmptyModel(); | 204 | var model = store.createEmptyModel(); |
@@ -276,7 +279,8 @@ class TransformationRuleTest { | |||
276 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) | 279 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) |
277 | .with(ViatraModelQueryAdapter.builder() | 280 | .with(ViatraModelQueryAdapter.builder() |
278 | .queries(deleteEmptyClassPrecondition)) | 281 | .queries(deleteEmptyClassPrecondition)) |
279 | .with(DesignSpaceExplorationAdapter.builder()) | 282 | .with(DesignSpaceExplorationAdapter.builder() |
283 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) | ||
280 | .build(); | 284 | .build(); |
281 | 285 | ||
282 | var model = store.createEmptyModel(); | 286 | var model = store.createEmptyModel(); |
@@ -352,7 +356,8 @@ class TransformationRuleTest { | |||
352 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) | 356 | .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) |
353 | .with(ViatraModelQueryAdapter.builder() | 357 | .with(ViatraModelQueryAdapter.builder() |
354 | .queries(deleteEmptyClassPrecondition)) | 358 | .queries(deleteEmptyClassPrecondition)) |
355 | .with(DesignSpaceExplorationAdapter.builder()) | 359 | .with(DesignSpaceExplorationAdapter.builder() |
360 | .strategy(new DepthFirstStrategy().withDepthLimit(0))) | ||
356 | .build(); | 361 | .build(); |
357 | 362 | ||
358 | var model = store.createEmptyModel(); | 363 | var model = store.createEmptyModel(); |