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 --- .../store/dse/DesignSpaceExplorationAdapter.java | 6 +- .../dse/DesignSpaceExplorationStoreAdapter.java | 18 +++++ .../java/tools/refinery/store/dse/Strategy.java | 4 +- .../DesignSpaceExplorationAdapterImpl.java | 92 ++++++++++++---------- .../DesignSpaceExplorationStoreAdapterImpl.java | 27 ++++--- .../store/dse/internal/TransformationRule.java | 16 +++- .../store/dse/strategy/BestFirstStrategy.java | 36 +++++++-- .../store/dse/strategy/DepthFirstStrategy.java | 20 ++++- 8 files changed, 152 insertions(+), 67 deletions(-) (limited to 'subprojects/store-dse/src/main/java/tools') 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 8963a496..c4aa97c2 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 @@ -38,7 +38,9 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter { public boolean backtrack(); - public Fitness calculateFitness(); + public boolean backtrack(String reason); + + public Fitness getFitness(); public void newSolution(); @@ -63,4 +65,6 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter { public void setRandom(Random random); public void setRandom(long seed); + + public List getSolutions(); } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java index 186bfebb..0252748d 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationStoreAdapter.java @@ -6,6 +6,24 @@ package tools.refinery.store.dse; import tools.refinery.store.adapter.ModelStoreAdapter; +import tools.refinery.store.dse.internal.TransformationRule; +import tools.refinery.store.dse.objectives.Objective; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.dnf.RelationalQuery; + +import java.util.List; +import java.util.Set; public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter { + + @Override + DesignSpaceExplorationAdapter createModelAdapter(Model model); + + Set getTransformationSpecifications(); + + Set getGlobalConstraints(); + + List getObjectives(); + + Strategy getStrategy(); } 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 e240f478..409fe8a6 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 { - public void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); + void initStrategy(DesignSpaceExplorationAdapter designSpaceExplorationAdapter); - public void explore(); + 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 b32e9696..4e5cc467 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 @@ -33,26 +33,28 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration private final Model model; private final ModelQueryAdapter queryEngine; private final DesignSpaceExplorationStoreAdapterImpl storeAdapter; - private final LinkedHashSet transformationRules; - private final LinkedHashSet globalConstraints; + private final Set transformationRules; + private final Set globalConstraints; private final List objectives; private final LinkedHashSet> globalConstraintResultSets = new LinkedHashSet<>(); private final Interpretation sizeInterpretation; private final Strategy strategy; private ObjectiveComparatorHelper objectiveComparatorHelper; - private List trajectory = new LinkedList<>(); + private List trajectory = new ArrayList<>(); + private Map parents = new HashMap<>(); private Fitness lastFitness; - private final LinkedHashSet solutions = new LinkedHashSet<>(); - private Map> statesAndUntraversedActivations; - private Map> statesAndTraversedActivations; + private final List solutions = new ArrayList<>(); + private Map> statesAndTraversedActivations; private Random random = new Random(); private boolean isNewState = false; private final boolean isVisualizationEnabled; private final ModelVisualizerAdapter modelVisualizerAdapter; + private final Map fitnessCache = new HashMap<>(); + public List getTrajectory() { - return new LinkedList<>(trajectory); + return new ArrayList<>(trajectory); } public DesignSpaceExplorationAdapterImpl(Model model, DesignSpaceExplorationStoreAdapterImpl storeAdapter) { @@ -72,7 +74,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } objectives = storeAdapter.getObjectives(); - statesAndUntraversedActivations = new HashMap<>(); statesAndTraversedActivations = new HashMap<>(); strategy = storeAdapter.getStrategy(); modelVisualizerAdapter = model.tryGetAdapter(ModelVisualizerAdapter.class).orElse(null); @@ -91,11 +92,9 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } @Override - public LinkedHashSet explore() { + public List explore() { var state = model.commit(); trajectory.add(state); - statesAndUntraversedActivations.put(state, getAllActivations()); - statesAndTraversedActivations.put(state, new LinkedHashSet<>()); strategy.initStrategy(this); strategy.explore(); return solutions; @@ -137,14 +136,22 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration @Override public boolean backtrack() { + return backtrack(""); + } + @Override + public boolean backtrack(String reason) { if (trajectory.size() < 2) { return false; } + var currentState = model.getState(); + if (!parents.containsKey(currentState)) { + return false; + } if (isVisualizationEnabled) { modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 1), - trajectory.get(trajectory.size() - 2), "backtrack"); + trajectory.get(trajectory.size() - 2), "backtrack(" + reason + ")"); } - model.restore(trajectory.get(trajectory.size() - 2)); + model.restore(parents.get(model.getState())); trajectory.remove(trajectory.size() - 1); return true; } @@ -156,7 +163,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration // modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1), // trajectory.get(trajectory.size() - 1), "restore"); // } - this.trajectory = trajectory; + this.trajectory = new ArrayList<>(trajectory); } @@ -171,7 +178,18 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } @Override - public Fitness calculateFitness() { + public List getSolutions() { + return solutions; + } + + @Override + public Fitness getFitness() { + var result = fitnessCache.computeIfAbsent(model.getState(), s -> calculateFitness()); + lastFitness = result; + return result; + } + + private Fitness calculateFitness() { Fitness result = new Fitness(); boolean satisfiesHardObjectives = true; for (Objective objective : objectives) { @@ -203,15 +221,19 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } public LinkedHashSet getUntraversedActivations() { -// return statesAndUntraversedActivations.get(model.getState()); - LinkedHashSet untraversedActivations = new LinkedHashSet<>(); - for (Activation activation : getAllActivations()) { - if (!statesAndTraversedActivations.get(model.getState()).contains(activation)) { - untraversedActivations.add(activation); + var traversedActivations = statesAndTraversedActivations.get(model.getState()); + if (traversedActivations == null) { + return new LinkedHashSet<>(getAllActivations()); + } + else { + LinkedHashSet untraversedActivations = new LinkedHashSet<>(); + for (Activation activation : getAllActivations()) { + if (!traversedActivations.contains(activation)) { + untraversedActivations.add(activation); + } } + return untraversedActivations; } - - return untraversedActivations; } @Override @@ -220,26 +242,20 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration return false; } var previousState = model.getState(); - if (!statesAndUntraversedActivations.get(previousState).contains(activation)) { -// TODO: throw exception? - return false; - } if (!activation.fire()) { return false; } - statesAndUntraversedActivations.get(previousState).remove(activation); - statesAndTraversedActivations.get(previousState).add(activation); + statesAndTraversedActivations.computeIfAbsent(previousState, s -> new ArrayList<>()).add(activation); var newState = model.commit(); trajectory.add(newState); - isNewState = !statesAndUntraversedActivations.containsKey(newState); - statesAndUntraversedActivations.put(newState, getAllActivations()); - statesAndTraversedActivations.put(newState, new LinkedHashSet<>()); + parents.put(newState, previousState); + isNewState = !statesAndTraversedActivations.containsKey(newState); if (isVisualizationEnabled) { if (isNewState) { modelVisualizerAdapter.addState(newState); } - modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 2), - trajectory.get(trajectory.size() - 1), activation.transformationRule().getName(), + // TODO: Change to this: + modelVisualizerAdapter.addTransition(previousState, newState, activation.transformationRule().getName(), activation.activation()); } return true; @@ -266,10 +282,10 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration return trajectory.contains(model.getState()); } - public LinkedHashSet getAllActivations() { - LinkedHashSet result = new LinkedHashSet<>(); + public List getAllActivations() { + List result = new LinkedList<>(); for (var rule : transformationRules) { - result.addAll(rule.getAllActivations()); + result.addAll(rule.getAllActivationsAsList()); } return result; } @@ -279,10 +295,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration return !isNewState; } - public Fitness getLastFitness() { - return lastFitness; - } - public ObjectiveComparatorHelper getObjectiveComparatorHelper() { if (objectiveComparatorHelper == null) { objectiveComparatorHelper = new ObjectiveComparatorHelper(objectives); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java index 09925ae7..fea39886 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationStoreAdapterImpl.java @@ -5,27 +5,26 @@ */ package tools.refinery.store.dse.internal; -import tools.refinery.store.adapter.ModelAdapter; -import tools.refinery.store.model.Model; -import tools.refinery.store.model.ModelStore; -import tools.refinery.store.query.dnf.RelationalQuery; import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter; import tools.refinery.store.dse.Strategy; import tools.refinery.store.dse.objectives.Objective; +import tools.refinery.store.model.Model; +import tools.refinery.store.model.ModelStore; +import tools.refinery.store.query.dnf.RelationalQuery; -import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter { private final ModelStore store; - private final LinkedHashSet transformationSpecifications; - private final LinkedHashSet globalConstraints; + private final Set transformationSpecifications; + private final Set globalConstraints; private final List objectives; private final Strategy strategy; public DesignSpaceExplorationStoreAdapterImpl(ModelStore store, - LinkedHashSet transformationSpecifications, - LinkedHashSet globalConstraints, + Set transformationSpecifications, + Set globalConstraints, List objectives, Strategy strategy) { this.store = store; this.transformationSpecifications = transformationSpecifications; @@ -40,22 +39,26 @@ public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplor } @Override - public ModelAdapter createModelAdapter(Model model) { + public DesignSpaceExplorationAdapterImpl createModelAdapter(Model model) { return new DesignSpaceExplorationAdapterImpl(model, this); } - public LinkedHashSet getTransformationSpecifications() { + @Override + public Set getTransformationSpecifications() { return transformationSpecifications; } - public LinkedHashSet getGlobalConstraints() { + @Override + public Set getGlobalConstraints() { return globalConstraints; } + @Override public List getObjectives() { return objectives; } + @Override public Strategy getStrategy() { return strategy; } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java index 015d4815..8123c0d6 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java @@ -14,8 +14,7 @@ import tools.refinery.store.query.resultset.OrderedResultSet; import tools.refinery.store.query.resultset.ResultSet; import tools.refinery.store.tuple.Tuple; -import java.util.LinkedHashSet; -import java.util.Random; +import java.util.*; public class TransformationRule { @@ -66,11 +65,11 @@ public class TransformationRule { return precondition; } - public ResultSet getAllActivationsAsSets() { + public ResultSet getAllActivationsAsResultSet() { return activations; } - public LinkedHashSet getAllActivations() { + public Set getAllActivations() { var result = new LinkedHashSet(); var cursor = activations.getAll(); while (cursor.move()) { @@ -79,6 +78,15 @@ public class TransformationRule { return result; } + public List getAllActivationsAsList() { + var result = new ArrayList(); + var cursor = activations.getAll(); + while (cursor.move()) { + result.add(new Activation(this, cursor.getKey())); + } + return result; + } + public Activation getRandomActivation() { return new Activation(this, activations.getKey(random.nextInt(activations.size()))); } 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 8648864c..57f86401 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 @@ -26,6 +26,7 @@ public class BestFirstStrategy implements Strategy { private DesignSpaceExplorationAdapter dseAdapter; private int maxDepth; + private int maxSolutions; private boolean backTrackIfSolution = true; private boolean onlyBetterFirst = false; @@ -54,11 +55,20 @@ public class BestFirstStrategy implements Strategy { } public BestFirstStrategy(int maxDepth) { + this(maxDepth, -1); + } + + public BestFirstStrategy(int maxDepth, int maxSolutions) { if (maxDepth < 0) { this.maxDepth = Integer.MAX_VALUE; } else { this.maxDepth = maxDepth; } + if (maxSolutions < 0) { + this.maxSolutions = Integer.MAX_VALUE; + } else { + this.maxSolutions = maxSolutions; + } } public BestFirstStrategy continueIfHardObjectivesFulfilled() { @@ -76,12 +86,15 @@ public class BestFirstStrategy implements Strategy { this.dseAdapter = designSpaceExplorationAdapter; final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); - trajectoriesToExplore = new PriorityQueue(11, + trajectoriesToExplore = new PriorityQueue<>(11, (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness)); } @Override public void explore() { + if (maxSolutions == 0) { + return; + } final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); boolean globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); @@ -90,7 +103,7 @@ public class BestFirstStrategy implements Strategy { return; } - final Fitness firstFitness = dseAdapter.calculateFitness(); + final Fitness firstFitness = dseAdapter.getFitness(); if (firstFitness.isSatisfiesHardObjectives()) { dseAdapter.newSolution(); // "First state is a solution. Terminate."); @@ -103,9 +116,16 @@ public class BestFirstStrategy implements Strategy { return; } - final List firstTrajectory = dseAdapter.getTrajectory(); - TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness); - trajectoriesToExplore.add(currentTrajectoryWithFitness); +// 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); + TrajectoryWithFitness currentTrajectoryWithFitness = null; mainLoop: while (true) { @@ -145,9 +165,13 @@ public class BestFirstStrategy implements Strategy { // "Global constraint is not satisfied."); dseAdapter.backtrack(); } else { - final Fitness nextFitness = dseAdapter.calculateFitness(); + final Fitness nextFitness = dseAdapter.getFitness(); if (nextFitness.isSatisfiesHardObjectives()) { dseAdapter.newSolution(); + var solutions = dseAdapter.getSolutions().size(); + if (solutions >= maxSolutions) { + return; + } // "Found a solution."); if (backTrackIfSolution) { dseAdapter.backtrack(); 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 1405789b..f4a0747a 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 @@ -21,6 +21,7 @@ public class DepthFirstStrategy implements Strategy { private DesignSpaceExplorationAdapter dseAdapter; private int maxDepth; + private int maxSolutions; private boolean backTrackIfSolution = true; public DepthFirstStrategy() { @@ -28,11 +29,20 @@ public class DepthFirstStrategy implements Strategy { } public DepthFirstStrategy(int maxDepth) { + this(maxDepth, -1); + } + + public DepthFirstStrategy(int maxDepth, int maxSolutions) { if (maxDepth < 0) { this.maxDepth = Integer.MAX_VALUE; } else { this.maxDepth = maxDepth; } + if (maxSolutions < 0) { + this.maxSolutions = Integer.MAX_VALUE; + } else { + this.maxSolutions = maxSolutions; + } } public DepthFirstStrategy continueIfHardObjectivesFulfilled() { @@ -47,6 +57,9 @@ public class DepthFirstStrategy implements Strategy { @Override public void explore() { + if (maxSolutions == 0) { + return; + } mainloop: while (true) { var globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); if (!globalConstraintsAreSatisfied) { @@ -61,9 +74,13 @@ public class DepthFirstStrategy implements Strategy { } } - Fitness fitness = dseAdapter.calculateFitness(); + Fitness fitness = dseAdapter.getFitness(); if (fitness.isSatisfiesHardObjectives()) { dseAdapter.newSolution(); + var solutions = dseAdapter.getSolutions().size(); + if (solutions >= maxSolutions) { + return; + } if (backTrackIfSolution) { var isSuccessfulUndo = dseAdapter.backtrack(); if (!isSuccessfulUndo) { @@ -76,7 +93,6 @@ public class DepthFirstStrategy implements Strategy { } } - var depth = dseAdapter.getDepth(); if (dseAdapter.getDepth() >= maxDepth) { var isSuccessfulUndo = dseAdapter.backtrack(); if (!isSuccessfulUndo) { -- cgit v1.2.3-54-g00ecf 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/main/java/tools') 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-54-g00ecf 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/main/java/tools') 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-54-g00ecf From 0c26310fc48b5359da11b32b04e008e64f91c10e Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Mon, 7 Aug 2023 16:23:57 +0200 Subject: Reduce complexity of Depth first search --- .../store/dse/strategy/DepthFirstStrategy.java | 89 +++++++++------------- 1 file changed, 36 insertions(+), 53 deletions(-) (limited to 'subprojects/store-dse/src/main/java/tools') 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 15529371..425e1e01 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 @@ -11,11 +11,8 @@ package tools.refinery.store.dse.strategy; import tools.refinery.store.dse.DesignSpaceExplorationAdapter; import tools.refinery.store.dse.Strategy; -import tools.refinery.store.dse.internal.Activation; import tools.refinery.store.dse.objectives.Fitness; -import java.util.Collection; - public class DepthFirstStrategy implements Strategy { private DesignSpaceExplorationAdapter dseAdapter; @@ -60,69 +57,55 @@ public class DepthFirstStrategy implements Strategy { if (maxSolutions == 0) { return; } - mainloop: while (true) { - var globalConstraintsAreSatisfied = dseAdapter.checkGlobalConstraints(); - if (!globalConstraintsAreSatisfied) { - var isSuccessfulUndo = dseAdapter.backtrack(); - if (!isSuccessfulUndo) { - // Global constraint is not satisfied and cannot backtrack. - break; - } - else { - // Global constraint is not satisfied, backtrack. - continue; - } + 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(); - var solutions = dseAdapter.getSolutions().size(); - if (solutions >= maxSolutions) { + if (backTrackIfSolution && !dseAdapter.backtrack()) { + // Found a solution but cannot backtrack. return; } - if (backTrackIfSolution) { - var isSuccessfulUndo = dseAdapter.backtrack(); - if (!isSuccessfulUndo) { - // Found a solution but cannot backtrack. - break; - } else { - // Found a solution, backtrack. - continue; - } - } } - if (dseAdapter.getDepth() >= maxDepth) { - var isSuccessfulUndo = dseAdapter.backtrack(); - if (!isSuccessfulUndo) { - // Reached max depth but cannot backtrack. - break; - } + if (!checkAndHandleDepth()) { + // Reached max depth but cannot backtrack. + return; } - Collection activations; - do { - activations = dseAdapter.getUntraversedActivations(); - 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()); + if (!backtrackToLastUntraversed()) { + return; + } dseAdapter.fireRandomActivation(); -// if (dseAdapter.isCurrentInTrajectory()) { -// if (!dseAdapter.backtrack()) { -//// TODO: throw exception -//// "The new state is present in the trajectory but cannot backtrack. Should never happen!" -// break; -// } -// else { -//// "The new state is already visited in the trajectory, backtrack." -// continue; -// } -// } } } + + 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; + } } -- cgit v1.2.3-54-g00ecf From f889dea154c57fd1831abc0db766f367665c0f60 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Tue, 8 Aug 2023 13:20:07 +0200 Subject: Improve performance of best first earch --- .../tools/refinery/store/dse/objectives/Fitness.java | 1 + .../store/dse/strategy/BestFirstStrategy.java | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'subprojects/store-dse/src/main/java/tools') 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 0bf956d2..b1dc4442 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 @@ -32,6 +32,7 @@ public class Fitness extends HashMap { public boolean equals(Object other) { if (other == null) return false; if (getClass() != other.getClass()) return false; + if (!super.equals(other)) return false; return satisfiesHardObjectives == ((Fitness) other).satisfiesHardObjectives; } 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 98af5695..0883d3d7 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 @@ -16,10 +16,7 @@ import tools.refinery.store.dse.internal.Activation; import tools.refinery.store.dse.objectives.Fitness; import tools.refinery.store.dse.objectives.ObjectiveComparatorHelper; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.PriorityQueue; +import java.util.*; public class BestFirstStrategy implements Strategy { @@ -37,6 +34,20 @@ public class BestFirstStrategy implements Strategy { public String toString() { return trajectory.toString() + fitness.toString(); } + + @Override + public int hashCode() { + return trajectory.get(trajectory.size() - 1).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TrajectoryWithFitness other) { + return Objects.equals(trajectory.get(trajectory.size() - 1), other.trajectory.get(other.trajectory.size() - 1)); +// return trajectory.equals(((TrajectoryWithFitness) obj).trajectory); + } + return false; + } } public BestFirstStrategy() { -- cgit v1.2.3-54-g00ecf 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/main/java/tools') 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-54-g00ecf From 2dae95bdf2ea309f7b8a172698d5b9c26ca5c7e5 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Tue, 8 Aug 2023 21:49:23 +0200 Subject: Improve BestFirstStrategy performance --- .../main/java/tools/refinery/store/dse/strategy/BestFirstStrategy.java | 1 - 1 file changed, 1 deletion(-) (limited to 'subprojects/store-dse/src/main/java/tools') 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 047b204a..92d878ce 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 @@ -195,7 +195,6 @@ public class BestFirstStrategy implements Strategy { } // State is fully traversed. - trajectoriesToExplore.remove(currentTrajectoryWithFitness); currentTrajectoryWithFitness = null; } -- cgit v1.2.3-54-g00ecf From 3839b0a04b8f7872093cb94122c6b1f88f5168f6 Mon Sep 17 00:00:00 2001 From: Attila Ficsor Date: Tue, 8 Aug 2023 22:20:51 +0200 Subject: Add return value to fireRandomActivation --- .../tools/refinery/store/dse/DesignSpaceExplorationAdapter.java | 2 +- .../store/dse/internal/DesignSpaceExplorationAdapterImpl.java | 9 +++------ .../tools/refinery/store/dse/strategy/DepthFirstStrategy.java | 4 +++- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'subprojects/store-dse/src/main/java/tools') 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 c45f088a..5aed5298 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 @@ -50,7 +50,7 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter { public boolean fireActivation(Activation activation); - public void fireRandomActivation(); + public boolean fireRandomActivation(); public List getTrajectory(); 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 04bba885..220f0b2d 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 @@ -252,7 +252,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration if (isNewState) { modelVisualizerAdapter.addState(newState, getFitness().values()); } - // TODO: Change to this: modelVisualizerAdapter.addTransition(previousState, newState, activation.transformationRule().getName(), activation.activation()); } @@ -260,11 +259,10 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } @Override - public void fireRandomActivation() { + public boolean fireRandomActivation() { var activations = getUntraversedActivations(); if (activations.isEmpty()) { -// TODO: throw exception - return; + return false; } int index = random.nextInt(activations.size()); var iterator = activations.iterator(); @@ -272,7 +270,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration iterator.next(); } var activationId = iterator.next(); - fireActivation(activationId); + return fireActivation(activationId); } public List getAllActivations() { @@ -284,7 +282,6 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration } public boolean isCurrentStateAlreadyTraversed() { -// TODO: check isomorphism? return !isNewState; } 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 5f7f61b8..0a0caa7e 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 @@ -67,7 +67,9 @@ public class DepthFirstStrategy implements Strategy { return; } - dseAdapter.fireRandomActivation(); + if (!dseAdapter.fireRandomActivation()) { + return; + } } } -- cgit v1.2.3-54-g00ecf