diff options
author | 2023-09-07 11:59:23 +0200 | |
---|---|---|
committer | 2023-09-07 12:01:48 +0200 | |
commit | c70eedced3417e82f3e6092e8cf4aa665b085545 (patch) | |
tree | 361cf9078adc5e6abf814012508dd7d7d96d0d7e /subprojects/store-dse/src | |
parent | Add visualization to restructured DSE (diff) | |
parent | missing synchronized statements and flush added (diff) | |
download | refinery-c70eedced3417e82f3e6092e8cf4aa665b085545.tar.gz refinery-c70eedced3417e82f3e6092e8cf4aa665b085545.tar.zst refinery-c70eedced3417e82f3e6092e8cf4aa665b085545.zip |
Merge remote-tracking branch 'oszkar/datastructure' into datastructure
Diffstat (limited to 'subprojects/store-dse/src')
6 files changed, 171 insertions, 18 deletions
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 b1c51506..0f1702ea 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,7 @@ import tools.refinery.store.dse.transition.VersionWithObjectiveValue; | |||
11 | import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker; | 11 | import tools.refinery.store.dse.transition.statespace.internal.ActivationStoreWorker; |
12 | import tools.refinery.store.map.Version; | 12 | import tools.refinery.store.map.Version; |
13 | import tools.refinery.store.model.Model; | 13 | import tools.refinery.store.model.Model; |
14 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; | 14 | import tools.refinery.store.query.ModelQueryAdapter; |
15 | import tools.refinery.store.statecoding.StateCoderAdapter; | 15 | import tools.refinery.store.statecoding.StateCoderAdapter; |
16 | import tools.refinery.visualization.ModelVisualizerAdapter; | 16 | import tools.refinery.visualization.ModelVisualizerAdapter; |
17 | 17 | ||
@@ -23,7 +23,7 @@ public class BestFirstWorker { | |||
23 | final ActivationStoreWorker activationStoreWorker; | 23 | final ActivationStoreWorker activationStoreWorker; |
24 | final StateCoderAdapter stateCoderAdapter; | 24 | final StateCoderAdapter stateCoderAdapter; |
25 | final DesignSpaceExplorationAdapter explorationAdapter; | 25 | final DesignSpaceExplorationAdapter explorationAdapter; |
26 | final ViatraModelQueryAdapter queryAdapter; | 26 | final ModelQueryAdapter queryAdapter; |
27 | final ModelVisualizerAdapter visualizerAdapter; | 27 | final ModelVisualizerAdapter visualizerAdapter; |
28 | final boolean isVisualizationEnabled; | 28 | final boolean isVisualizationEnabled; |
29 | 29 | ||
@@ -33,10 +33,10 @@ public class BestFirstWorker { | |||
33 | 33 | ||
34 | explorationAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); | 34 | explorationAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class); |
35 | stateCoderAdapter = model.getAdapter(StateCoderAdapter.class); | 35 | stateCoderAdapter = model.getAdapter(StateCoderAdapter.class); |
36 | queryAdapter = model.getAdapter(ModelQueryAdapter.class); | ||
36 | activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), | 37 | activationStoreWorker = new ActivationStoreWorker(storeManager.getActivationStore(), |
37 | explorationAdapter.getTransformations()); | 38 | explorationAdapter.getTransformations()); |
38 | visualizerAdapter = model.getAdapter(ModelVisualizerAdapter.class); | 39 | visualizerAdapter = model.getAdapter(ModelVisualizerAdapter.class); |
39 | queryAdapter = model.getAdapter(ViatraModelQueryAdapter.class); | ||
40 | System.out.println("visualizerAdapter = " + visualizerAdapter); | 40 | System.out.println("visualizerAdapter = " + visualizerAdapter); |
41 | isVisualizationEnabled = visualizerAdapter != null; | 41 | isVisualizationEnabled = visualizerAdapter != null; |
42 | } | 42 | } |
@@ -110,7 +110,9 @@ public class BestFirstWorker { | |||
110 | 110 | ||
111 | public RandomVisitResult visitRandomUnvisited(Random random) { | 111 | public RandomVisitResult visitRandomUnvisited(Random random) { |
112 | if (!model.hasUncommittedChanges()) { | 112 | if (!model.hasUncommittedChanges()) { |
113 | queryAdapter.flushChanges(); | ||
113 | var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); | 114 | var visitResult = activationStoreWorker.fireRandomActivation(this.last, random); |
115 | |||
114 | if (visitResult.successfulVisit()) { | 116 | if (visitResult.successfulVisit()) { |
115 | Version oldVersion = null; | 117 | Version oldVersion = null; |
116 | if (isVisualizationEnabled) { | 118 | if (isVisualizationEnabled) { |
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; | |||
12 | import tools.refinery.store.query.dnf.AnyQuery; | 12 | import tools.refinery.store.query.dnf.AnyQuery; |
13 | 13 | ||
14 | public class QueryCriteria implements Criterion { | 14 | public class QueryCriteria implements Criterion { |
15 | protected final boolean acceptIfHasMatch; | 15 | protected final boolean satisfiedIfHasMatch; |
16 | protected final AnyQuery query; | 16 | protected final AnyQuery query; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * Criteria based on the existence of matches evaluated on the model. | 19 | * Criteria based on the existence of matches evaluated on the model. |
20 | * @param query The query evaluated on the model. | 20 | * @param query The query evaluated on the model. |
21 | * @param acceptIfHasMatch If true, the criteria satisfied if the query has any match on the model. Otherwise, | 21 | * @param satisfiedIfHasMatch If true, the criteria satisfied if the query has any match on the model. Otherwise, |
22 | * the criteria satisfied if the query has no match on the model. | 22 | * the criteria satisfied if the query has no match on the model. |
23 | */ | 23 | */ |
24 | public QueryCriteria(AnyQuery query, boolean acceptIfHasMatch) { | 24 | public QueryCriteria(AnyQuery query, boolean satisfiedIfHasMatch) { |
25 | this.query = query; | 25 | this.query = query; |
26 | this.acceptIfHasMatch = acceptIfHasMatch; | 26 | this.satisfiedIfHasMatch = satisfiedIfHasMatch; |
27 | } | 27 | } |
28 | 28 | ||
29 | @Override | 29 | @Override |
30 | public CriterionCalculator createCalculator(Model model) { | 30 | public CriterionCalculator createCalculator(Model model) { |
31 | var resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(query); | 31 | var resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(query); |
32 | if(acceptIfHasMatch) { | 32 | if(satisfiedIfHasMatch) { |
33 | return () -> resultSet.size() > 0; | 33 | return () -> resultSet.size() > 0; |
34 | } else { | 34 | } else { |
35 | return () -> resultSet.size() == 0; | 35 | return () -> resultSet.size() == 0; |
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
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 { | |||
29 | successful[0] = true; | 29 | successful[0] = true; |
30 | List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length); | 30 | List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length); |
31 | for(int emptyEntrySize : emptyEntrySizes) { | 31 | for(int emptyEntrySize : emptyEntrySizes) { |
32 | result.add(ActivationStoreListEntry.create(emptyEntrySize)); | 32 | result.add(ActivationStoreEntry.create(emptyEntrySize)); |
33 | } | 33 | } |
34 | return result; | 34 | return result; |
35 | }); | 35 | }); |
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 | |||
15 | 15 | ||
16 | final IntHashSet codes; | 16 | final IntHashSet codes; |
17 | 17 | ||
18 | public FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) { | 18 | protected FastEquivalenceClassStore(StateCoderStoreAdapter stateCoderStoreAdapter) { |
19 | super(stateCoderStoreAdapter); | 19 | super(stateCoderStoreAdapter); |
20 | this.codes = new IntHashSet(); | 20 | this.codes = new IntHashSet(); |
21 | } | 21 | } |
22 | 22 | ||
23 | @Override | 23 | @Override |
24 | protected boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, int[] emptyActivations, boolean accept) { | 24 | protected synchronized boolean tryToAdd(StateCoderResult stateCoderResult, VersionWithObjectiveValue newVersion, |
25 | int[] emptyActivations, boolean accept) { | ||
25 | return this.codes.add(stateCoderResult.modelCode()); | 26 | return this.codes.add(stateCoderResult.modelCode()); |
26 | } | 27 | } |
27 | 28 | ||
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; | |||
9 | import tools.refinery.store.dse.transition.VersionWithObjectiveValue; | 9 | import tools.refinery.store.dse.transition.VersionWithObjectiveValue; |
10 | import tools.refinery.store.dse.transition.objectives.Objective; | 10 | import tools.refinery.store.dse.transition.objectives.Objective; |
11 | import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue; | 11 | import tools.refinery.store.dse.transition.statespace.ObjectivePriorityQueue; |
12 | import tools.refinery.store.map.Version; | ||
13 | 12 | ||
14 | import java.util.Comparator; | 13 | import java.util.Comparator; |
15 | import java.util.List; | 14 | import java.util.List; |
@@ -37,27 +36,27 @@ public class ObjectivePriorityQueueImpl implements ObjectivePriorityQueue { | |||
37 | } | 36 | } |
38 | 37 | ||
39 | @Override | 38 | @Override |
40 | public void submit(VersionWithObjectiveValue versionWithObjectiveValue) { | 39 | public synchronized void submit(VersionWithObjectiveValue versionWithObjectiveValue) { |
41 | priorityQueue.add(versionWithObjectiveValue); | 40 | priorityQueue.add(versionWithObjectiveValue); |
42 | } | 41 | } |
43 | 42 | ||
44 | @Override | 43 | @Override |
45 | public void remove(VersionWithObjectiveValue versionWithObjectiveValue) { | 44 | public synchronized void remove(VersionWithObjectiveValue versionWithObjectiveValue) { |
46 | priorityQueue.remove(versionWithObjectiveValue); | 45 | priorityQueue.remove(versionWithObjectiveValue); |
47 | } | 46 | } |
48 | 47 | ||
49 | @Override | 48 | @Override |
50 | public int getSize() { | 49 | public synchronized int getSize() { |
51 | return priorityQueue.size(); | 50 | return priorityQueue.size(); |
52 | } | 51 | } |
53 | 52 | ||
54 | @Override | 53 | @Override |
55 | public VersionWithObjectiveValue getBest() { | 54 | public synchronized VersionWithObjectiveValue getBest() { |
56 | return priorityQueue.peek(); | 55 | return priorityQueue.peek(); |
57 | } | 56 | } |
58 | 57 | ||
59 | @Override | 58 | @Override |
60 | public VersionWithObjectiveValue getRandom(Random random) { | 59 | public synchronized VersionWithObjectiveValue getRandom(Random random) { |
61 | int randomPosition = random.nextInt(getSize()); | 60 | int randomPosition = random.nextInt(getSize()); |
62 | for (VersionWithObjectiveValue entry : this.priorityQueue) { | 61 | for (VersionWithObjectiveValue entry : this.priorityQueue) { |
63 | if (randomPosition-- == 0) { | 62 | if (randomPosition-- == 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 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.dse.transition; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.dse.modification.ModificationAdapter; | ||
10 | import tools.refinery.store.dse.transition.objectives.QueryCriteria; | ||
11 | import tools.refinery.store.dse.transition.objectives.QueryObjective; | ||
12 | import tools.refinery.store.model.Model; | ||
13 | import tools.refinery.store.model.ModelStore; | ||
14 | import tools.refinery.store.query.ModelQueryAdapter; | ||
15 | import tools.refinery.store.query.dnf.FunctionalQuery; | ||
16 | import tools.refinery.store.query.dnf.Query; | ||
17 | import tools.refinery.store.query.dnf.RelationalQuery; | ||
18 | import tools.refinery.store.query.literal.CallPolarity; | ||
19 | import tools.refinery.store.query.literal.Literals; | ||
20 | import tools.refinery.store.query.term.Variable; | ||
21 | import tools.refinery.store.query.term.int_.IntTerms; | ||
22 | import tools.refinery.store.query.viatra.ViatraModelQueryAdapter; | ||
23 | import tools.refinery.store.query.view.AnySymbolView; | ||
24 | import tools.refinery.store.query.view.KeyOnlyView; | ||
25 | import tools.refinery.store.representation.Symbol; | ||
26 | import tools.refinery.store.statecoding.StateCoderAdapter; | ||
27 | import tools.refinery.store.tuple.Tuple; | ||
28 | |||
29 | import java.util.List; | ||
30 | |||
31 | import static org.junit.jupiter.api.Assertions.*; | ||
32 | |||
33 | class TransitionBuildTests { | ||
34 | Symbol<Boolean> person = new Symbol<>("Person", 1, Boolean.class, false); | ||
35 | Symbol<Boolean> friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
36 | AnySymbolView personView = new KeyOnlyView<>(person); | ||
37 | AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
38 | |||
39 | /*RelationalQuery areNotFriends = Query.of("areNotFriends", | ||
40 | (builder, p1, p2) -> builder.clause( | ||
41 | personView.call(p1), | ||
42 | personView.call(p2), | ||
43 | not(friendView.call(p1, p2))))*/ | ||
44 | |||
45 | RelationalQuery moreThan3Friends = Query.of("moreThan3Friends", | ||
46 | (builder, tooMuchFriends) -> builder.clause(Integer.class, (numberOfFriends) -> List.of( | ||
47 | numberOfFriends.assign(friendView.count(tooMuchFriends, Variable.of())), | ||
48 | Literals.assume(IntTerms.less(IntTerms.constant(3), numberOfFriends)), | ||
49 | personView.call(tooMuchFriends) | ||
50 | ))); | ||
51 | |||
52 | RelationalQuery somebodyHasNoFriend = Query.of("somebodyHasNoFriend", | ||
53 | (builder, lonely) -> builder.clause( | ||
54 | personView.call(lonely), | ||
55 | friendView.call(CallPolarity.NEGATIVE, lonely, Variable.of()) | ||
56 | )); | ||
57 | FunctionalQuery<Integer> numberOfFriends = FunctionalQuery.of(Integer.class, | ||
58 | (builder, output) -> builder.clause(output.assign(friendView.count(Variable.of(), Variable.of())))); | ||
59 | |||
60 | @Test | ||
61 | void acceptTest() { | ||
62 | Model model = getModel(); | ||
63 | |||
64 | var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
65 | var query = model.getAdapter(ModelQueryAdapter.class); | ||
66 | var personI = model.getInterpretation(person); | ||
67 | var friendI = model.getInterpretation(friend); | ||
68 | |||
69 | assertTrue(dse.checkAccept()); | ||
70 | personI.put(Tuple.of(1), true); | ||
71 | personI.put(Tuple.of(2), true); | ||
72 | |||
73 | query.flushChanges(); | ||
74 | |||
75 | assertFalse(dse.checkAccept()); | ||
76 | friendI.put(Tuple.of(1, 2), true); | ||
77 | friendI.put(Tuple.of(2, 1), true); | ||
78 | |||
79 | query.flushChanges(); | ||
80 | |||
81 | assertTrue(dse.checkAccept()); | ||
82 | } | ||
83 | |||
84 | @Test | ||
85 | void includeTest() { | ||
86 | Model model = getModel(); | ||
87 | |||
88 | var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
89 | var query = model.getAdapter(ModelQueryAdapter.class); | ||
90 | var personI = model.getInterpretation(person); | ||
91 | var friendI = model.getInterpretation(friend); | ||
92 | |||
93 | assertFalse(dse.checkExclude()); | ||
94 | |||
95 | personI.put(Tuple.of(1), true); | ||
96 | friendI.put(Tuple.of(1, 2), true); | ||
97 | friendI.put(Tuple.of(1, 3), true); | ||
98 | friendI.put(Tuple.of(1, 4), true); | ||
99 | |||
100 | query.flushChanges(); | ||
101 | assertFalse(dse.checkExclude()); | ||
102 | |||
103 | personI.put(Tuple.of(5), true); | ||
104 | friendI.put(Tuple.of(1, 5), true); | ||
105 | |||
106 | query.flushChanges(); | ||
107 | assertTrue(dse.checkExclude()); | ||
108 | |||
109 | friendI.put(Tuple.of(1, 2), false); | ||
110 | |||
111 | query.flushChanges(); | ||
112 | assertFalse(dse.checkExclude()); | ||
113 | } | ||
114 | |||
115 | @Test | ||
116 | void objectiveTest() { | ||
117 | Model model = getModel(); | ||
118 | |||
119 | var dse = model.getAdapter(DesignSpaceExplorationAdapter.class); | ||
120 | var query = model.getAdapter(ModelQueryAdapter.class); | ||
121 | var friendI = model.getInterpretation(friend); | ||
122 | |||
123 | assertEquals(0.0, dse.getObjectiveValue().get(0), 0.01); | ||
124 | |||
125 | friendI.put(Tuple.of(1, 2), true); | ||
126 | |||
127 | query.flushChanges(); | ||
128 | assertEquals(1.0, dse.getObjectiveValue().get(0), 0.01); | ||
129 | |||
130 | friendI.put(Tuple.of(1, 3), true); | ||
131 | friendI.put(Tuple.of(1, 4), true); | ||
132 | |||
133 | query.flushChanges(); | ||
134 | assertEquals(3.0, dse.getObjectiveValue().get(0), 0.01); | ||
135 | } | ||
136 | |||
137 | private Model getModel() { | ||
138 | var store = ModelStore.builder() | ||
139 | .symbols(person, friend) | ||
140 | .with(ViatraModelQueryAdapter.builder()) | ||
141 | .with(StateCoderAdapter.builder()) | ||
142 | .with(ModificationAdapter.builder()) | ||
143 | .with(DesignSpaceExplorationAdapter.builder() | ||
144 | .objective(new QueryObjective(numberOfFriends)) | ||
145 | .exclude(new QueryCriteria(moreThan3Friends, true)) | ||
146 | .accept(new QueryCriteria(somebodyHasNoFriend, false))) | ||
147 | .build(); | ||
148 | |||
149 | return store.createEmptyModel(); | ||
150 | } | ||
151 | } | ||