diff options
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java')
-rw-r--r-- | subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java | 131 |
1 files changed, 131 insertions, 0 deletions
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 new file mode 100644 index 00000000..1229ec15 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java | |||
@@ -0,0 +1,131 @@ | |||
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.statespace.internal; | ||
7 | |||
8 | import org.eclipse.collections.api.block.procedure.Procedure; | ||
9 | import tools.refinery.store.dse.transition.VersionWithObjectiveValue; | ||
10 | import tools.refinery.store.dse.transition.statespace.ActivationStore; | ||
11 | |||
12 | import java.util.*; | ||
13 | |||
14 | public class ActivationStoreImpl implements ActivationStore { | ||
15 | final int numberOfTransformations; | ||
16 | final Procedure<VersionWithObjectiveValue> actionWhenAllActivationVisited; | ||
17 | final Map<VersionWithObjectiveValue, List<ActivationStoreEntry>> versionToActivations; | ||
18 | |||
19 | public ActivationStoreImpl(final int numberOfTransformations, | ||
20 | Procedure<VersionWithObjectiveValue> actionWhenAllActivationVisited) { | ||
21 | this.numberOfTransformations = numberOfTransformations; | ||
22 | this.actionWhenAllActivationVisited = actionWhenAllActivationVisited; | ||
23 | versionToActivations = new HashMap<>(); | ||
24 | } | ||
25 | |||
26 | public synchronized VisitResult markNewAsVisited(VersionWithObjectiveValue to, int[] emptyEntrySizes) { | ||
27 | boolean[] successful = new boolean[]{false}; | ||
28 | var entries = versionToActivations.computeIfAbsent(to, x -> { | ||
29 | successful[0] = true; | ||
30 | List<ActivationStoreEntry> result = new ArrayList<>(emptyEntrySizes.length); | ||
31 | for(int emptyEntrySize : emptyEntrySizes) { | ||
32 | result.add(ActivationStoreListEntry.create(emptyEntrySize)); | ||
33 | } | ||
34 | return result; | ||
35 | }); | ||
36 | boolean hasMore = false; | ||
37 | for (var entry : entries) { | ||
38 | if (entry.getNumberOfUnvisitedActivations() > 0) { | ||
39 | hasMore = true; | ||
40 | break; | ||
41 | } | ||
42 | } | ||
43 | if(!hasMore) { | ||
44 | actionWhenAllActivationVisited.accept(to); | ||
45 | } | ||
46 | return new VisitResult(successful[0], hasMore, -1, -1); | ||
47 | } | ||
48 | |||
49 | public synchronized VisitResult visitActivation(VersionWithObjectiveValue from, int transformationIndex, int activationIndex) { | ||
50 | var entries = versionToActivations.get(from); | ||
51 | var entry = entries.get(transformationIndex); | ||
52 | final int unvisited = entry.getNumberOfUnvisitedActivations(); | ||
53 | |||
54 | final boolean successfulVisit = unvisited > 0; | ||
55 | final boolean hasMoreInActivation = unvisited > 1; | ||
56 | final boolean hasMore; | ||
57 | final int transformation; | ||
58 | final int activation; | ||
59 | |||
60 | if (successfulVisit) { | ||
61 | transformation = transformationIndex; | ||
62 | activation = entry.getAndAddActivationAfter(activationIndex); | ||
63 | |||
64 | } else { | ||
65 | transformation = -1; | ||
66 | activation = -1; | ||
67 | } | ||
68 | |||
69 | if(hasMoreInActivation) { | ||
70 | boolean hasMoreInOtherTransformation = false; | ||
71 | for (var e : entries) { | ||
72 | if (e != entry && e.getNumberOfVisitedActivations() > 0) { | ||
73 | hasMoreInOtherTransformation = true; | ||
74 | break; | ||
75 | } | ||
76 | } | ||
77 | hasMore = hasMoreInOtherTransformation; | ||
78 | } else { | ||
79 | hasMore = true; | ||
80 | } | ||
81 | |||
82 | if(!hasMore) { | ||
83 | actionWhenAllActivationVisited.accept(from); | ||
84 | } | ||
85 | |||
86 | return new VisitResult(false, hasMore, transformation, activation); | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public synchronized boolean hasUnmarkedActivation(VersionWithObjectiveValue version) { | ||
91 | var entries = versionToActivations.get(version); | ||
92 | boolean hasMore = false; | ||
93 | for (var entry : entries) { | ||
94 | if (entry.getNumberOfUnvisitedActivations() > 0) { | ||
95 | hasMore = true; | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | return hasMore; | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public synchronized VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random) { | ||
104 | var entries = versionToActivations.get(version); | ||
105 | |||
106 | int sum1 = 0; | ||
107 | for (var entry : entries) { | ||
108 | sum1 += entry.getNumberOfUnvisitedActivations(); | ||
109 | } | ||
110 | |||
111 | int selected = random.nextInt(sum1); | ||
112 | int sum2 = 0; | ||
113 | int transformation = 0; | ||
114 | int activation = -1; | ||
115 | for (; transformation < entries.size(); transformation++) { | ||
116 | var entry = entries.get(transformation); | ||
117 | int unvisited = entry.getNumberOfUnvisitedActivations(); | ||
118 | if (selected < sum2 + unvisited) { | ||
119 | activation = sum2 + unvisited - selected; | ||
120 | break; | ||
121 | } else { | ||
122 | sum2 += unvisited; | ||
123 | } | ||
124 | } | ||
125 | if (activation == -1) { | ||
126 | throw new IllegalArgumentException("no unvisited"); | ||
127 | } | ||
128 | |||
129 | return this.visitActivation(version, transformation, activation); | ||
130 | } | ||
131 | } | ||