From e722deec08fe509f3e5a2b701c7e3260ee10aa66 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 12:04:58 +0200 Subject: Update exploration strategies - Fix best first search algorithm - Improve efficiency of exploration adapter --- .../refinery/store/dse/TransformationRuleTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'subprojects/store-dse/src/test') 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 312bcebd..f57f68ef 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 @@ -137,8 +137,8 @@ public class TransformationRuleTest { queryEngine.flushChanges(); - var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsSets(); - var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsSets(); + var assignFeatureRuleActivations = assignFeatureRule.getAllActivationsAsResultSet(); + var deleteEmptyClassRuleActivations = deleteEmptyClassRule.getAllActivationsAsResultSet(); assertResults(Map.of( Tuple.of(newClass1Id, newFieldId), true, @@ -236,12 +236,12 @@ public class TransformationRuleTest { assertResults(Map.of( Tuple.of(newModelId, newClass1Id), true, Tuple.of(newModelId, newClass2Id), true - ), deleteEmptyClassRule0.getAllActivationsAsSets()); + ), deleteEmptyClassRule0.getAllActivationsAsResultSet()); assertResults(Map.of( Tuple.of(newModelId, newClass1Id), true, Tuple.of(newModelId, newClass2Id), true - ), deleteEmptyClassRule1.getAllActivationsAsSets()); + ), deleteEmptyClassRule1.getAllActivationsAsResultSet()); assertEquals(Tuple.of(newModelId, newClass2Id), activation0); assertEquals(Tuple.of(newModelId, newClass1Id), activation1); @@ -312,7 +312,7 @@ public class TransformationRuleTest { assertResults(Map.of( Tuple.of(newModelId, newClass1Id), true, Tuple.of(newModelId, newClass2Id), true - ), deleteEmptyClassRule.getAllActivationsAsSets()); + ), deleteEmptyClassRule.getAllActivationsAsResultSet()); deleteEmptyClassRule.fireActivation(Tuple.of(0, 1)); @@ -320,7 +320,7 @@ public class TransformationRuleTest { assertResults(Map.of( Tuple.of(newModelId, newClass1Id), false, Tuple.of(newModelId, newClass2Id), true - ), deleteEmptyClassRule.getAllActivationsAsSets()); + ), deleteEmptyClassRule.getAllActivationsAsResultSet()); } @Test @@ -388,21 +388,21 @@ public class TransformationRuleTest { assertResults(Map.of( Tuple.of(newModelId, newClass1Id), true, Tuple.of(newModelId, newClass2Id), true - ), deleteEmptyClassRule.getAllActivationsAsSets()); + ), deleteEmptyClassRule.getAllActivationsAsResultSet()); deleteEmptyClassRule.fireRandomActivation(); assertResults(Map.of( Tuple.of(newModelId, newClass1Id), true, Tuple.of(newModelId, newClass2Id), false - ), deleteEmptyClassRule.getAllActivationsAsSets()); + ), deleteEmptyClassRule.getAllActivationsAsResultSet()); deleteEmptyClassRule.fireRandomActivation(); assertResults(Map.of( Tuple.of(newModelId, newClass1Id), false, Tuple.of(newModelId, newClass2Id), false - ), deleteEmptyClassRule.getAllActivationsAsSets()); + ), deleteEmptyClassRule.getAllActivationsAsResultSet()); } } -- cgit v1.2.3-70-g09d2 From a20fd33c647d8511762f84436dbd8d1632b57fe8 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 12:59:35 +0200 Subject: Clean up design space exploration --- .../store/dse/DesignSpaceExplorationAdapter.java | 2 - .../DesignSpaceExplorationAdapterImpl.java | 7 +-- .../store/dse/objectives/BaseObjective.java | 2 +- .../refinery/store/dse/objectives/Comparators.java | 2 +- .../refinery/store/dse/objectives/Fitness.java | 15 +++++ .../dse/objectives/ObjectiveComparatorHelper.java | 1 + .../store/dse/strategy/BestFirstStrategy.java | 65 +++++++--------------- .../store/dse/strategy/DepthFirstStrategy.java | 23 +++----- .../tools/refinery/store/dse/CRAExamplesTest.java | 2 +- .../java/tools/refinery/store/dse/DebugTest.java | 2 +- .../store/dse/DesignSpaceExplorationTest.java | 2 +- .../refinery/store/dse/TransformationRuleTest.java | 2 +- .../visualization/ModelVisualizerStoreAdapter.java | 1 - .../internal/ModelVisualizerAdapterImpl.java | 57 ++++++++++++------- 14 files changed, 89 insertions(+), 94 deletions(-) (limited to 'subprojects/store-dse/src/test') diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java index c4aa97c2..c45f088a 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java @@ -52,8 +52,6 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter { public void fireRandomActivation(); - public boolean isCurrentInTrajectory(); - public List getTrajectory(); public boolean isCurrentStateAlreadyTraversed(); 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 4e5cc467..1329480c 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 @@ -43,7 +43,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration private ObjectiveComparatorHelper objectiveComparatorHelper; private List trajectory = new ArrayList<>(); private Map parents = new HashMap<>(); - private Fitness lastFitness; private final List solutions = new ArrayList<>(); private Map> statesAndTraversedActivations; private Random random = new Random(); @@ -184,9 +183,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration @Override public Fitness getFitness() { - var result = fitnessCache.computeIfAbsent(model.getState(), s -> calculateFitness()); - lastFitness = result; - return result; + return fitnessCache.computeIfAbsent(model.getState(), s -> calculateFitness()); } private Fitness calculateFitness() { @@ -201,8 +198,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } result.setSatisfiesHardObjectives(satisfiesHardObjectives); - lastFitness = result; - return result; } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java index 7df33efe..b76598fb 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/BaseObjective.java @@ -30,7 +30,7 @@ public abstract class BaseObjective implements Objective { protected boolean isThereFitnessConstraint = false; protected Comparator fitnessConstraintComparator; - public BaseObjective(String name) { + protected BaseObjective(String name) { Objects.requireNonNull(name, "Name of the objective cannot be null."); this.name = name; } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java index 476504b0..181397b3 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Comparators.java @@ -15,7 +15,7 @@ public class Comparators { private Comparators() { /*Utility class constructor*/ } - public static final Comparator HIGHER_IS_BETTER = (o1, o2) -> o1.compareTo(o2); + public static final Comparator HIGHER_IS_BETTER = Double::compareTo; public static final Comparator LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java index 92709d3e..0bf956d2 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/Fitness.java @@ -27,4 +27,19 @@ public class Fitness extends HashMap { public String toString() { return super.toString() + " hardObjectives=" + satisfiesHardObjectives; } + + @Override + public boolean equals(Object other) { + if (other == null) return false; + if (getClass() != other.getClass()) return false; + return satisfiesHardObjectives == ((Fitness) other).satisfiesHardObjectives; + } + + @Override + public int hashCode() { + int h = super.hashCode(); + h = h * 31 + (satisfiesHardObjectives ? 1 : 0); + return h; + } + } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java index 1d676562..eb03eeaf 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/ObjectiveComparatorHelper.java @@ -49,6 +49,7 @@ public class ObjectiveComparatorHelper { } } if (o2HasBetterFitness) { + return -1; } else if (o1HasBetterFitness) { return 1; } 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 57f86401..98af5695 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 @@ -25,29 +25,18 @@ public class BestFirstStrategy implements Strategy { private DesignSpaceExplorationAdapter dseAdapter; - private int maxDepth; - private int maxSolutions; + private final int maxDepth; + private final int maxSolutions; private boolean backTrackIfSolution = true; private boolean onlyBetterFirst = false; private PriorityQueue trajectoriesToExplore; - private static class TrajectoryWithFitness { - - public List trajectory; - public Fitness fitness; - - public TrajectoryWithFitness(List trajectory, Fitness fitness) { - super(); - this.trajectory = trajectory; - this.fitness = fitness; - } - + private record TrajectoryWithFitness(List trajectory, Fitness fitness) { @Override public String toString() { - return trajectory.toString() + fitness.toString(); - } - + return trajectory.toString() + fitness.toString(); + } } public BestFirstStrategy() { @@ -99,14 +88,14 @@ public class BestFirstStrategy implements Strategy { boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); if (!globalConstraintsAreSatisfied) { - // "Global constraint is not satisfied in the first state. Terminate."); + // Global constraint is not satisfied in the first state. Terminate. return; } final Fitness firstFitness = dseAdapter.getFitness(); if (firstFitness.isSatisfiesHardObjectives()) { dseAdapter.newSolution(); - // "First state is a solution. Terminate."); + // First state is a solution. Terminate. if (backTrackIfSolution) { return; } @@ -116,12 +105,6 @@ public class BestFirstStrategy implements Strategy { return; } -// final List firstTrajectory = dseAdapter.getTrajectory(); - -// TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), -// firstFitness); -// trajectoriesToExplore.add(currentTrajectoryWithFitness); - var firstTrajectoryWithFitness = new TrajectoryWithFitness(dseAdapter.getTrajectory(), firstFitness); trajectoriesToExplore.add(firstTrajectoryWithFitness); @@ -131,13 +114,11 @@ public class BestFirstStrategy implements Strategy { if (currentTrajectoryWithFitness == null) { if (trajectoriesToExplore.isEmpty()) { - // "State space is fully traversed."); + // State space is fully traversed. return; } else { currentTrajectoryWithFitness = trajectoriesToExplore.element(); -// if (logger.isDebugEnabled()) { -// "New trajectory is chosen: " + currentTrajectoryWithFitness); -// } + // New trajectory is chosen: " + currentTrajectoryWithFitness dseAdapter.restoreTrajectory(currentTrajectoryWithFitness.trajectory); } } @@ -150,19 +131,17 @@ public class BestFirstStrategy implements Strategy { while (iterator.hasNext()) { final Activation nextActivation = iterator.next(); if (!iterator.hasNext()) { - // "Last untraversed activation of the state."); + // Last untraversed activation of the state. trajectoriesToExplore.remove(currentTrajectoryWithFitness); } -// if (logger.isDebugEnabled()) { -// "Executing new activation: " + nextActivation); -// } + // Executing new activation dseAdapter.fireActivation(nextActivation); if (dseAdapter.isCurrentStateAlreadyTraversed()) { - // "The new state is already visited."); + // The new state is already visited. dseAdapter.backtrack(); } else if (!dseAdapter.checkGlobalConstraints()) { - // "Global constraint is not satisfied."); + // Global constraint is not satisfied. dseAdapter.backtrack(); } else { final Fitness nextFitness = dseAdapter.getFitness(); @@ -172,14 +151,14 @@ public class BestFirstStrategy implements Strategy { if (solutions >= maxSolutions) { return; } - // "Found a solution."); + // Found a solution. if (backTrackIfSolution) { dseAdapter.backtrack(); continue; } } if (dseAdapter.getDepth() >= maxDepth) { - // "Reached max depth."); + // Reached max depth. dseAdapter.backtrack(); continue; } @@ -191,33 +170,31 @@ public class BestFirstStrategy implements Strategy { int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness, nextTrajectoryWithFitness.fitness); if (compare < 0) { - // "Better fitness, moving on: " + nextFitness); + // Better fitness, moving on currentTrajectoryWithFitness = nextTrajectoryWithFitness; continue mainLoop; } else if (compare == 0) { if (onlyBetterFirst) { - // "Equally good fitness, backtrack: " + nextFitness); + // Equally good fitness, backtrack dseAdapter.backtrack(); - continue; } else { - // "Equally good fitness, moving on: " + nextFitness); + // Equally good fitness, moving on currentTrajectoryWithFitness = nextTrajectoryWithFitness; continue mainLoop; } } else { - // "Worse fitness."); + //"Worse fitness currentTrajectoryWithFitness = null; continue mainLoop; } } } - // "State is fully traversed."); + // State is fully traversed. trajectoriesToExplore.remove(currentTrajectoryWithFitness); currentTrajectoryWithFitness = null; } - // "Interrupted."); - + // Interrupted. } } 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 f4a0747a..15529371 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 @@ -65,11 +65,11 @@ public class DepthFirstStrategy implements Strategy { if (!globalConstraintsAreSatisfied) { var isSuccessfulUndo = dseAdapter.backtrack(); if (!isSuccessfulUndo) { -// "Global constraint is not satisfied and cannot backtrack." + // Global constraint is not satisfied and cannot backtrack. break; } else { -// "Global constraint is not satisfied, backtrack." + // Global constraint is not satisfied, backtrack. continue; } } @@ -84,10 +84,10 @@ public class DepthFirstStrategy implements Strategy { if (backTrackIfSolution) { var isSuccessfulUndo = dseAdapter.backtrack(); if (!isSuccessfulUndo) { -// "Found a solution but cannot backtrack." + // Found a solution but cannot backtrack. break; } else { -// "Found a solution, backtrack." + // Found a solution, backtrack. continue; } } @@ -96,7 +96,7 @@ public class DepthFirstStrategy implements Strategy { if (dseAdapter.getDepth() >= maxDepth) { var isSuccessfulUndo = dseAdapter.backtrack(); if (!isSuccessfulUndo) { -// "Reached max depth but cannot backtrack." + // Reached max depth but cannot backtrack. break; } } @@ -104,16 +104,11 @@ public class DepthFirstStrategy implements Strategy { Collection activations; do { activations = dseAdapter.getUntraversedActivations(); - if (activations.isEmpty()) { - if (!dseAdapter.backtrack()) { - // "No more transitions from current state and cannot backtrack." - break mainloop; - } - else { - // "No more transitions from current state, backtrack." - continue; - } + if (activations.isEmpty() && !dseAdapter.backtrack()) { + // No more transitions from current state and cannot backtrack. + break mainloop; } + // No more transitions from current state, backtrack. } while (activations.isEmpty()); dseAdapter.fireRandomActivation(); 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 4bdb05ec..f1e90280 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 @@ -25,7 +25,7 @@ import java.util.List; import static tools.refinery.store.query.literal.Literals.not; -public class CRAExamplesTest { +class CRAExamplesTest { private static final Symbol name = Symbol.of("Name", 1, String.class); // private static final Symbol classModel = Symbol.of("ClassModel", 1); 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 101a5362..553510c8 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 @@ -20,7 +20,7 @@ import tools.refinery.store.tuple.Tuple; import tools.refinery.visualization.ModelVisualizerAdapter; import tools.refinery.visualization.internal.FileFormat; -public class DebugTest { +class DebugTest { private static final Symbol classModel = Symbol.of("ClassModel", 1); private static final Symbol classElement = Symbol.of("ClassElement", 1); private static final Symbol feature = Symbol.of("Feature", 1); 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 f4644407..a379835d 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 @@ -21,7 +21,7 @@ import tools.refinery.visualization.ModelVisualizerAdapter; import static org.junit.jupiter.api.Assertions.assertEquals; -public class DesignSpaceExplorationTest { +class DesignSpaceExplorationTest { // private static final Symbol namedElement = Symbol.of("NamedElement", 1); // private static final Symbol attribute = Symbol.of("Attribute", 1); // private static final Symbol method = Symbol.of("Method", 1); 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 f57f68ef..3aa4c92e 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 @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static tools.refinery.store.query.literal.Literals.not; import static tools.refinery.store.dse.tests.QueryAssertions.assertResults; -public class TransformationRuleTest { +class TransformationRuleTest { private static final Symbol classModel = Symbol.of("ClassModel", 1); private static final Symbol classElement = Symbol.of("ClassElement", 1); diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java index 6599d4c3..6e6453fd 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java @@ -6,7 +6,6 @@ package tools.refinery.visualization; import tools.refinery.store.adapter.ModelStoreAdapter; -import tools.refinery.store.query.ModelQueryStoreAdapter; public interface ModelVisualizerStoreAdapter extends ModelStoreAdapter { } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java index 06cc8113..efafe5a2 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java @@ -21,38 +21,39 @@ import java.util.stream.Collectors; public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { private final Model model; private final ModelVisualizerStoreAdapter storeAdapter; - private final Map> interpretations; + private final Map> allInterpretations; private final StringBuilder designSpaceBuilder = new StringBuilder(); private final Map states = new HashMap<>(); private int transitionCounter = 0; private Integer numberOfStates = 0; - private static final Map truthValueToDot = new HashMap<>() - {{ - put(TruthValue.TRUE, "1"); - put(TruthValue.FALSE, "0"); - put(TruthValue.UNKNOWN, "½"); - put(TruthValue.ERROR, "E"); - put(true, "1"); - put(false, "0"); - }}; + private static final Map truthValueToDot = Map.of( + TruthValue.TRUE, "1", + TruthValue.FALSE, "0", + TruthValue.UNKNOWN, "½", + TruthValue.ERROR, "E", + true, "1", + false, "0" + ); public ModelVisualizerAdapterImpl(Model model, ModelVisualizerStoreAdapter storeAdapter) { this.model = model; this.storeAdapter = storeAdapter; - this.interpretations = new HashMap<>(); + this.allInterpretations = new HashMap<>(); for (var symbol : storeAdapter.getStore().getSymbols()) { var arity = symbol.arity(); if (arity < 1 || arity > 2) { continue; } var interpretation = (Interpretation) model.getInterpretation(symbol); - interpretations.put(symbol, interpretation); + allInterpretations.put(symbol, interpretation); } designSpaceBuilder.append("digraph designSpace {\n"); designSpaceBuilder.append(""" + nodesep=0 + ranksep=5 node[ - style=filled - fillcolor=white + \tstyle=filled + \tfillcolor=white ] """); } @@ -90,7 +91,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { ] """); - for (var entry : interpretations.entrySet()) { + for (var entry : allInterpretations.entrySet()) { var key = entry.getKey(); var arity = key.arity(); var cursor = entry.getValue().getAll(); @@ -302,6 +303,20 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { designSpaceBuilder.append(states.get(state)).append(" [URL=\"./").append(states.get(state)).append(".svg\"]\n"); } + @Override + public void addState(Version state, Collection fitness) { + if (states.containsKey(state)) { + return; + } + states.put(state, numberOfStates++); + designSpaceBuilder.append(states.get(state)).append(" [label = \"").append(states.get(state)).append(" ("); + + for (var f : fitness) { + designSpaceBuilder.append(f).append(", "); + } + designSpaceBuilder.append(")\"\n").append("URL=\"./").append(states.get(state)).append(".svg\"]\n"); + } + @Override public void addSolution(Version state) { addState(state); @@ -329,12 +344,12 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { @Override public boolean renderDesignSpace(String path, FileFormat format) { - for (var entry : states.entrySet()) { - var stateId = entry.getValue(); - var stateDot = createDotForModelState(entry.getKey()); - saveDot(stateDot, path + "/" + stateId + ".dot"); - renderDot(stateDot, format, path + "/" + stateId + "." + format.getFormat()); - } +// for (var entry : states.entrySet()) { +// var stateId = entry.getValue(); +// var stateDot = createDotForModelState(entry.getKey()); +// saveDot(stateDot, path + "/" + stateId + ".dot"); +// renderDot(stateDot, format, path + "/" + stateId + "." + format.getFormat()); +// } var designSpaceDot = buildDesignSpaceDot(); saveDot(designSpaceDot, path + "/designSpace.dot"); return renderDot(designSpaceDot, format, path + "/designSpace." + format.getFormat()); -- cgit v1.2.3-70-g09d2 From d5d8ad817c2f7d348a1fb40ca3f627ccc4ea37d5 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 15:10:07 +0200 Subject: Update visualizer builder --- .../DesignSpaceExplorationAdapterImpl.java | 10 +-- .../AlwaysSatisfiedRandomHardObjective.java | 56 ++++++++++++++ .../tools/refinery/store/dse/CRAExamplesTest.java | 11 ++- .../java/tools/refinery/store/dse/DebugTest.java | 11 ++- .../visualization/ModelVisualizerAdapter.java | 22 ++---- .../visualization/ModelVisualizerBuilder.java | 5 ++ .../visualization/ModelVisualizerStoreAdapter.java | 11 +++ .../internal/ModelVisualizeStoreAdapterImpl.java | 33 +++++++- .../internal/ModelVisualizerAdapterImpl.java | 88 +++++++++++++++------- .../internal/ModelVisualizerBuilderImpl.java | 38 +++++++++- 10 files changed, 223 insertions(+), 62 deletions(-) create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java (limited to 'subprojects/store-dse/src/test') 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 1329480c..008b2dab 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 @@ -96,6 +96,9 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration trajectory.add(state); strategy.initStrategy(this); strategy.explore(); + if (isVisualizationEnabled) { + modelVisualizerAdapter.visualize(); + } return solutions; } @@ -247,7 +250,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration isNewState = !statesAndTraversedActivations.containsKey(newState); if (isVisualizationEnabled) { if (isNewState) { - modelVisualizerAdapter.addState(newState); + modelVisualizerAdapter.addState(newState, getFitness().values()); } // TODO: Change to this: modelVisualizerAdapter.addTransition(previousState, newState, activation.transformationRule().getName(), @@ -272,11 +275,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration fireActivation(activationId); } - @Override - public boolean isCurrentInTrajectory() { - return trajectory.contains(model.getState()); - } - public List getAllActivations() { List result = new LinkedList<>(); for (var rule : transformationRules) { diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java new file mode 100644 index 00000000..327d5e2f --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro + * Copyright (c) 2023 The Refinery Authors + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package tools.refinery.store.dse.objectives; + +import tools.refinery.store.dse.DesignSpaceExplorationAdapter; + +import java.util.Random; + +/** + * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution. + * + * @author Andras Szabolcs Nagy + * + */ +public class AlwaysSatisfiedRandomHardObjective extends BaseObjective { + + private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective"; + private static final Random random = new Random(0); + + public AlwaysSatisfiedRandomHardObjective() { + super(DEFAULT_NAME); + } + + public AlwaysSatisfiedRandomHardObjective(String name) { + super(name); + } + + @Override + public Double getFitness(DesignSpaceExplorationAdapter context) { +// return 0d; + return random.nextDouble(); + } + + @Override + public boolean isHardObjective() { + return true; + } + + @Override + public boolean satisfiesHardObjective(Double fitness) { + return true; + } + + @Override + public Objective createNew() { + return this; + } + +} 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 f1e90280..23f0e703 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 @@ -188,7 +188,13 @@ class CRAExamplesTest { .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition, deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition, moveFeaturePrecondition)) - .with(ModelVisualizerAdapter.builder()) + .with(ModelVisualizerAdapter.builder() + .withOutputpath("test_output") + .withFormat(FileFormat.DOT) + .withFormat(FileFormat.SVG) + .saveStates() + .saveDesignSpace() + ) .with(DesignSpaceExplorationAdapter.builder() .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) // .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled() @@ -271,9 +277,6 @@ class CRAExamplesTest { var states = dseAdapter.explore(); System.out.println("states size: " + states.size()); - System.out.println("states: " + states); - var visualizer = model.getAdapter(ModelVisualizerAdapter.class); - visualizer.renderDesignSpace("test_output", FileFormat.SVG); } } 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 553510c8..88c4f152 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 @@ -90,7 +90,13 @@ class DebugTest { .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition, createFeaturePrecondition)) - .with(ModelVisualizerAdapter.builder()) + .with(ModelVisualizerAdapter.builder() + .withOutputpath("test_output") + .withFormat(FileFormat.DOT) + .withFormat(FileFormat.SVG) + .saveStates() + .saveDesignSpace() + ) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() @@ -113,10 +119,7 @@ class DebugTest { var states = dseAdapter.explore(); - var visualizer = model.getAdapter(ModelVisualizerAdapter.class); - visualizer.renderDesignSpace("test_output", FileFormat.SVG); System.out.println("states size: " + states.size()); - System.out.println("states: " + states); } } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java index bc32323d..ae87d8ac 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java @@ -8,9 +8,10 @@ package tools.refinery.visualization; import tools.refinery.store.adapter.ModelAdapter; import tools.refinery.store.map.Version; import tools.refinery.store.tuple.Tuple; -import tools.refinery.visualization.internal.FileFormat; import tools.refinery.visualization.internal.ModelVisualizerBuilderImpl; +import java.util.Collection; + public interface ModelVisualizerAdapter extends ModelAdapter { ModelVisualizerStoreAdapter getStoreAdapter(); @@ -18,27 +19,14 @@ public interface ModelVisualizerAdapter extends ModelAdapter { return new ModelVisualizerBuilderImpl(); } - public String createDotForCurrentModelState(); - - public String createDotForModelState(Version version); - - public boolean saveDot(String dot, String filePath); - - public boolean renderDot(String dot, String filePath); - - public boolean renderDot(String dot, FileFormat format, String filePath); - public void addTransition(Version from, Version to, String action); public void addTransition(Version from, Version to, String action, Tuple activation); public void addState(Version state); + public void addState(Version state, Collection fitness); + public void addState(Version state, String label); public void addSolution(Version state); - - public boolean saveDesignSpace(String path); - - public boolean renderDesignSpace(String path); - - public boolean renderDesignSpace(String path, FileFormat format); + public void visualize(); } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java index 56cc425e..592f5fcf 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerBuilder.java @@ -6,6 +6,11 @@ package tools.refinery.visualization; import tools.refinery.store.adapter.ModelAdapterBuilder; +import tools.refinery.visualization.internal.FileFormat; public interface ModelVisualizerBuilder extends ModelAdapterBuilder { + ModelVisualizerBuilder withOutputpath(String outputpath); + ModelVisualizerBuilder withFormat(FileFormat format); + ModelVisualizerBuilder saveDesignSpace(); + ModelVisualizerBuilder saveStates(); } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java index 6e6453fd..46663b2a 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerStoreAdapter.java @@ -6,6 +6,17 @@ package tools.refinery.visualization; import tools.refinery.store.adapter.ModelStoreAdapter; +import tools.refinery.visualization.internal.FileFormat; + +import java.util.Set; public interface ModelVisualizerStoreAdapter extends ModelStoreAdapter { + + String getOutputPath(); + + boolean isRenderDesignSpace(); + + boolean isRenderStates(); + + Set getFormats(); } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizeStoreAdapterImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizeStoreAdapterImpl.java index b4db2682..04be22d6 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizeStoreAdapterImpl.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizeStoreAdapterImpl.java @@ -10,11 +10,22 @@ import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelStore; import tools.refinery.visualization.ModelVisualizerStoreAdapter; +import java.util.Set; + public class ModelVisualizeStoreAdapterImpl implements ModelVisualizerStoreAdapter { private final ModelStore store; + private final String outputPath; + private final boolean renderDesignSpace; + private final boolean renderStates; + private final Set formats; - public ModelVisualizeStoreAdapterImpl(ModelStore store) { + public ModelVisualizeStoreAdapterImpl(ModelStore store, String outputPath, Set formats, + boolean renderDesignSpace, boolean renderStates) { this.store = store; + this.outputPath = outputPath; + this.formats = formats; + this.renderDesignSpace = renderDesignSpace; + this.renderStates = renderStates; } @Override @@ -26,4 +37,24 @@ public class ModelVisualizeStoreAdapterImpl implements ModelVisualizerStoreAdapt public ModelAdapter createModelAdapter(Model model) { return new ModelVisualizerAdapterImpl(model, this); } + + @Override + public String getOutputPath() { + return outputPath; + } + + @Override + public boolean isRenderDesignSpace() { + return renderDesignSpace; + } + + @Override + public boolean isRenderStates() { + return renderStates; + } + + @Override + public Set getFormats() { + return formats; + } } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java index efafe5a2..531969b4 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java @@ -26,6 +26,11 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { private final Map states = new HashMap<>(); private int transitionCounter = 0; private Integer numberOfStates = 0; + private final String outputPath; + private final Set formats; + private final boolean renderDesignSpace; + private final boolean renderStates; + private static final Map truthValueToDot = Map.of( TruthValue.TRUE, "1", TruthValue.FALSE, "0", @@ -38,6 +43,14 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { public ModelVisualizerAdapterImpl(Model model, ModelVisualizerStoreAdapter storeAdapter) { this.model = model; this.storeAdapter = storeAdapter; + this.outputPath = storeAdapter.getOutputPath(); + this.formats = storeAdapter.getFormats(); + if (formats.isEmpty()) { + formats.add(FileFormat.SVG); + } + this.renderDesignSpace = storeAdapter.isRenderDesignSpace(); + this.renderStates = storeAdapter.isRenderStates(); + this.allInterpretations = new HashMap<>(); for (var symbol : storeAdapter.getStore().getSymbols()) { var arity = symbol.arity(); @@ -68,8 +81,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return storeAdapter; } - @Override - public String createDotForCurrentModelState() { + private String createDotForCurrentModelState() { var unaryTupleToInterpretationsMap = new HashMap>>(); @@ -229,8 +241,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { }; } - @Override - public String createDotForModelState(Version version) { + private String createDotForModelState(Version version) { var currentVersion = model.getState(); model.restore(version); var graph = createDotForCurrentModelState(); @@ -238,8 +249,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return graph; } - @Override - public boolean saveDot(String dot, String filePath) { + private boolean saveDot(String dot, String filePath) { File file = new File(filePath); file.getParentFile().mkdirs(); @@ -252,13 +262,11 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return true; } - @Override - public boolean renderDot(String dot, String filePath) { + private boolean renderDot(String dot, String filePath) { return renderDot(dot, FileFormat.SVG, filePath); } - @Override - public boolean renderDot(String dot, FileFormat format, String filePath) { + private boolean renderDot(String dot, FileFormat format, String filePath) { try { Process process = new ProcessBuilder("dot", "-T" + format.getFormat(), "-o", filePath).start(); @@ -305,15 +313,21 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { @Override public void addState(Version state, Collection fitness) { + var labelBuilder = new StringBuilder(); + for (var f : fitness) { + labelBuilder.append(f).append(", "); + } + addState(state, labelBuilder.toString()); + } + + @Override + public void addState(Version state, String label) { if (states.containsKey(state)) { return; } states.put(state, numberOfStates++); designSpaceBuilder.append(states.get(state)).append(" [label = \"").append(states.get(state)).append(" ("); - - for (var f : fitness) { - designSpaceBuilder.append(f).append(", "); - } + designSpaceBuilder.append(label); designSpaceBuilder.append(")\"\n").append("URL=\"./").append(states.get(state)).append(".svg\"]\n"); } @@ -328,8 +342,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return designSpaceBuilder.toString(); } - @Override - public boolean saveDesignSpace(String path) { + private boolean saveDesignSpace(String path) { saveDot(buildDesignSpaceDot(), path + "/designSpace.dot"); for (var entry : states.entrySet()) { saveDot(createDotForModelState(entry.getKey()), path + "/" + entry.getValue() + ".dot"); @@ -337,21 +350,38 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return true; } - @Override - public boolean renderDesignSpace(String path) { - return renderDesignSpace(path, FileFormat.SVG); + private void renderDesignSpace(String path, Set formats) { + File filePath = new File(path); + filePath.mkdirs(); + if (renderStates) { + for (var entry : states.entrySet()) { + var stateId = entry.getValue(); + var stateDot = createDotForModelState(entry.getKey()); + for (var format : formats) { + if (format == FileFormat.DOT) { + saveDot(stateDot, path + "/" + stateId + ".dot"); + } + else { + renderDot(stateDot, format, path + "/" + stateId + "." + format.getFormat()); + } + } + } + } + if (renderDesignSpace) { + var designSpaceDot = buildDesignSpaceDot(); + for (var format : formats) { + if (format == FileFormat.DOT) { + saveDot(designSpaceDot, path + "/designSpace.dot"); + } + else { + renderDot(designSpaceDot, format, path + "/designSpace." + format.getFormat()); + } + } + } } @Override - public boolean renderDesignSpace(String path, FileFormat format) { -// for (var entry : states.entrySet()) { -// var stateId = entry.getValue(); -// var stateDot = createDotForModelState(entry.getKey()); -// saveDot(stateDot, path + "/" + stateId + ".dot"); -// renderDot(stateDot, format, path + "/" + stateId + "." + format.getFormat()); -// } - var designSpaceDot = buildDesignSpaceDot(); - saveDot(designSpaceDot, path + "/designSpace.dot"); - return renderDot(designSpaceDot, format, path + "/designSpace." + format.getFormat()); + public void visualize() { + renderDesignSpace(outputPath, formats); } } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java index d19cf2cf..e4d801d8 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerBuilderImpl.java @@ -9,11 +9,47 @@ import tools.refinery.store.adapter.AbstractModelAdapterBuilder; import tools.refinery.store.model.ModelStore; import tools.refinery.visualization.ModelVisualizerBuilder; +import java.util.LinkedHashSet; +import java.util.Set; + public class ModelVisualizerBuilderImpl extends AbstractModelAdapterBuilder implements ModelVisualizerBuilder { + private String outputPath; + private boolean saveDesignSpace = false; + private boolean saveStates = false; + private Set formats = new LinkedHashSet<>(); + @Override protected ModelVisualizeStoreAdapterImpl doBuild(ModelStore store) { - return new ModelVisualizeStoreAdapterImpl(store); + return new ModelVisualizeStoreAdapterImpl(store, outputPath, formats, saveDesignSpace, saveStates); + } + + @Override + public ModelVisualizerBuilder withOutputpath(String outputpath) { + checkNotConfigured(); + this.outputPath = outputpath; + return this; + } + + @Override + public ModelVisualizerBuilder withFormat(FileFormat format) { + checkNotConfigured(); + this.formats.add(format); + return this; + } + + @Override + public ModelVisualizerBuilder saveDesignSpace() { + checkNotConfigured(); + this.saveDesignSpace = true; + return this; + } + + @Override + public ModelVisualizerBuilder saveStates() { + checkNotConfigured(); + this.saveStates = true; + return this; } } -- cgit v1.2.3-70-g09d2 From 52bd73128478c44bcbeb49ba3b8c971976053bcd Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 15:10:36 +0200 Subject: Add dummy objective with random fitness --- .../src/test/java/tools/refinery/store/dse/CRAExamplesTest.java | 2 ++ .../store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java | 2 ++ 2 files changed, 4 insertions(+) (limited to 'subprojects/store-dse/src/test') 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 23f0e703..2fe9fec3 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 @@ -6,6 +6,7 @@ package tools.refinery.store.dse; import org.junit.jupiter.api.Test; +import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; import tools.refinery.store.model.ModelStore; import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.query.dnf.Query; @@ -197,6 +198,7 @@ class CRAExamplesTest { ) .with(DesignSpaceExplorationAdapter.builder() .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) + .objectives(new AlwaysSatisfiedRandomHardObjective()) // .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled() .strategy(new BestFirstStrategy(6).continueIfHardObjectivesFulfilled() // .goOnOnlyIfFitnessIsBetter() 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 88c4f152..2cb59ec7 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 @@ -6,6 +6,7 @@ package tools.refinery.store.dse; import org.junit.jupiter.api.Test; +import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; import tools.refinery.store.model.ModelStore; import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.query.dnf.Query; @@ -99,6 +100,7 @@ class DebugTest { ) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) + .objectives(new AlwaysSatisfiedRandomHardObjective()) .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() // .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() // .goOnOnlyIfFitnessIsBetter() -- cgit v1.2.3-70-g09d2 From 9c0f8f8a28aaaec01a6177aacd0c4dddd8a2b7ed Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 15:16:51 +0200 Subject: Disable tests --- .../src/test/java/tools/refinery/store/dse/CRAExamplesTest.java | 2 ++ .../store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java | 2 ++ 2 files changed, 4 insertions(+) (limited to 'subprojects/store-dse/src/test') 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 2fe9fec3..d761db02 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 @@ -5,6 +5,7 @@ */ package tools.refinery.store.dse; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; import tools.refinery.store.model.ModelStore; @@ -181,6 +182,7 @@ class CRAExamplesTest { }); @Test + @Disabled("This test is only for debugging purposes") void craTest() { var store = ModelStore.builder() .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency, 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 2cb59ec7..36bc6cce 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 @@ -5,6 +5,7 @@ */ package tools.refinery.store.dse; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import tools.refinery.store.dse.objectives.AlwaysSatisfiedRandomHardObjective; import tools.refinery.store.model.ModelStore; @@ -42,6 +43,7 @@ class DebugTest { @Test + @Disabled("This test is only for debugging purposes") void BFSTest() { var createClassPrecondition = Query.of("CreateClassPrecondition", (builder, model) -> builder.clause( -- cgit v1.2.3-70-g09d2 From 31447338dede415158b017fd78a6b6036cddc511 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 15:26:37 +0200 Subject: Remove visualization from DSE tests --- .../tools/refinery/store/dse/DesignSpaceExplorationTest.java | 9 --------- 1 file changed, 9 deletions(-) (limited to 'subprojects/store-dse/src/test') 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 a379835d..89adbf65 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 @@ -17,7 +17,6 @@ import tools.refinery.store.query.view.AnySymbolView; import tools.refinery.store.query.view.KeyOnlyView; import tools.refinery.store.representation.Symbol; import tools.refinery.store.tuple.Tuple; -import tools.refinery.visualization.ModelVisualizerAdapter; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -118,7 +117,6 @@ class DesignSpaceExplorationTest { var store = ModelStore.builder() .symbols(classModel) .with(ViatraModelQueryAdapter.builder()) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .strategy(new DepthFirstStrategy(0))) .build(); @@ -158,7 +156,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) .strategy(new DepthFirstStrategy(4) @@ -205,7 +202,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() @@ -274,7 +270,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition, createFeaturePrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) .strategy(new DepthFirstStrategy(10).continueIfHardObjectivesFulfilled() @@ -298,7 +293,6 @@ class DesignSpaceExplorationTest { var store = ModelStore.builder() .symbols(classModel) .with(ViatraModelQueryAdapter.builder()) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .strategy(new BestFirstStrategy(0))) .build(); @@ -338,7 +332,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) .strategy(new BestFirstStrategy(4) @@ -385,7 +378,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() @@ -454,7 +446,6 @@ class DesignSpaceExplorationTest { .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) .with(ViatraModelQueryAdapter.builder() .queries(createClassPrecondition, createFeaturePrecondition)) - .with(ModelVisualizerAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) .strategy(new BestFirstStrategy(10).continueIfHardObjectivesFulfilled() -- cgit v1.2.3-70-g09d2 From 1f853e4590d7f235bf8a63fa017fc92369a80a5a Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Tue, 8 Aug 2023 13:57:19 +0200 Subject: Refactor search strategy to improve readability --- .../java/tools/refinery/store/dse/Strategy.java | 2 +- .../DesignSpaceExplorationAdapterImpl.java | 10 +- .../store/dse/strategy/BestFirstStrategy.java | 29 ++-- .../store/dse/strategy/DepthFirstStrategy.java | 55 +++---- .../tools/refinery/store/dse/CRAExamplesTest.java | 4 +- .../java/tools/refinery/store/dse/DebugTest.java | 4 +- .../store/dse/DesignSpaceExplorationTest.java | 168 +++++++++++++++++++-- .../refinery/store/dse/TransformationRuleTest.java | 13 +- 8 files changed, 201 insertions(+), 84 deletions(-) (limited to 'subprojects/store-dse/src/test') 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; public interface Strategy { - void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); + void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); void explore(); } 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 private final Map fitnessCache = new HashMap<>(); - public List getTrajectory() { - return new ArrayList<>(trajectory); - } - public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { this.model = model; this.storeAdapter = storeAdapter; @@ -75,11 +71,16 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration objectives = storeAdapter.getObjectives(); statesAndTraversedActivations = new HashMap<>(); strategy = storeAdapter.getStrategy(); + strategy.initialize(this); modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); isVisualizationEnabled = modelVisualizerAdapter != null; } + public List getTrajectory() { + return new ArrayList<>(trajectory); + } + @Override public Model getModel() { return model; @@ -94,7 +95,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration public List explore() { var state = model.commit(); trajectory.add(state); - strategy.initStrategy(this); strategy.explore(); if (isVisualizationEnabled) { 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 { private DesignSpaceExplorationAdapter dseAdapter; - private final int maxDepth; - private final int maxSolutions; + private int maxDepth = Integer.MAX_VALUE; + private int maxSolutions = Integer.MAX_VALUE; private boolean backTrackIfSolution = true; private boolean onlyBetterFirst = false; @@ -50,25 +50,18 @@ public class BestFirstStrategy implements Strategy { } } - public BestFirstStrategy() { - this(-1); - } - - public BestFirstStrategy(int maxDepth) { - this(maxDepth, -1); - } - - public BestFirstStrategy(int maxDepth, int maxSolutions) { - if (maxDepth < 0) { - this.maxDepth = Integer.MAX_VALUE; - } else { + public BestFirstStrategy withDepthLimit(int maxDepth) { + if (maxDepth >= 0) { this.maxDepth = maxDepth; } - if (maxSolutions < 0) { - this.maxSolutions = Integer.MAX_VALUE; - } else { + return this; + } + + public BestFirstStrategy withSolutionLimit(int maxSolutions) { + if (maxSolutions >= 0) { this.maxSolutions = maxSolutions; } + return this; } public BestFirstStrategy continueIfHardObjectivesFulfilled() { @@ -82,7 +75,7 @@ public class BestFirstStrategy implements Strategy { } @Override - public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { + public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { this.dseAdapter = designSpaceExplorationAdapter; final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); 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 @@ -/******************************************************************************* - * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro - * Copyright (c) 2023 The Refinery Authors - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-v20.html. +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors * * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ + */ package tools.refinery.store.dse.strategy; import tools.refinery.store.dse.DesignSpaceExplorationAdapter; @@ -17,38 +13,31 @@ public class DepthFirstStrategy implements Strategy { private DesignSpaceExplorationAdapter dseAdapter; - private int maxDepth; - private int maxSolutions; - private boolean backTrackIfSolution = true; + private int maxDepth = Integer.MAX_VALUE; + private int maxSolutions = Integer.MAX_VALUE; + private boolean backtrackFromSolution = true; - public DepthFirstStrategy() { - this(-1); - } - - public DepthFirstStrategy(int maxDepth) { - this(maxDepth, -1); - } - - public DepthFirstStrategy(int maxDepth, int maxSolutions) { - if (maxDepth < 0) { - this.maxDepth = Integer.MAX_VALUE; - } else { + public DepthFirstStrategy withDepthLimit(int maxDepth) { + if (maxDepth >= 0) { this.maxDepth = maxDepth; } - if (maxSolutions < 0) { - this.maxSolutions = Integer.MAX_VALUE; - } else { + return this; + } + + public DepthFirstStrategy withSolutionLimit(int maxSolutions) { + if (maxSolutions >= 0) { this.maxSolutions = maxSolutions; } + return this; } public DepthFirstStrategy continueIfHardObjectivesFulfilled() { - backTrackIfSolution = false; + backtrackFromSolution = false; return this; } @Override - public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { + public void initialize(DesignSpaceExplorationAdapter designSpaceExplorationAdapter) { this.dseAdapter = designSpaceExplorationAdapter; } @@ -59,22 +48,18 @@ public class DepthFirstStrategy implements Strategy { } while (dseAdapter.getSolutions().size() < maxSolutions) { if (!checkAndHandleGlobalConstraints()) { - // Global constraint is not satisfied and cannot backtrack. return; } - // Global constraint is not satisfied, backtrack. Fitness fitness = dseAdapter.getFitness(); if (fitness.isSatisfiesHardObjectives()) { dseAdapter.newSolution(); - if (backTrackIfSolution && !dseAdapter.backtrack()) { - // Found a solution but cannot backtrack. + if (backtrackFromSolution && !dseAdapter.backtrack()) { return; } } if (!checkAndHandleDepth()) { - // Reached max depth but cannot backtrack. return; } @@ -87,24 +72,18 @@ public class DepthFirstStrategy implements Strategy { } private boolean checkAndHandleGlobalConstraints() { - // Global constraint is not satisfied and cannot backtrack. return dseAdapter.checkGlobalConstraints() || dseAdapter.backtrack(); - // Global constraint is satisfied or backtrack. } private boolean checkAndHandleDepth() { - // Reached max depth but cannot backtrack. return dseAdapter.getDepth() < maxDepth || dseAdapter.backtrack(); - // Reached max depth or backtrack. } private boolean backtrackToLastUntraversed() { while (dseAdapter.getUntraversedActivations().isEmpty()) { if (!dseAdapter.backtrack()) { - // No more transitions from current state and cannot backtrack. return false; } - // No more transitions from current state, backtrack. } return true; } 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 { .with(DesignSpaceExplorationAdapter.builder() .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) .objectives(new AlwaysSatisfiedRandomHardObjective()) -// .strategy(new DepthFirstStrategy(3).continueIfHardObjectivesFulfilled() - .strategy(new BestFirstStrategy(6).continueIfHardObjectivesFulfilled() +// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled() + .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled() // .goOnOnlyIfFitnessIsBetter() )) .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 { .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) .objectives(new AlwaysSatisfiedRandomHardObjective()) - .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() -// .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() + .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() +// .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() // .goOnOnlyIfFitnessIsBetter() )) .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 { void createObjectTest() { var store = ModelStore.builder() .with(ViatraModelQueryAdapter.builder()) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -77,7 +78,8 @@ class DesignSpaceExplorationTest { void deleteMiddleObjectTest() { var store = ModelStore.builder() .with(ViatraModelQueryAdapter.builder()) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy())) .build(); var model = store.createEmptyModel(); @@ -118,7 +120,7 @@ class DesignSpaceExplorationTest { .symbols(classModel) .with(ViatraModelQueryAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() - .strategy(new DepthFirstStrategy(0))) + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -158,7 +160,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) - .strategy(new DepthFirstStrategy(4) + .strategy(new DepthFirstStrategy().withDepthLimit(0) )) .build(); @@ -204,7 +206,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) - .strategy(new DepthFirstStrategy(4).continueIfHardObjectivesFulfilled() + .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() )) .build(); @@ -272,7 +274,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition, createFeaturePrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) - .strategy(new DepthFirstStrategy(10).continueIfHardObjectivesFulfilled() + .strategy(new DepthFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled() )) .build(); @@ -289,12 +291,81 @@ class DesignSpaceExplorationTest { } @Test - void BFSTrivialTest() { + void DFSSolutionLimitTest() { + var createClassPrecondition = Query.of("CreateClassPrecondition", + (builder, model) -> builder.clause( + classModelView.call(model) + )); + + var createClassRule = new TransformationRule("CreateClass", + createClassPrecondition, + (model) -> { + var classesInterpretation = model.getInterpretation(classes); + var classElementInterpretation = model.getInterpretation(classElement); + return ((Tuple activation) -> { + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var modelElement = activation.get(0); + + var newClassElement = dseAdapter.createObject(); + var newClassElementId = newClassElement.get(0); + + classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); + classElementInterpretation.put(Tuple.of(newClassElementId), true); + }); + }); + + var createFeaturePrecondition = Query.of("CreateFeaturePrecondition", + (builder, model) -> builder.clause( + classModelView.call(model) + )); + + var createFeatureRule = new TransformationRule("CreateFeature", + createFeaturePrecondition, + (model) -> { + var featuresInterpretation = model.getInterpretation(features); + var featureInterpretation = model.getInterpretation(feature); + return ((Tuple activation) -> { + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var modelElement = activation.get(0); + + var newClassElement = dseAdapter.createObject(); + var newClassElementId = newClassElement.get(0); + + featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true); + featureInterpretation.put(Tuple.of(newClassElementId), true); + }); + }); + + var store = ModelStore.builder() + .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) + .with(ViatraModelQueryAdapter.builder() + .queries(createClassPrecondition, createFeaturePrecondition)) + .with(DesignSpaceExplorationAdapter.builder() + .transformations(createClassRule, createFeatureRule) + .strategy(new DepthFirstStrategy().withSolutionLimit(222) + .continueIfHardObjectivesFulfilled() + )) + .build(); + + var model = store.createEmptyModel(); + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var queryEngine = model.getAdapter(ModelQueryAdapter.class); + + var modelElementInterpretation = model.getInterpretation(classModel); + modelElementInterpretation.put(dseAdapter.createObject(), true); + queryEngine.flushChanges(); + + var states = dseAdapter.explore(); + assertEquals(222, states.size()); + } + + @Test + void BeFSTrivialTest() { var store = ModelStore.builder() .symbols(classModel) .with(ViatraModelQueryAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() - .strategy(new BestFirstStrategy(0))) + .strategy(new BestFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -305,7 +376,7 @@ class DesignSpaceExplorationTest { } @Test - void BFSOneRuleTest() { + void BeFSOneRuleTest() { var createClassPrecondition = Query.of("CreateClassPrecondition", (builder, model) -> builder.clause( classModelView.call(model) @@ -334,7 +405,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) - .strategy(new BestFirstStrategy(4) + .strategy(new BestFirstStrategy().withDepthLimit(4) )) .build(); @@ -351,7 +422,7 @@ class DesignSpaceExplorationTest { } @Test - void BFSContinueTest() { + void BeFSContinueTest() { var createClassPrecondition = Query.of("CreateClassPrecondition", (builder, model) -> builder.clause( classModelView.call(model) @@ -380,7 +451,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule) - .strategy(new BestFirstStrategy(4).continueIfHardObjectivesFulfilled() + .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() )) .build(); @@ -397,7 +468,7 @@ class DesignSpaceExplorationTest { } @Test - void BFSCompletenessTest() { + void BeFSCompletenessTest() { var createClassPrecondition = Query.of("CreateClassPrecondition", (builder, model) -> builder.clause( classModelView.call(model) @@ -448,7 +519,7 @@ class DesignSpaceExplorationTest { .queries(createClassPrecondition, createFeaturePrecondition)) .with(DesignSpaceExplorationAdapter.builder() .transformations(createClassRule, createFeatureRule) - .strategy(new BestFirstStrategy(10).continueIfHardObjectivesFulfilled() + .strategy(new BestFirstStrategy().withDepthLimit(10).continueIfHardObjectivesFulfilled() )) .build(); @@ -464,4 +535,73 @@ class DesignSpaceExplorationTest { assertEquals(2047, states.size()); } + @Test + void BeFSSolutionLimitTest() { + var createClassPrecondition = Query.of("CreateClassPrecondition", + (builder, model) -> builder.clause( + classModelView.call(model) + )); + + var createClassRule = new TransformationRule("CreateClass", + createClassPrecondition, + (model) -> { + var classesInterpretation = model.getInterpretation(classes); + var classElementInterpretation = model.getInterpretation(classElement); + return ((Tuple activation) -> { + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var modelElement = activation.get(0); + + var newClassElement = dseAdapter.createObject(); + var newClassElementId = newClassElement.get(0); + + classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); + classElementInterpretation.put(Tuple.of(newClassElementId), true); + }); + }); + + var createFeaturePrecondition = Query.of("CreateFeaturePrecondition", + (builder, model) -> builder.clause( + classModelView.call(model) + )); + + var createFeatureRule = new TransformationRule("CreateFeature", + createFeaturePrecondition, + (model) -> { + var featuresInterpretation = model.getInterpretation(features); + var featureInterpretation = model.getInterpretation(feature); + return ((Tuple activation) -> { + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var modelElement = activation.get(0); + + var newClassElement = dseAdapter.createObject(); + var newClassElementId = newClassElement.get(0); + + featuresInterpretation.put(Tuple.of(modelElement, newClassElementId), true); + featureInterpretation.put(Tuple.of(newClassElementId), true); + }); + }); + + var store = ModelStore.builder() + .symbols(classModel, classElement, classes, feature, features, isEncapsulatedBy, encapsulates) + .with(ViatraModelQueryAdapter.builder() + .queries(createClassPrecondition, createFeaturePrecondition)) + .with(DesignSpaceExplorationAdapter.builder() + .transformations(createClassRule, createFeatureRule) + .strategy(new BestFirstStrategy().withSolutionLimit(222) + .continueIfHardObjectivesFulfilled() + )) + .build(); + + var model = store.createEmptyModel(); + var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); + var queryEngine = model.getAdapter(ModelQueryAdapter.class); + + var modelElementInterpretation = model.getInterpretation(classModel); + modelElementInterpretation.put(dseAdapter.createObject(), true); + queryEngine.flushChanges(); + + var states = dseAdapter.explore(); + assertEquals(222, states.size()); + } + } 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 @@ package tools.refinery.store.dse; import org.junit.jupiter.api.Test; +import tools.refinery.store.dse.strategy.DepthFirstStrategy; import tools.refinery.store.model.ModelStore; import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.query.dnf.Query; @@ -103,7 +104,8 @@ class TransformationRuleTest { .with(ViatraModelQueryAdapter.builder() .queries(assignFeaturePrecondition, assignFeaturePreconditionHelper, deleteEmptyClassPrecondition)) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -195,7 +197,8 @@ class TransformationRuleTest { .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) .with(ViatraModelQueryAdapter.builder() .queries(deleteEmptyClassPrecondition)) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -276,7 +279,8 @@ class TransformationRuleTest { .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) .with(ViatraModelQueryAdapter.builder() .queries(deleteEmptyClassPrecondition)) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); @@ -352,7 +356,8 @@ class TransformationRuleTest { .symbols(classModel, classElement, feature, isEncapsulatedBy, encapsulates, classes, features) .with(ViatraModelQueryAdapter.builder() .queries(deleteEmptyClassPrecondition)) - .with(DesignSpaceExplorationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .strategy(new DepthFirstStrategy().withDepthLimit(0))) .build(); var model = store.createEmptyModel(); -- cgit v1.2.3-70-g09d2