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 (limited to 'subprojects') 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 From 167417e5c917732c8f6fd5292ec398a45c08ef6b Mon Sep 17 00:00:00 2001 From: nagilooh Date: Wed, 6 Sep 2023 17:52:45 +0200 Subject: Fix numerous issues with DSE --- .../tools/refinery/store/dse/strategy/BestFirstExplorer.java | 4 ++++ .../tools/refinery/store/dse/strategy/BestFirstWorker.java | 6 +++--- .../transition/statespace/internal/ActivationStoreImpl.java | 6 +++--- .../statespace/internal/ObjectivePriorityQueueImpl.java | 7 +------ .../dse/transition/statespace/internal/SolutionStoreImpl.java | 11 +++++------ 5 files changed, 16 insertions(+), 18 deletions(-) (limited to 'subprojects') 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 03a7fca3..f82d7c06 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 @@ -58,6 +58,10 @@ public class BestFirstExplorer extends BestFirstWorker { } } } + else { + lastVisited = null; + break; + } } //final ObjectiveComparatorHelper objectiveComparatorHelper = dseAdapter.getObjectiveComparatorHelper(); 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 4240fdf9..b8662d8d 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 @@ -45,12 +45,12 @@ public class BestFirstWorker { Version version = model.commit(); ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue(); - var res = new VersionWithObjectiveValue(version, objectiveValue); + last = new VersionWithObjectiveValue(version, objectiveValue); var code = stateCoderAdapter.calculateStateCode(); var accepted = explorationAdapter.checkAccept(); - boolean isNew = storeManager.getEquivalenceClassStore().submit(res, code, + boolean isNew = storeManager.getEquivalenceClassStore().submit(last, code, activationStoreWorker.calculateEmptyActivationSize(), accepted); - return new SubmitResult(isNew, accepted, objectiveValue, isNew ? res : null); + return new SubmitResult(isNew, accepted, objectiveValue, isNew ? last : null); } public void restoreToLast() { diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java index 1229ec15..559c715a 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java @@ -66,7 +66,7 @@ public class ActivationStoreImpl implements ActivationStore { activation = -1; } - if(hasMoreInActivation) { + if(!hasMoreInActivation) { boolean hasMoreInOtherTransformation = false; for (var e : entries) { if (e != entry && e.getNumberOfVisitedActivations() > 0) { @@ -83,7 +83,7 @@ public class ActivationStoreImpl implements ActivationStore { actionWhenAllActivationVisited.accept(from); } - return new VisitResult(false, hasMore, transformation, activation); + return new VisitResult(successfulVisit, hasMore, transformation, activation); } @Override @@ -116,7 +116,7 @@ public class ActivationStoreImpl implements ActivationStore { var entry = entries.get(transformation); int unvisited = entry.getNumberOfUnvisitedActivations(); if (selected < sum2 + unvisited) { - activation = sum2 + unvisited - selected; + activation = sum2 + unvisited - selected - 1; break; } else { sum2 += unvisited; diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java index 249b22da..c88a411f 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java @@ -53,12 +53,7 @@ public class ObjectivePriorityQueueImpl implements ObjectivePriorityQueue { @Override public VersionWithObjectiveValue getBest() { - var best = priorityQueue.peek(); - if (best != null) { - return best; - } else { - throw new IllegalArgumentException("The objective store is empty!"); - } + return priorityQueue.peek(); } @Override diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java index cc48864f..43548eaa 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/SolutionStoreImpl.java @@ -10,17 +10,17 @@ import tools.refinery.store.dse.transition.statespace.SolutionStore; import java.util.ArrayList; import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.PriorityQueue; + public class SolutionStoreImpl implements SolutionStore { final int maxNumberSolutions; public static final int UNLIMITED = -1; - final SortedSet solutions; + final PriorityQueue solutions; public SolutionStoreImpl(int maxNumberSolutions) { this.maxNumberSolutions = maxNumberSolutions; - solutions = new TreeSet<>(ObjectivePriorityQueueImpl.c1); + solutions = new PriorityQueue<>(ObjectivePriorityQueueImpl.c1.reversed()); } @@ -29,8 +29,7 @@ public class SolutionStoreImpl implements SolutionStore { boolean removeLast = hasEnoughSolution(); solutions.add(version); if(removeLast) { - var last = solutions.last(); - solutions.remove(last); + var last = solutions.poll(); return last != version; } else { return true; -- cgit v1.2.3-54-g00ecf From ccf1da01870d77b99e6a1a3b78e58caf9c9ed83e Mon Sep 17 00:00:00 2001 From: OszkarSemerath Date: Thu, 7 Sep 2023 01:22:52 +0200 Subject: Sample tests for the dse adapter --- .../dse/transition/objectives/QueryCriteria.java | 12 +- .../store/dse/transition/TransitionTests.java | 151 +++++++++++++++++++++ 2 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/TransitionTests.java (limited to 'subprojects') diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java index e2260cca..e6dddd53 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java @@ -12,27 +12,27 @@ import tools.refinery.store.query.ModelQueryBuilder; import tools.refinery.store.query.dnf.AnyQuery; public class QueryCriteria implements Criterion { - protected final boolean acceptIfHasMatch; + protected final boolean satisfiedIfHasMatch; protected final AnyQuery query; /** * Criteria based on the existence of matches evaluated on the model. * @param query The query evaluated on the model. - * @param acceptIfHasMatch If true, the criteria satisfied if the query has any match on the model. Otherwise, + * @param satisfiedIfHasMatch If true, the criteria satisfied if the query has any match on the model. Otherwise, * the criteria satisfied if the query has no match on the model. */ - public QueryCriteria(AnyQuery query, boolean acceptIfHasMatch) { + public QueryCriteria(AnyQuery query, boolean satisfiedIfHasMatch) { this.query = query; - this.acceptIfHasMatch = acceptIfHasMatch; + this.satisfiedIfHasMatch = satisfiedIfHasMatch; } @Override public CriterionCalculator createCalculator(Model model) { var resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(query); - if(acceptIfHasMatch) { + if(satisfiedIfHasMatch) { return () -> resultSet.size() > 0; } else { - return () -> resultSet.size() == 0; + return () -> resultSet.size() == 0; } } diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/TransitionTests.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/TransitionTests.java new file mode 100644 index 00000000..b89360cb --- /dev/null +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/transition/TransitionTests.java @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition; + +import org.junit.jupiter.api.Test; +import tools.refinery.store.dse.modification.ModificationAdapter; +import tools.refinery.store.dse.transition.objectives.QueryCriteria; +import tools.refinery.store.dse.transition.objectives.QueryObjective; +import tools.refinery.store.model.Model; +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.query.literal.CallPolarity; +import tools.refinery.store.query.literal.Literals; +import tools.refinery.store.query.term.Variable; +import tools.refinery.store.query.term.int_.IntTerms; +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 java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class TransitionBuildTests { + Symbol person = new Symbol<>("Person", 1, Boolean.class, false); + Symbol friend = new Symbol<>("friend", 2, Boolean.class, false); + AnySymbolView personView = new KeyOnlyView<>(person); + AnySymbolView friendView = new KeyOnlyView<>(friend); + + /*RelationalQuery areNotFriends = Query.of("areNotFriends", + (builder, p1, p2) -> builder.clause( + personView.call(p1), + personView.call(p2), + not(friendView.call(p1, p2))))*/ + + RelationalQuery moreThan3Friends = Query.of("moreThan3Friends", + (builder, tooMuchFriends) -> builder.clause(Integer.class, (numberOfFriends) -> List.of( + numberOfFriends.assign(friendView.count(tooMuchFriends, Variable.of())), + Literals.assume(IntTerms.less(IntTerms.constant(3), numberOfFriends)), + personView.call(tooMuchFriends) + ))); + + RelationalQuery somebodyHasNoFriend = Query.of("somebodyHasNoFriend", + (builder, lonely) -> builder.clause( + personView.call(lonely), + friendView.call(CallPolarity.NEGATIVE, lonely, Variable.of()) + )); + FunctionalQuery numberOfFriends = FunctionalQuery.of(Integer.class, + (builder, output) -> builder.clause(output.assign(friendView.count(Variable.of(), Variable.of())))); + + @Test + void acceptTest() { + Model model = getModel(); + + var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); + var query = model.getAdapter(ModelQueryAdapter.class); + var personI = model.getInterpretation(person); + var friendI = model.getInterpretation(friend); + + assertTrue(dse.checkAccept()); + personI.put(Tuple.of(1), true); + personI.put(Tuple.of(2), true); + + query.flushChanges(); + + assertFalse(dse.checkAccept()); + friendI.put(Tuple.of(1, 2), true); + friendI.put(Tuple.of(2, 1), true); + + query.flushChanges(); + + assertTrue(dse.checkAccept()); + } + + @Test + void includeTest() { + Model model = getModel(); + + var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); + var query = model.getAdapter(ModelQueryAdapter.class); + var personI = model.getInterpretation(person); + var friendI = model.getInterpretation(friend); + + assertFalse(dse.checkExclude()); + + personI.put(Tuple.of(1), true); + friendI.put(Tuple.of(1, 2), true); + friendI.put(Tuple.of(1, 3), true); + friendI.put(Tuple.of(1, 4), true); + + query.flushChanges(); + assertFalse(dse.checkExclude()); + + personI.put(Tuple.of(5), true); + friendI.put(Tuple.of(1, 5), true); + + query.flushChanges(); + assertTrue(dse.checkExclude()); + + friendI.put(Tuple.of(1, 2), false); + + query.flushChanges(); + assertFalse(dse.checkExclude()); + } + + @Test + void objectiveTest() { + Model model = getModel(); + + var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); + var query = model.getAdapter(ModelQueryAdapter.class); + var friendI = model.getInterpretation(friend); + + assertEquals(0.0, dse.getObjectiveValue().get(0), 0.01); + + friendI.put(Tuple.of(1, 2), true); + + query.flushChanges(); + assertEquals(1.0, dse.getObjectiveValue().get(0), 0.01); + + friendI.put(Tuple.of(1, 3), true); + friendI.put(Tuple.of(1, 4), true); + + query.flushChanges(); + assertEquals(3.0, dse.getObjectiveValue().get(0), 0.01); + } + + private Model getModel() { + var store = ModelStore.builder() + .symbols(person, friend) + .with(ViatraModelQueryAdapter.builder()) + .with(StateCoderAdapter.builder()) + .with(ModificationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .objective(new QueryObjective(numberOfFriends)) + .exclude(new QueryCriteria(moreThan3Friends, true)) + .accept(new QueryCriteria(somebodyHasNoFriend, false))) + .build(); + + return store.createEmptyModel(); + } +} -- cgit v1.2.3-54-g00ecf From 5bfea37c2d5af9e2dda7725a75cc073ca8283cfa Mon Sep 17 00:00:00 2001 From: OszkarSemerath Date: Thu, 7 Sep 2023 02:07:35 +0200 Subject: missing synchronized statements and flush added --- .../tools/refinery/store/dse/strategy/BestFirstWorker.java | 6 +++++- .../transition/statespace/internal/ActivationStoreImpl.java | 2 +- .../statespace/internal/FastEquivalenceClassStore.java | 5 +++-- .../statespace/internal/ObjectivePriorityQueueImpl.java | 11 +++++------ 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'subprojects') 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 b8662d8d..f28505c3 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 @@ -11,6 +11,7 @@ import tools.refinery.store.dse.transition.VersionWithObjectiveValue; import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker; import tools.refinery.store.map.Version; import tools.refinery.store.model.Model; +import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.statecoding.StateCoderAdapter; import java.util.Random; @@ -21,6 +22,7 @@ public class BestFirstWorker { final ActivationStoreWorker activationStoreWorker; final StateCoderAdapter stateCoderAdapter; final DesignSpaceExplorationAdapter explorationAdapter; + final ModelQueryAdapter queryAdapter; public BestFirstWorker(BestFirstStoreManager storeManager, Model model) { this.storeManager = storeManager; @@ -28,9 +30,9 @@ public class BestFirstWorker { explorationAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); stateCoderAdapter = model.getAdapter(StateCoderAdapter.class); + queryAdapter = model.getAdapter(ModelQueryAdapter.class); activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), explorationAdapter.getTransformations()); - } private VersionWithObjectiveValue last = null; @@ -93,7 +95,9 @@ public class BestFirstWorker { public RandomVisitResult visitRandomUnvisited(Random random) { if (!model.hasUncommittedChanges()) { + queryAdapter.flushChanges(); var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); + if (visitResult.successfulVisit()) { return new RandomVisitResult(submit(), visitResult.mayHaveMore()); } else { diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java index 559c715a..fbd5b17f 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java @@ -29,7 +29,7 @@ public class ActivationStoreImpl implements ActivationStore { successful[0] = true; List result = new ArrayList<>(emptyEntrySizes.length); for(int emptyEntrySize : emptyEntrySizes) { - result.add(ActivationStoreListEntry.create(emptyEntrySize)); + result.add(ActivationStoreEntry.create(emptyEntrySize)); } return result; }); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java index 75e117c0..faeedba5 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java @@ -15,13 +15,14 @@ public abstract class FastEquivalenceClassStore extends AbstractEquivalenceClass final IntHashSet codes; - public FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) { + protected FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) { super(stateCoderStoreAdapter); this.codes = new IntHashSet(); } @Override - protected boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, int[] emptyActivations, boolean accept) { + protected synchronized boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, + int[] emptyActivations, boolean accept) { return this.codes.add(stateCoderResult.modelCode()); } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java index c88a411f..2f3e142a 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ObjectivePriorityQueueImpl.java @@ -9,7 +9,6 @@ import tools.refinery.store.dse.transition.ObjectiveValues; import tools.refinery.store.dse.transition.VersionWithObjectiveValue; import tools.refinery.store.dse.transition.objectives.Objective; import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue; -import tools.refinery.store.map.Version; import java.util.Comparator; import java.util.List; @@ -37,27 +36,27 @@ public class ObjectivePriorityQueueImpl implements ObjectivePriorityQueue { } @Override - public void submit(VersionWithObjectiveValue versionWithObjectiveValue) { + public synchronized void submit(VersionWithObjectiveValue versionWithObjectiveValue) { priorityQueue.add(versionWithObjectiveValue); } @Override - public void remove(VersionWithObjectiveValue versionWithObjectiveValue) { + public synchronized void remove(VersionWithObjectiveValue versionWithObjectiveValue) { priorityQueue.remove(versionWithObjectiveValue); } @Override - public int getSize() { + public synchronized int getSize() { return priorityQueue.size(); } @Override - public VersionWithObjectiveValue getBest() { + public synchronized VersionWithObjectiveValue getBest() { return priorityQueue.peek(); } @Override - public VersionWithObjectiveValue getRandom(Random random) { + public synchronized VersionWithObjectiveValue getRandom(Random random) { int randomPosition = random.nextInt(getSize()); for (VersionWithObjectiveValue entry : this.priorityQueue) { if (randomPosition-- == 0) { -- cgit v1.2.3-54-g00ecf From fd1ba7c8e9877552a293ae11aee76179ac3f0d68 Mon Sep 17 00:00:00 2001 From: nagilooh Date: Thu, 7 Sep 2023 11:57:29 +0200 Subject: Add visualization to restructured DSE --- .../store/dse/strategy/BestFirstExplorer.java | 3 ++ .../store/dse/strategy/BestFirstWorker.java | 36 ++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'subprojects') 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 f82d7c06..9a03b0b8 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 @@ -36,6 +36,7 @@ public class BestFirstExplorer extends BestFirstWorker { if (lastVisited == null) { lastVisited = this.restoreToBest(); if(lastVisited == null) { + visualizerAdapter.visualize(); return; } } @@ -161,5 +162,7 @@ public class BestFirstExplorer extends BestFirstWorker { */ } // Interrupted. + visualizerAdapter.visualize(); + } } 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 b8662d8d..b1c51506 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 @@ -11,7 +11,9 @@ import tools.refinery.store.dse.transition.VersionWithObjectiveValue; import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker; import tools.refinery.store.map.Version; import tools.refinery.store.model.Model; +import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; import tools.refinery.store.statecoding.StateCoderAdapter; +import tools.refinery.visualization.ModelVisualizerAdapter; import java.util.Random; @@ -21,6 +23,9 @@ public class BestFirstWorker { final ActivationStoreWorker activationStoreWorker; final StateCoderAdapter stateCoderAdapter; final DesignSpaceExplorationAdapter explorationAdapter; + final ViatraModelQueryAdapter queryAdapter; + final ModelVisualizerAdapter visualizerAdapter; + final boolean isVisualizationEnabled; public BestFirstWorker(BestFirstStoreManager storeManager, Model model) { this.storeManager = storeManager; @@ -30,7 +35,10 @@ public class BestFirstWorker { stateCoderAdapter = model.getAdapter(StateCoderAdapter.class); activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), explorationAdapter.getTransformations()); - + visualizerAdapter = model.getAdapter(ModelVisualizerAdapter.class); + queryAdapter = model.getAdapter(ViatraModelQueryAdapter.class); + System.out.println("visualizerAdapter = " + visualizerAdapter); + isVisualizationEnabled = visualizerAdapter != null; } private VersionWithObjectiveValue last = null; @@ -44,6 +52,7 @@ public class BestFirstWorker { } Version version = model.commit(); + queryAdapter.flushChanges(); ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue(); last = new VersionWithObjectiveValue(version, objectiveValue); var code = stateCoderAdapter.calculateStateCode(); @@ -55,14 +64,22 @@ public class BestFirstWorker { public void restoreToLast() { if (explorationAdapter.getModel().hasUncommittedChanges()) { + var oldVersion = model.getState(); explorationAdapter.getModel().restore(last.version()); + if (isVisualizationEnabled) { + visualizerAdapter.addTransition(oldVersion, last.version(), ""); + } } } public VersionWithObjectiveValue restoreToBest() { var bestVersion = storeManager.getObjectiveStore().getBest(); if (bestVersion != null) { + var oldVersion = model.getState(); this.model.restore(bestVersion.version()); + if (isVisualizationEnabled) { + visualizerAdapter.addTransition(oldVersion, last.version(), ""); + } } return bestVersion; } @@ -95,7 +112,22 @@ public class BestFirstWorker { if (!model.hasUncommittedChanges()) { var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); if (visitResult.successfulVisit()) { - return new RandomVisitResult(submit(), visitResult.mayHaveMore()); + Version oldVersion = null; + if (isVisualizationEnabled) { + oldVersion = last.version(); + } + var submitResult = submit(); + if (isVisualizationEnabled) { + + Version newVersion = null; + if (submitResult.newVersion() != null) { + newVersion = submitResult.newVersion().version(); + visualizerAdapter.addState(newVersion, submitResult.newVersion().objectiveValue().toString()); + visualizerAdapter.addSolution(newVersion); + } + visualizerAdapter.addTransition(oldVersion, newVersion, ""); + } + return new RandomVisitResult(submitResult, visitResult.mayHaveMore()); } else { return new RandomVisitResult(null, visitResult.mayHaveMore()); } -- cgit v1.2.3-54-g00ecf From 741ff77e0e841cdf3fd893e1fb3d1ccccc6a83e4 Mon Sep 17 00:00:00 2001 From: nagilooh Date: Thu, 7 Sep 2023 17:34:37 +0200 Subject: fix issues with DSE framework --- .../store/dse/strategy/BestFirstExplorer.java | 2 - .../store/dse/strategy/BestFirstStoreManager.java | 22 ++- .../store/dse/strategy/BestFirstWorker.java | 64 +++---- .../statespace/EquivalenceClassStore.java | 1 + .../internal/AbstractEquivalenceClassStore.java | 7 + .../statespace/internal/ActivationStoreImpl.java | 7 +- .../statespace/internal/ActivationStoreWorker.java | 1 - .../internal/FastEquivalenceClassStore.java | 4 + .../tools/refinery/store/dse/CRAExamplesTest.java | 28 ++- .../java/tools/refinery/store/dse/DebugTest.java | 190 ++++++++++++--------- .../refinery/store/dse/tests/DummyCriterion.java | 5 + .../refinery/store/dse/tests/DummyObjective.java | 5 + .../store/dse/tests/DummyRandomCriterion.java | 25 +++ .../store/dse/tests/DummyRandomObjective.java | 23 +++ .../visualization/ModelVisualizerAdapter.java | 13 +- .../internal/ModelVisualizerAdapterImpl.java | 61 +------ .../statespace/VisualizationStore.java | 13 ++ .../internal/VisualizationStoreImpl.java | 46 +++++ 18 files changed, 310 insertions(+), 207 deletions(-) create mode 100644 subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomCriterion.java create mode 100644 subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomObjective.java create mode 100644 subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java create mode 100644 subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java (limited to 'subprojects') 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 9a03b0b8..a2b6268f 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 @@ -36,7 +36,6 @@ public class BestFirstExplorer extends BestFirstWorker { if (lastVisited == null) { lastVisited = this.restoreToBest(); if(lastVisited == null) { - visualizerAdapter.visualize(); return; } } @@ -162,7 +161,6 @@ public class BestFirstExplorer extends BestFirstWorker { */ } // Interrupted. - visualizerAdapter.visualize(); } } 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 3795daa4..0b9aae9c 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 @@ -18,14 +18,20 @@ import tools.refinery.store.dse.transition.statespace.internal.ObjectivePriority import tools.refinery.store.dse.transition.statespace.internal.SolutionStoreImpl; import tools.refinery.store.map.Version; import tools.refinery.store.model.ModelStore; +import tools.refinery.store.statecoding.StateCoderResult; import tools.refinery.store.statecoding.StateCoderStoreAdapter; +import tools.refinery.visualization.ModelVisualizerStoreAdapter; +import tools.refinery.visualization.statespace.VisualizationStore; +import tools.refinery.visualization.statespace.internal.VisualizationStoreImpl; public class BestFirstStoreManager { + ModelStore modelStore; ObjectivePriorityQueue objectiveStore; ActivationStore activationStore; SolutionStore solutionStore; EquivalenceClassStore equivalenceClassStore; + VisualizationStore visualizationStore; public BestFirstStoreManager(ModelStore modelStore) { this.modelStore = modelStore; @@ -35,17 +41,17 @@ public class BestFirstStoreManager { objectiveStore = new ObjectivePriorityQueueImpl(storeAdapter.getObjectives()); Procedure whenAllActivationsVisited = x -> objectiveStore.remove(x); activationStore = new ActivationStoreImpl(storeAdapter.getTransformations().size(), whenAllActivationsVisited); - solutionStore = new SolutionStoreImpl(10); + solutionStore = new SolutionStoreImpl(50); equivalenceClassStore = new FastEquivalenceClassStore(modelStore.getAdapter(StateCoderStoreAdapter.class)) { @Override protected void delegate(VersionWithObjectiveValue version, int[] emptyActivations, boolean accept) { - objectiveStore.submit(version); - activationStore.markNewAsVisited(version, emptyActivations); - if(accept) { - solutionStore.submit(version); - } + throw new UnsupportedOperationException("This equivalence storage is not prepared to resolve symmetries!"); } }; + visualizationStore = new VisualizationStoreImpl(); + } + public ModelStore getModelStore() { + return modelStore; } ObjectivePriorityQueue getObjectiveStore() { @@ -64,6 +70,10 @@ public class BestFirstStoreManager { return equivalenceClassStore; } + public VisualizationStore getVisualizationStore() { + return visualizationStore; + } + public void startExploration(Version initial) { BestFirstExplorer bestFirstExplorer = new BestFirstExplorer(this, modelStore.createModelForState(initial), 1); bestFirstExplorer.explore(); 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 0f1702ea..f1bec14f 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,7 @@ import tools.refinery.store.map.Version; import tools.refinery.store.model.Model; import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.statecoding.StateCoderAdapter; -import tools.refinery.visualization.ModelVisualizerAdapter; +import tools.refinery.visualization.statespace.VisualizationStore; import java.util.Random; @@ -24,7 +24,7 @@ public class BestFirstWorker { final StateCoderAdapter stateCoderAdapter; final DesignSpaceExplorationAdapter explorationAdapter; final ModelQueryAdapter queryAdapter; - final ModelVisualizerAdapter visualizerAdapter; + final VisualizationStore visualizationStore; final boolean isVisualizationEnabled; public BestFirstWorker(BestFirstStoreManager storeManager, Model model) { @@ -36,9 +36,8 @@ public class BestFirstWorker { queryAdapter = model.getAdapter(ModelQueryAdapter.class); activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), explorationAdapter.getTransformations()); - visualizerAdapter = model.getAdapter(ModelVisualizerAdapter.class); - System.out.println("visualizerAdapter = " + visualizerAdapter); - isVisualizationEnabled = visualizerAdapter != null; + visualizationStore = storeManager.getVisualizationStore(); + isVisualizationEnabled = visualizationStore != null; } private VersionWithObjectiveValue last = null; @@ -47,28 +46,41 @@ public class BestFirstWorker { public SubmitResult submit() { if (explorationAdapter.checkExclude()) { - last = null; return new SubmitResult(false, false, null, null); } - Version version = model.commit(); - queryAdapter.flushChanges(); - ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue(); - last = new VersionWithObjectiveValue(version, objectiveValue); var code = stateCoderAdapter.calculateStateCode(); - var accepted = explorationAdapter.checkAccept(); - boolean isNew = storeManager.getEquivalenceClassStore().submit(last, code, - activationStoreWorker.calculateEmptyActivationSize(), accepted); - return new SubmitResult(isNew, accepted, objectiveValue, isNew ? last : null); + + boolean isNew = storeManager.getEquivalenceClassStore().submit(code); + if (isNew) { + Version version = model.commit(); + ObjectiveValue objectiveValue = explorationAdapter.getObjectiveValue(); + var versionWithObjectiveValue = new VersionWithObjectiveValue(version, objectiveValue); + last = versionWithObjectiveValue; + var accepted = explorationAdapter.checkAccept(); + + storeManager.getObjectiveStore().submit(versionWithObjectiveValue); + storeManager.getActivationStore().markNewAsVisited(versionWithObjectiveValue, activationStoreWorker.calculateEmptyActivationSize()); + if(accepted) { + storeManager.solutionStore.submit(versionWithObjectiveValue); + } + + if (isVisualizationEnabled) { + visualizationStore.addState(last.version(), last.objectiveValue().toString()); + if (accepted) { + visualizationStore.addSolution(last.version()); + } + } + + return new SubmitResult(true, accepted, objectiveValue, last); + } + + return new SubmitResult(false, false, null, null); } public void restoreToLast() { if (explorationAdapter.getModel().hasUncommittedChanges()) { - var oldVersion = model.getState(); explorationAdapter.getModel().restore(last.version()); - if (isVisualizationEnabled) { - visualizerAdapter.addTransition(oldVersion, last.version(), ""); - } } } @@ -78,7 +90,7 @@ public class BestFirstWorker { var oldVersion = model.getState(); this.model.restore(bestVersion.version()); if (isVisualizationEnabled) { - visualizerAdapter.addTransition(oldVersion, last.version(), ""); + visualizationStore.addTransition(oldVersion, last.version(), ""); } } return bestVersion; @@ -105,7 +117,7 @@ public class BestFirstWorker { } } - record RandomVisitResult(SubmitResult submitResult, boolean shouldRetry) { + public record RandomVisitResult(SubmitResult submitResult, boolean shouldRetry) { } public RandomVisitResult visitRandomUnvisited(Random random) { @@ -119,15 +131,9 @@ public class BestFirstWorker { oldVersion = last.version(); } var submitResult = submit(); - if (isVisualizationEnabled) { - - Version newVersion = null; - if (submitResult.newVersion() != null) { - newVersion = submitResult.newVersion().version(); - visualizerAdapter.addState(newVersion, submitResult.newVersion().objectiveValue().toString()); - visualizerAdapter.addSolution(newVersion); - } - visualizerAdapter.addTransition(oldVersion, newVersion, ""); + if (isVisualizationEnabled && submitResult.newVersion() != null) { + var newVersion = submitResult.newVersion().version(); + visualizationStore.addTransition(oldVersion, newVersion, ""); } return new RandomVisitResult(submitResult, visitResult.mayHaveMore()); } else { diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java index bbe26fe5..28d1488b 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/EquivalenceClassStore.java @@ -10,6 +10,7 @@ import tools.refinery.store.statecoding.StateCoderResult; public interface EquivalenceClassStore { boolean submit(VersionWithObjectiveValue version, StateCoderResult stateCoderResult, int[] emptyActivations, boolean accept); + boolean submit(StateCoderResult stateCoderResult); boolean hasUnresolvedSymmetry(); void resolveOneSymmetry(); int getNumberOfUnresolvedSymmetries(); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java index 8466a0f3..b5087e86 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/AbstractEquivalenceClassStore.java @@ -22,6 +22,13 @@ public abstract class AbstractEquivalenceClassStore implements EquivalenceClassS protected abstract boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, int[] emptyActivations, boolean accept); + public abstract boolean tryToAdd(StateCoderResult stateCoderResult); + + @Override + public boolean submit(StateCoderResult stateCoderResult) { + return tryToAdd(stateCoderResult); + } + @Override public synchronized boolean submit(VersionWithObjectiveValue version, StateCoderResult stateCoderResult, int[] emptyActivations, boolean accept) { diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java index fbd5b17f..9186741f 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java @@ -69,7 +69,7 @@ public class ActivationStoreImpl implements ActivationStore { if(!hasMoreInActivation) { boolean hasMoreInOtherTransformation = false; for (var e : entries) { - if (e != entry && e.getNumberOfVisitedActivations() > 0) { + if (e != entry && e.getNumberOfUnvisitedActivations() > 0) { hasMoreInOtherTransformation = true; break; } @@ -108,6 +108,11 @@ public class ActivationStoreImpl implements ActivationStore { sum1 += entry.getNumberOfUnvisitedActivations(); } + if(sum1 == 0) { + this.actionWhenAllActivationVisited.accept(version); + return new VisitResult(false, false, -1, -1); + } + int selected = random.nextInt(sum1); int sum2 = 0; int transformation = 0; diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java index e05f5122..881b133c 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreWorker.java @@ -8,7 +8,6 @@ package tools.refinery.store.dse.transition.statespace.internal; import tools.refinery.store.dse.transition.Transformation; import tools.refinery.store.dse.transition.VersionWithObjectiveValue; import tools.refinery.store.dse.transition.statespace.ActivationStore; -import tools.refinery.store.map.Version; import java.util.List; import java.util.Random; diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java index faeedba5..6eba87d4 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/FastEquivalenceClassStore.java @@ -26,6 +26,10 @@ public abstract class FastEquivalenceClassStore extends AbstractEquivalenceClass return this.codes.add(stateCoderResult.modelCode()); } + public synchronized boolean tryToAdd(StateCoderResult stateCoderResult) { + return this.codes.add(stateCoderResult.modelCode()); + } + @Override public void resolveOneSymmetry() { throw new IllegalArgumentException("This equivalence storage is not prepared to resolve symmetries!"); 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 f4c38b18..831b9ff0 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 @@ -9,6 +9,8 @@ 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.tests.DummyRandomCriterion; +import tools.refinery.store.dse.tests.DummyRandomObjective; import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; import tools.refinery.store.dse.tests.DummyCriterion; import tools.refinery.store.dse.tests.DummyObjective; @@ -188,7 +190,7 @@ class CRAExamplesTest { }); @Test -// @Disabled("This test is only for debugging purposes") + @Disabled("This test is only for debugging purposes") void craTest() { var store = ModelStore.builder() .symbols(classElement, encapsulates, classes, features, attribute, method, dataDependency, @@ -197,24 +199,20 @@ class CRAExamplesTest { .queries(feature, assignFeaturePreconditionHelper, assignFeaturePrecondition, deleteEmptyClassPrecondition, createClassPreconditionHelper, createClassPrecondition, moveFeaturePrecondition)) -// .with(ModelVisualizerAdapter.builder() -// .withOutputpath("test_output") -// .withFormat(FileFormat.DOT) -// .withFormat(FileFormat.SVG) -// .saveStates() -// .saveDesignSpace() -// ) + .with(ModelVisualizerAdapter.builder() + .withOutputpath("test_output") + .withFormat(FileFormat.DOT) + .withFormat(FileFormat.SVG) + .saveStates() + .saveDesignSpace() + ) .with(StateCoderAdapter.builder()) .with(ModificationAdapter.builder()) .with(DesignSpaceExplorationAdapter.builder() .transformations(assignFeatureRule, deleteEmptyClassRule, createClassRule, moveFeatureRule) - .objectives(new DummyObjective()) - .accept(new DummyCriterion(true)) + .objectives(new DummyRandomObjective()) + .accept(new DummyRandomCriterion()) .exclude(new DummyCriterion(false)) -// .objectives(new AlwaysSatisfiedRandomHardObjective()) -// .strategy(new DepthFirstStrategy().withDepthLimit(3).continueIfHardObjectivesFulfilled() -// .strategy(new BestFirstStrategy().withDepthLimit(6).continueIfHardObjectivesFulfilled() -// .goOnOnlyIfFitnessIsBetter()) ) .build(); @@ -296,7 +294,5 @@ class CRAExamplesTest { 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/DebugTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java index 1d757a5f..87c3892a 100644 --- a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/DebugTest.java @@ -5,9 +5,27 @@ */ package tools.refinery.store.dse; +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.tests.DummyCriterion; +import tools.refinery.store.dse.tests.DummyObjective; +import tools.refinery.store.dse.tests.DummyRandomCriterion; +import tools.refinery.store.dse.tests.DummyRandomObjective; +import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; +import tools.refinery.store.dse.transition.TransformationRule; +import tools.refinery.store.model.ModelStore; +import tools.refinery.store.query.ModelQueryAdapter; +import tools.refinery.store.query.dnf.Query; +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; class DebugTest { private static final Symbol classModel = Symbol.of("ClassModel", 1); @@ -29,88 +47,92 @@ class DebugTest { private static final AnySymbolView classesView = new KeyOnlyView<>(classes); -// @Test -// @Disabled("This test is only for debugging purposes") -// void BFSTest() { -// 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, feature, isEncapsulatedBy, encapsulates, classes, features) -// .with(ViatraModelQueryAdapter.builder() -// .queries(createClassPrecondition, createFeaturePrecondition)) -// .with(ModelVisualizerAdapter.builder() -// .withOutputpath("test_output") -// .withFormat(FileFormat.DOT) -// .withFormat(FileFormat.SVG) -// .saveStates() -// .saveDesignSpace() -// ) -// .with(DesignSpaceExplorationAdapter.builder() -// .transformations(createClassRule, createFeatureRule) -// .objectives(new AlwaysSatisfiedRandomHardObjective()) -// .strategy(new DepthFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() -//// .strategy(new BestFirstStrategy().withDepthLimit(4).continueIfHardObjectivesFulfilled() -//// .goOnOnlyIfFitnessIsBetter() -// )) -// .build(); -// -// var model = store.createEmptyModel(); -// var dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); -//// dseAdapter.setRandom(1); -// var queryEngine = model.getAdapter(ModelQueryAdapter.class); -// -// var modelElementInterpretation = model.getInterpretation(classModel); -// var classElementInterpretation = model.getInterpretation(classElement); -// var modelElement = dseAdapter.createObject(); -// modelElementInterpretation.put(modelElement, true); -// classElementInterpretation.put(modelElement, true); -// queryEngine.flushChanges(); -// -// -// var states = dseAdapter.explore(); -// System.out.println("states size: " + states.size()); -// -// } + @Test + @Disabled("This test is only for debugging purposes") + void BFSTest() { + 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(ModificationAdapter.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(ModificationAdapter.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, feature, isEncapsulatedBy, encapsulates, classes, features) + .with(ViatraModelQueryAdapter.builder() + .queries(createClassPrecondition, createFeaturePrecondition)) + .with(ModelVisualizerAdapter.builder() + .withOutputpath("test_output") + .withFormat(FileFormat.DOT) + .withFormat(FileFormat.SVG) + .saveStates() + .saveDesignSpace() + ) + .with(StateCoderAdapter.builder()) + .with(ModificationAdapter.builder()) + .with(DesignSpaceExplorationAdapter.builder() + .transformations(createClassRule, createFeatureRule) + .objectives(new DummyRandomObjective()) + .accept(new DummyRandomCriterion()) + .exclude(new DummyRandomCriterion()) + ) + .build(); + + var model = store.createEmptyModel(); + var dseAdapter = model.getAdapter(ModificationAdapter.class); +// dseAdapter.setRandom(1); + var queryEngine = model.getAdapter(ModelQueryAdapter.class); + + var modelElementInterpretation = model.getInterpretation(classModel); + var classElementInterpretation = model.getInterpretation(classElement); + var modelElement = dseAdapter.createObject(); + modelElementInterpretation.put(modelElement, true); + classElementInterpretation.put(modelElement, 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()); + + } } 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 index 6bcbd1c3..2d5a0f36 100644 --- 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 @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ package tools.refinery.store.dse.tests; import tools.refinery.store.dse.transition.objectives.Criterion; 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 index 77a23d62..f5d281aa 100644 --- 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 @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ package tools.refinery.store.dse.tests; import tools.refinery.store.dse.transition.objectives.Objective; diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomCriterion.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomCriterion.java new file mode 100644 index 00000000..71fd4403 --- /dev/null +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomCriterion.java @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +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; + +import java.util.Random; + +public class DummyRandomCriterion implements Criterion { + + @SuppressWarnings("squid:S2245") + private static final Random random = new Random(9856654); + public DummyRandomCriterion() { + } + + @Override + public CriterionCalculator createCalculator(Model model) { + return random::nextBoolean; + } +} diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomObjective.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomObjective.java new file mode 100644 index 00000000..219e74c6 --- /dev/null +++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/tests/DummyRandomObjective.java @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +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; + +import java.util.Random; + +public class DummyRandomObjective implements Objective { + + @SuppressWarnings("squid:S2245") + private static final Random random = new Random(9856654); + + @Override + public ObjectiveCalculator createCalculator(Model model) { + return random::nextDouble; + } +} 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 ae87d8ac..ad80bbc6 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java @@ -9,6 +9,7 @@ import tools.refinery.store.adapter.ModelAdapter; import tools.refinery.store.map.Version; import tools.refinery.store.tuple.Tuple; import tools.refinery.visualization.internal.ModelVisualizerBuilderImpl; +import tools.refinery.visualization.statespace.VisualizationStore; import java.util.Collection; @@ -18,15 +19,5 @@ public interface ModelVisualizerAdapter extends ModelAdapter { static ModelVisualizerBuilder builder() { return new ModelVisualizerBuilderImpl(); } - - 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 void visualize(); - + void visualize(VisualizationStore visualizationStore); } 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 531969b4..031b2e6b 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 @@ -13,6 +13,7 @@ import tools.refinery.store.representation.TruthValue; import tools.refinery.store.tuple.Tuple; import tools.refinery.visualization.ModelVisualizerAdapter; import tools.refinery.visualization.ModelVisualizerStoreAdapter; +import tools.refinery.visualization.statespace.VisualizationStore; import java.io.*; import java.util.*; @@ -281,62 +282,6 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { return true; } - @Override - public void addTransition(Version from, Version to, String action) { - designSpaceBuilder.append(states.get(from)).append(" -> ").append(states.get(to)) - .append(" [label=\"").append(transitionCounter++).append(": ").append(action).append("\"]\n"); - } - - @Override - public void addTransition(Version from, Version to, String action, Tuple activation) { - designSpaceBuilder.append(states.get(from)).append(" -> ").append(states.get(to)) - .append(" [label=\"").append(transitionCounter++).append(": ").append(action).append(" / "); - - - for (int i = 0; i < activation.getSize(); i++) { - designSpaceBuilder.append(activation.get(i)); - if (i < activation.getSize() - 1) { - designSpaceBuilder.append(", "); - } - } - designSpaceBuilder.append("\"]\n"); - } - - @Override - public void addState(Version state) { - if (states.containsKey(state)) { - return; - } - states.put(state, numberOfStates++); - designSpaceBuilder.append(states.get(state)).append(" [URL=\"./").append(states.get(state)).append(".svg\"]\n"); - } - - @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(" ("); - designSpaceBuilder.append(label); - designSpaceBuilder.append(")\"\n").append("URL=\"./").append(states.get(state)).append(".svg\"]\n"); - } - - @Override - public void addSolution(Version state) { - addState(state); - designSpaceBuilder.append(states.get(state)).append(" [shape = doublecircle]\n"); - } - private String buildDesignSpaceDot() { designSpaceBuilder.append("}"); return designSpaceBuilder.toString(); @@ -381,7 +326,9 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter { } @Override - public void visualize() { + public void visualize(VisualizationStore visualizationStore) { + this.designSpaceBuilder.append(visualizationStore.getDesignSpaceStringBuilder()); + this.states.putAll(visualizationStore.getStates()); renderDesignSpace(outputPath, formats); } } diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java new file mode 100644 index 00000000..0bf9d4a5 --- /dev/null +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java @@ -0,0 +1,13 @@ +package tools.refinery.visualization.statespace; + +import tools.refinery.store.map.Version; + +import java.util.Map; + +public interface VisualizationStore { + void addState(Version state, String label); + void addSolution(Version state); + void addTransition(Version from, Version to, String label); + StringBuilder getDesignSpaceStringBuilder(); + Map getStates(); +} diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java new file mode 100644 index 00000000..13794667 --- /dev/null +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java @@ -0,0 +1,46 @@ +package tools.refinery.visualization.statespace.internal; + +import tools.refinery.store.map.Version; +import tools.refinery.visualization.statespace.VisualizationStore; + +import java.util.HashMap; +import java.util.Map; + +public class VisualizationStoreImpl implements VisualizationStore { + + private final Map states = new HashMap<>(); + private int transitionCounter = 0; + private Integer numberOfStates = 0; + private final StringBuilder designSpaceBuilder = new StringBuilder(); + + @Override + public synchronized 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(" ("); + designSpaceBuilder.append(label); + designSpaceBuilder.append(")\"\n").append("URL=\"./").append(states.get(state)).append(".svg\"]\n"); + } + + @Override + public synchronized void addSolution(Version state) { + designSpaceBuilder.append(states.get(state)).append(" [peripheries = 2]\n"); + } + + @Override + public synchronized void addTransition(Version from, Version to, String label) { + designSpaceBuilder.append(states.get(from)).append(" -> ").append(states.get(to)) + .append(" [label=\"").append(transitionCounter++).append(": ").append(label).append("\"]\n"); + } + + public synchronized StringBuilder getDesignSpaceStringBuilder() { + return designSpaceBuilder; + } + + @Override + public Map getStates() { + return states; + } +} -- cgit v1.2.3-54-g00ecf From f13d204b7fba1705e92e5c17be6d9780678fc543 Mon Sep 17 00:00:00 2001 From: nagilooh Date: Thu, 7 Sep 2023 18:10:15 +0200 Subject: Add missing copyright headers --- .../tools/refinery/visualization/statespace/VisualizationStore.java | 5 +++++ .../visualization/statespace/internal/VisualizationStoreImpl.java | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'subprojects') diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java index 0bf9d4a5..414ef737 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/VisualizationStore.java @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ package tools.refinery.visualization.statespace; import tools.refinery.store.map.Version; diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java index 13794667..08a69cb4 100644 --- a/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java +++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/statespace/internal/VisualizationStoreImpl.java @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ package tools.refinery.visualization.statespace.internal; import tools.refinery.store.map.Version; -- cgit v1.2.3-54-g00ecf