From 2809374210839fb72f455d846cd483c711b5dcb0 Mon Sep 17 00:00:00 2001 From: nagilooh Date: Tue, 5 Sep 2023 20:49:41 +0200 Subject: Add minor improvements and fixes for explorer --- .../internal/ModificationStoreAdapterImpl.java | 2 +- .../store/dse/strategy/BestFirstExplorer.java | 13 +- .../store/dse/strategy/BestFirstStoreManager.java | 4 +- .../store/dse/strategy/BestFirstWorker.java | 7 +- .../tools/refinery/store/dse/CRAExamplesTest.java | 283 +++++++++++---------- .../refinery/store/dse/tests/DummyCriterion.java | 17 ++ .../refinery/store/dse/tests/DummyObjective.java | 13 + 7 files changed, 194 insertions(+), 145 deletions(-) create mode 100644 subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyCriterion.java create mode 100644 subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyObjective.java diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java index 913cb33f..62e4227b 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java @@ -24,6 +24,6 @@ public class ModificationStoreAdapterImpl implements ModificationStoreAdapter { @Override public ModelAdapter createModelAdapter(Model model) { - return null; + return new ModificationAdapterImpl(this, model); } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java index 72bbbc55..03a7fca3 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java @@ -5,7 +5,6 @@ */ package tools.refinery.store.dse.strategy; -import tools.refinery.store.dse.transition.ObjectiveValue; import tools.refinery.store.dse.transition.VersionWithObjectiveValue; import tools.refinery.store.model.Model; @@ -32,13 +31,11 @@ public class BestFirstExplorer extends BestFirstWorker { public void explore() { VersionWithObjectiveValue lastVisited = submit().newVersion(); - mainLoop: while (shouldRun()) { + while (shouldRun()) { if (lastVisited == null) { - var restored = this.restoreToBest(); - if(restored != null) { - lastVisited = restored; - } else { + lastVisited = this.restoreToBest(); + if(lastVisited == null) { return; } } @@ -47,7 +44,7 @@ public class BestFirstExplorer extends BestFirstWorker { while(tryActivation && shouldRun()) { RandomVisitResult randomVisitResult = this.visitRandomUnvisited(random); - tryActivation &= randomVisitResult.shouldRetry(); + tryActivation = randomVisitResult.shouldRetry(); var newSubmit = randomVisitResult.submitResult(); if(newSubmit != null) { if(!newSubmit.include()) { @@ -57,7 +54,7 @@ public class BestFirstExplorer extends BestFirstWorker { int compareResult = compare(lastVisited,newVisit); if(compareResult >= 0) { lastVisited = newVisit; - continue mainLoop; + break; } } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java index d1fd7884..3795daa4 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java @@ -35,7 +35,7 @@ public class BestFirstStoreManager { objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives()); Procedure whenAllActivationsVisited = x -> objectiveStore.remove(x); activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited); - solutionStore = new SolutionStoreImpl(1); + solutionStore = new SolutionStoreImpl(10); equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) { @Override protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) { @@ -56,7 +56,7 @@ public class BestFirstStoreManager { return activationStore; } - SolutionStore getSolutionStore() { + public SolutionStore getSolutionStore() { return solutionStore; } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java index ea7fe43f..4240fdf9 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstWorker.java @@ -13,7 +13,6 @@ import tools.refinery.store.map.Version; import tools.refinery.store.model.Model; import tools.refinery.store.statecoding.StateCoderAdapter; - import java.util.Random; public class BestFirstWorker { @@ -31,6 +30,7 @@ public class BestFirstWorker { stateCoderAdapter = model.getAdapter(StateCoderAdapter.class); activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), explorationAdapter.getTransformations()); + } private VersionWithObjectiveValue last = null; @@ -48,12 +48,9 @@ public class BestFirstWorker { var res = new VersionWithObjectiveValue(version, objectiveValue); var code = stateCoderAdapter.calculateStateCode(); var accepted = explorationAdapter.checkAccept(); - boolean isNew = storeManager.getEquivalenceClassStore().submit(res, code, activationStoreWorker.calculateEmptyActivationSize(), accepted); - - last = new VersionWithObjectiveValue(version, objectiveValue); - return new SubmitResult(isNew, accepted, objectiveValue, last); + return new SubmitResult(isNew, accepted, objectiveValue, isNew ? res : null); } public void restoreToLast() { 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 36517709..f4c38b18 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/CRAExamplesTest.java @@ -5,13 +5,28 @@ */ package tools.refinery.store.dse; -import tools.refinery.store.dse.transition.TransformationRule; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import tools.refinery.store.dse.modification.ModificationAdapter; +import tools.refinery.store.dse.strategy.BestFirstStoreManager; +import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; +import tools.refinery.store.dse.tests.DummyCriterion; +import tools.refinery.store.dse.tests.DummyObjective; +import tools.refinery.store.model.ModelStore; +import tools.refinery.store.query.ModelQueryAdapter; +import tools.refinery.store.query.dnf.FunctionalQuery; import tools.refinery.store.query.dnf.Query; import tools.refinery.store.query.dnf.RelationalQuery; +import tools.refinery.store.dse.transition.TransformationRule; +import tools.refinery.store.query.term.Variable; +import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; import tools.refinery.store.query.view.AnySymbolView; import tools.refinery.store.query.view.KeyOnlyView; import tools.refinery.store.representation.Symbol; +import tools.refinery.store.statecoding.StateCoderAdapter; import tools.refinery.store.tuple.Tuple; +import tools.refinery.visualization.ModelVisualizerAdapter; +import tools.refinery.visualization.internal.FileFormat; import java.util.List; @@ -121,42 +136,42 @@ class CRAExamplesTest { }); }); -// private static final TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass", -// deleteEmptyClassPrecondition, -// (model) -> { -//// var classesInterpretation = model.getInterpretation(classes); -// var classElementInterpretation = model.getInterpretation(classElement); -// return ((Tuple activation) -> { -// // TODO: can we move dseAdapter outside? -// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); -//// var modelElement = activation.get(0); -// var classElement = activation.get(0); -// -//// classesInterpretation.put(Tuple.of(modelElement, classElement), false); -// classElementInterpretation.put(Tuple.of(classElement), false); -// dseAdapter.deleteObject(Tuple.of(classElement)); -// }); -// }); - -// private static final TransformationRule createClassRule = new TransformationRule("CreateClass", -// createClassPrecondition, -// (model) -> { -// var classElementInterpretation = model.getInterpretation(classElement); -//// var classesInterpretation = model.getInterpretation(classes); -// var encapsulatesInterpretation = model.getInterpretation(encapsulates); -// return ((Tuple activation) -> { -// // TODO: can we move dseAdapter outside? -// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); -//// var modelElement = activation.get(0); -// var feature = activation.get(0); -// -// var newClassElement = dseAdapter.createObject(); -// var newClassElementId = newClassElement.get(0); -// classElementInterpretation.put(newClassElement, true); -//// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); -// encapsulatesInterpretation.put(Tuple.of(newClassElementId, feature), true); -// }); -// }); + private static final TransformationRule deleteEmptyClassRule = new TransformationRule("DeleteEmptyClass", + deleteEmptyClassPrecondition, + (model) -> { +// var classesInterpretation = model.getInterpretation(classes); + var classElementInterpretation = model.getInterpretation(classElement); + return ((Tuple activation) -> { + // TODO: can we move modificationAdapter outside? + var modificationAdapter = model.getAdapter(ModificationAdapter.class); +// var modelElement = activation.get(0); + var classElement = activation.get(0); + +// classesInterpretation.put(Tuple.of(modelElement, classElement), false); + classElementInterpretation.put(Tuple.of(classElement), false); + modificationAdapter.deleteObject(Tuple.of(classElement)); + }); + }); + + private static final TransformationRule createClassRule = new TransformationRule("CreateClass", + createClassPrecondition, + (model) -> { + var classElementInterpretation = model.getInterpretation(classElement); +// var classesInterpretation = model.getInterpretation(classes); + var encapsulatesInterpretation = model.getInterpretation(encapsulates); + return ((Tuple activation) -> { + // TODO: can we move modificationAdapter outside? + var modificationAdapter = model.getAdapter(ModificationAdapter.class); +// var modelElement = activation.get(0); + var feature = activation.get(0); + + var newClassElement = modificationAdapter.createObject(); + var newClassElementId = newClassElement.get(0); + classElementInterpretation.put(newClassElement, true); +// classesInterpretation.put(Tuple.of(modelElement, newClassElementId), true); + encapsulatesInterpretation.put(Tuple.of(newClassElementId, feature), true); + }); + }); private static final TransformationRule moveFeatureRule = new TransformationRule("MoveFeature", moveFeaturePrecondition, @@ -172,16 +187,16 @@ class CRAExamplesTest { }); }); -// @Test + @Test // @Disabled("This test is only for debugging purposes") -// void craTest() { -// var store = ModelStore.builder() -// .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency, -// functionalDependency, name) -// .with(ViatraModelQueryAdapter.builder() -// .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition, -// deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition, -// moveFeaturePrecondition)) + void craTest() { + var store = ModelStore.builder() + .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency, + functionalDependency, name) + .with(ViatraModelQueryAdapter.builder() + .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition, + deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition, + moveFeaturePrecondition)) // .with(ModelVisualizerAdapter.builder() // .withOutputpath("test_output") // .withFormat(FileFormat.DOT) @@ -189,89 +204,99 @@ class CRAExamplesTest { // .saveStates() // .saveDesignSpace() // ) -// .with(DesignSpaceExplorationAdapter.builder() -// .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) + .with(StateCoderAdapter.builder()) + .with(ModificationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) + .objectives(new DummyObjective()) + .accept(new DummyCriterion(true)) + .exclude(new DummyCriterion(false)) // .objectives(new AlwaysSatisfiedRandomHardObjective()) -//// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled() +// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled() // .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled() -//// .goOnOnlyIfFitnessIsBetter() -// )) -// .build(); -// -// var model = store.createEmptyModel(); -// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); -//// dseAdapter.setRandom(1); -// var queryEngine = model.getAdapter(ModelQueryAdapter.class); -// -//// var modelInterpretation = model.getInterpretation(classModel); -// var nameInterpretation = model.getInterpretation(name); -// var methodInterpretation = model.getInterpretation(method); -// var attributeInterpretation = model.getInterpretation(attribute); -// var dataDependencyInterpretation = model.getInterpretation(dataDependency); -// var functionalDependencyInterpretation = model.getInterpretation(functionalDependency); -// -//// var modelElement = dseAdapter.createObject(); -// var method1 = dseAdapter.createObject(); -// var method1Id = method1.get(0); -// var method2 = dseAdapter.createObject(); -// var method2Id = method2.get(0); -// var method3 = dseAdapter.createObject(); -// var method3Id = method3.get(0); -// var method4 = dseAdapter.createObject(); -// var method4Id = method4.get(0); -// var attribute1 = dseAdapter.createObject(); -// var attribute1Id = attribute1.get(0); -// var attribute2 = dseAdapter.createObject(); -// var attribute2Id = attribute2.get(0); -// var attribute3 = dseAdapter.createObject(); -// var attribute3Id = attribute3.get(0); -// var attribute4 = dseAdapter.createObject(); -// var attribute4Id = attribute4.get(0); -// var attribute5 = dseAdapter.createObject(); -// var attribute5Id = attribute5.get(0); -// -// nameInterpretation.put(method1, "M1"); -// nameInterpretation.put(method2, "M2"); -// nameInterpretation.put(method3, "M3"); -// nameInterpretation.put(method4, "M4"); -// nameInterpretation.put(attribute1, "A1"); -// nameInterpretation.put(attribute2, "A2"); -// nameInterpretation.put(attribute3, "A3"); -// nameInterpretation.put(attribute4, "A4"); -// nameInterpretation.put(attribute5, "A5"); -// -// -// -//// modelInterpretation.put(modelElement, true); -// methodInterpretation.put(method1, true); -// methodInterpretation.put(method2, true); -// methodInterpretation.put(method3, true); -// methodInterpretation.put(method4, true); -// attributeInterpretation.put(attribute1, true); -// attributeInterpretation.put(attribute2, true); -// attributeInterpretation.put(attribute3, true); -// attributeInterpretation.put(attribute4, true); -// attributeInterpretation.put(attribute5, true); -// -// dataDependencyInterpretation.put(Tuple.of(method1Id, attribute1Id), true); -// dataDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true); -// dataDependencyInterpretation.put(Tuple.of(method2Id, attribute2Id), true); -// dataDependencyInterpretation.put(Tuple.of(method3Id, attribute3Id), true); -// dataDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true); -// dataDependencyInterpretation.put(Tuple.of(method4Id, attribute3Id), true); -// dataDependencyInterpretation.put(Tuple.of(method4Id, attribute5Id), true); -// -// functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true); -// functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute4Id), true); -// functionalDependencyInterpretation.put(Tuple.of(method2Id, attribute1Id), true); -// functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute1Id), true); -// functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true); -// functionalDependencyInterpretation.put(Tuple.of(method4Id, attribute2Id), true); -// -// queryEngine.flushChanges(); -// -// var states = dseAdapter.explore(); -// System.out.println("states size: " + states.size()); -// } -//*/ +// .goOnOnlyIfFitnessIsBetter()) + ) + .build(); + + var model = store.createEmptyModel(); +// modificationAdapter.setRandom(1); + var queryEngine = model.getAdapter(ModelQueryAdapter.class); + +// var modelInterpretation = model.getInterpretation(classModel); + var nameInterpretation = model.getInterpretation(name); + var methodInterpretation = model.getInterpretation(method); + var attributeInterpretation = model.getInterpretation(attribute); + var dataDependencyInterpretation = model.getInterpretation(dataDependency); + var functionalDependencyInterpretation = model.getInterpretation(functionalDependency); + + var modificationAdapter = model.getAdapter(ModificationAdapter.class); + +// var modelElement = modificationAdapter.createObject(); + var method1 = modificationAdapter.createObject(); + var method1Id = method1.get(0); + var method2 = modificationAdapter.createObject(); + var method2Id = method2.get(0); + var method3 = modificationAdapter.createObject(); + var method3Id = method3.get(0); + var method4 = modificationAdapter.createObject(); + var method4Id = method4.get(0); + var attribute1 = modificationAdapter.createObject(); + var attribute1Id = attribute1.get(0); + var attribute2 = modificationAdapter.createObject(); + var attribute2Id = attribute2.get(0); + var attribute3 = modificationAdapter.createObject(); + var attribute3Id = attribute3.get(0); + var attribute4 = modificationAdapter.createObject(); + var attribute4Id = attribute4.get(0); + var attribute5 = modificationAdapter.createObject(); + var attribute5Id = attribute5.get(0); + + nameInterpretation.put(method1, "M1"); + nameInterpretation.put(method2, "M2"); + nameInterpretation.put(method3, "M3"); + nameInterpretation.put(method4, "M4"); + nameInterpretation.put(attribute1, "A1"); + nameInterpretation.put(attribute2, "A2"); + nameInterpretation.put(attribute3, "A3"); + nameInterpretation.put(attribute4, "A4"); + nameInterpretation.put(attribute5, "A5"); + + + +// modelInterpretation.put(modelElement, true); + methodInterpretation.put(method1, true); + methodInterpretation.put(method2, true); + methodInterpretation.put(method3, true); + methodInterpretation.put(method4, true); + attributeInterpretation.put(attribute1, true); + attributeInterpretation.put(attribute2, true); + attributeInterpretation.put(attribute3, true); + attributeInterpretation.put(attribute4, true); + attributeInterpretation.put(attribute5, true); + + dataDependencyInterpretation.put(Tuple.of(method1Id, attribute1Id), true); + dataDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true); + dataDependencyInterpretation.put(Tuple.of(method2Id, attribute2Id), true); + dataDependencyInterpretation.put(Tuple.of(method3Id, attribute3Id), true); + dataDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true); + dataDependencyInterpretation.put(Tuple.of(method4Id, attribute3Id), true); + dataDependencyInterpretation.put(Tuple.of(method4Id, attribute5Id), true); + + functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute3Id), true); + functionalDependencyInterpretation.put(Tuple.of(method1Id, attribute4Id), true); + functionalDependencyInterpretation.put(Tuple.of(method2Id, attribute1Id), true); + functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute1Id), true); + functionalDependencyInterpretation.put(Tuple.of(method3Id, attribute4Id), true); + functionalDependencyInterpretation.put(Tuple.of(method4Id, attribute2Id), true); + + var initialVersion = model.commit(); + queryEngine.flushChanges(); + + var bestFirst = new BestFirstStoreManager(store); + bestFirst.startExploration(initialVersion); + var resultStore = bestFirst.getSolutionStore(); + System.out.println("states size: " + resultStore.getSolutions().size()); + var modelVisualizerAdapter = model.getAdapter(ModelVisualizerAdapter.class); + modelVisualizerAdapter.visualize(); + } } diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyCriterion.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyCriterion.java new file mode 100644 index 00000000..6bcbd1c3 --- /dev/null +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyCriterion.java @@ -0,0 +1,17 @@ +package tools.refinery.store.dse.tests; + +import tools.refinery.store.dse.transition.objectives.Criterion; +import tools.refinery.store.dse.transition.objectives.CriterionCalculator; +import tools.refinery.store.model.Model; + +public class DummyCriterion implements Criterion { + protected final boolean returnValue; + public DummyCriterion(boolean returnValue) { + this.returnValue = returnValue; + } + + @Override + public CriterionCalculator createCalculator(Model model) { + return () -> returnValue; + } +} diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyObjective.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyObjective.java new file mode 100644 index 00000000..77a23d62 --- /dev/null +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyObjective.java @@ -0,0 +1,13 @@ +package tools.refinery.store.dse.tests; + +import tools.refinery.store.dse.transition.objectives.Objective; +import tools.refinery.store.dse.transition.objectives.ObjectiveCalculator; +import tools.refinery.store.model.Model; + +public class DummyObjective implements Objective { + + @Override + public ObjectiveCalculator createCalculator(Model model) { + return () -> {return 0d;}; + } +} -- cgit v1.2.3-54-g00ecf