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 | 138 |
1 files changed, 138 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..82f89db7 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java | |||
@@ -0,0 +1,138 @@ | |||
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 tools.refinery.store.dse.transition.VersionWithObjectiveValue; | ||
9 | import tools.refinery.store.dse.transition.statespace.ActivationStore; | ||
10 | |||
11 | import java.util.*; | ||
12 | import java.util.function.Consumer; | ||
13 | |||
14 | public class ActivationStoreImpl implements ActivationStore { | ||
15 | final int numberOfTransformations; | ||
16 | final Consumer<VersionWithObjectiveValue> actionWhenAllActivationVisited; | ||
17 | final Map<VersionWithObjectiveValue, List<ActivationStoreEntry>> versionToActivations; | ||
18 | |||
19 | public ActivationStoreImpl(final int numberOfTransformations, | ||
20 | Consumer<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(ActivationStoreEntry.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, | ||
50 | int activationIndex) { | ||
51 | var entries = versionToActivations.get(from); | ||
52 | var entry = entries.get(transformationIndex); | ||
53 | final int unvisited = entry.getNumberOfUnvisitedActivations(); | ||
54 | |||
55 | final boolean successfulVisit = unvisited > 0; | ||
56 | final boolean hasMoreInActivation = unvisited > 1; | ||
57 | final boolean hasMore; | ||
58 | final int transformation; | ||
59 | final int activation; | ||
60 | |||
61 | if (successfulVisit) { | ||
62 | transformation = transformationIndex; | ||
63 | activation = entry.getAndAddActivationAfter(activationIndex); | ||
64 | |||
65 | } else { | ||
66 | transformation = -1; | ||
67 | activation = -1; | ||
68 | } | ||
69 | |||
70 | if (!hasMoreInActivation) { | ||
71 | boolean hasMoreInOtherTransformation = false; | ||
72 | for (var e : entries) { | ||
73 | if (e != entry && e.getNumberOfUnvisitedActivations() > 0) { | ||
74 | hasMoreInOtherTransformation = true; | ||
75 | break; | ||
76 | } | ||
77 | } | ||
78 | hasMore = hasMoreInOtherTransformation; | ||
79 | } else { | ||
80 | hasMore = true; | ||
81 | } | ||
82 | |||
83 | if (!hasMore) { | ||
84 | actionWhenAllActivationVisited.accept(from); | ||
85 | } | ||
86 | |||
87 | return new VisitResult(successfulVisit, hasMore, transformation, activation); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public synchronized boolean hasUnmarkedActivation(VersionWithObjectiveValue version) { | ||
92 | var entries = versionToActivations.get(version); | ||
93 | boolean hasMore = false; | ||
94 | for (var entry : entries) { | ||
95 | if (entry.getNumberOfUnvisitedActivations() > 0) { | ||
96 | hasMore = true; | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | return hasMore; | ||
101 | } | ||
102 | |||
103 | @Override | ||
104 | public synchronized VisitResult getRandomAndMarkAsVisited(VersionWithObjectiveValue version, Random random) { | ||
105 | var entries = versionToActivations.get(version); | ||
106 | |||
107 | var weights = new double[entries.size()]; | ||
108 | double totalWeight = 0; | ||
109 | int numberOfAllUnvisitedActivations = 0; | ||
110 | for (int i = 0; i < weights.length; i++) { | ||
111 | var entry = entries.get(i); | ||
112 | int unvisited = entry.getNumberOfUnvisitedActivations(); | ||
113 | double weight = unvisited == 0 ? 0 : unvisited; //(Math.log(unvisited) + 1.0); | ||
114 | weights[i] = weight; | ||
115 | totalWeight += weight; | ||
116 | numberOfAllUnvisitedActivations += unvisited; | ||
117 | } | ||
118 | |||
119 | if (numberOfAllUnvisitedActivations == 0) { | ||
120 | this.actionWhenAllActivationVisited.accept(version); | ||
121 | return new VisitResult(false, false, -1, -1); | ||
122 | } | ||
123 | |||
124 | double offset = random.nextDouble(totalWeight); | ||
125 | int transformation = 0; | ||
126 | for (; transformation < entries.size(); transformation++) { | ||
127 | double weight = weights[transformation]; | ||
128 | if (weight > 0 && offset < weight) { | ||
129 | var entry = entries.get(transformation); | ||
130 | int activation = random.nextInt(entry.getNumberOfActivations()); | ||
131 | return this.visitActivation(version, transformation, activation); | ||
132 | } | ||
133 | offset -= weight; | ||
134 | } | ||
135 | |||
136 | throw new AssertionError("Unvisited activation %f not found".formatted(offset)); | ||
137 | } | ||
138 | } | ||