aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/statespace/internal/ActivationStoreImpl.java
diff options
context:
space:
mode:
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.java138
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 */
6package tools.refinery.store.dse.transition.statespace.internal;
7
8import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
9import tools.refinery.store.dse.transition.statespace.ActivationStore;
10
11import java.util.*;
12import java.util.function.Consumer;
13
14public 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}