aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java')
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java130
1 files changed, 130 insertions, 0 deletions
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java
new file mode 100644
index 00000000..acc53e73
--- /dev/null
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java
@@ -0,0 +1,130 @@
1package tools.refinery.language.semantics.model.internal;
2
3import org.eclipse.collections.api.LazyIntIterable;
4import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
5import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
6import org.eclipse.collections.api.tuple.primitive.IntObjectPair;
7import tools.refinery.store.model.Tuple;
8import tools.refinery.store.model.representation.TruthValue;
9
10final class IntermediateNode extends DecisionTreeNode {
11 private final MutableIntObjectMap<DecisionTreeNode> children;
12
13 private final DecisionTreeNode otherwise;
14
15 IntermediateNode(MutableIntObjectMap<DecisionTreeNode> children, DecisionTreeNode otherwise) {
16 this.children = children;
17 this.otherwise = otherwise;
18 }
19
20 private DecisionTreeNode getChild(int index) {
21 var child = children.get(index);
22 return child == null ? otherwise : child;
23 }
24
25 @Override
26 public DecisionTreeValue getValue(int level, Tuple tuple) {
27 return getChild(tuple.get(level)).getValue(level - 1, tuple);
28 }
29
30 @Override
31 public DecisionTreeNode deepCopy() {
32 var newChildren = IntObjectMaps.mutable.from(children.keyValuesView(), IntObjectPair::getOne,
33 pair -> pair.getTwo().deepCopy());
34 var newOtherwise = otherwise.deepCopy();
35 return new IntermediateNode(newChildren, newOtherwise);
36 }
37
38 @Override
39 protected void mergeAllValues(int nextLevel, Tuple tuple, TruthValue value) {
40 otherwise.mergeValue(nextLevel, tuple, value);
41 for (var child : children) {
42 child.mergeValue(nextLevel, tuple, value);
43 }
44 reduceChildren();
45 }
46
47 @Override
48 protected void mergeSingleValue(int key, int nextLevel, Tuple tuple, TruthValue value) {
49 var otherwiseReduced = getOtherwiseReducedValue();
50 var child = children.get(key);
51 if (child == null) {
52 var newChild = otherwise.withMergedValue(nextLevel, tuple, value);
53 if (otherwiseReduced == null || newChild.getReducedValue() != otherwiseReduced) {
54 children.put(key, newChild);
55 }
56 return;
57 }
58 child.mergeValue(nextLevel, tuple, value);
59 if (otherwiseReduced != null && child.getReducedValue() == otherwiseReduced) {
60 children.remove(key);
61 }
62 }
63
64 @Override
65 public void overwriteValues(DecisionTreeNode values) {
66 if (values instanceof IntermediateNode intermediateValues) {
67 otherwise.overwriteValues(intermediateValues.otherwise);
68 for (var pair : children.keyValuesView()) {
69 pair.getTwo().overwriteValues(intermediateValues.getChild(pair.getOne()));
70 }
71 for (var pair : intermediateValues.children.keyValuesView()) {
72 children.getIfAbsentPut(pair.getOne(), () -> otherwise.withOverwrittenValues(pair.getTwo()));
73 }
74 reduceChildren();
75 } else {
76 throw new IllegalArgumentException("Level mismatch");
77 }
78 }
79
80 private void reduceChildren() {
81 var otherwiseReduced = getOtherwiseReducedValue();
82 if (otherwiseReduced == null) {
83 return;
84 }
85 var iterator = children.iterator();
86 while (iterator.hasNext()) {
87 var child = iterator.next();
88 if (child.getReducedValue() == otherwiseReduced) {
89 iterator.remove();
90 }
91 }
92 }
93
94 @Override
95 protected DecisionTreeValue getOtherwiseReducedValue() {
96 return otherwise.getReducedValue();
97 }
98
99 @Override
100 protected LazyIntIterable getChildKeys() {
101 return children.keysView();
102 }
103
104 protected boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, int[] sortedChildren) {
105 for (int i = startIndex; i < sortedChildren.length; i++) {
106 var key = sortedChildren[i];
107 var child = getChild(key);
108 var found = child.moveNext(level - 1, cursor);
109 if (found) {
110 cursor.iterationState[level] = i;
111 cursor.rawTuple[level] = key;
112 return true;
113 }
114 }
115 return false;
116 }
117
118 protected boolean moveNextDense(int level, DecisionTreeCursor cursor, int startIndex) {
119 for (int i = startIndex; i < cursor.nodeCount; i++) {
120 var child = getChild(i);
121 var found = child.moveNext(level - 1, cursor);
122 if (found) {
123 cursor.iterationState[level] = i;
124 cursor.rawTuple[level] = i;
125 return true;
126 }
127 }
128 return false;
129 }
130}