aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java')
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java125
1 files changed, 125 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java
new file mode 100644
index 00000000..95018c4f
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/RepresentativeElectionNode.java
@@ -0,0 +1,125 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2012, Tamas Szabo, Gabor Bergmann, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.rete.single;
10
11import tools.refinery.viatra.runtime.rete.itc.alg.representative.RepresentativeElectionAlgorithm;
12import tools.refinery.viatra.runtime.rete.itc.alg.representative.RepresentativeObserver;
13import tools.refinery.viatra.runtime.rete.itc.graphimpl.Graph;
14import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
15import tools.refinery.viatra.runtime.matchers.tuple.Tuples;
16import tools.refinery.viatra.runtime.matchers.util.Clearable;
17import tools.refinery.viatra.runtime.matchers.util.Direction;
18import tools.refinery.viatra.runtime.matchers.util.timeline.Timeline;
19import tools.refinery.viatra.runtime.rete.network.ReinitializedNode;
20import tools.refinery.viatra.runtime.rete.network.ReteContainer;
21import tools.refinery.viatra.runtime.rete.network.communication.Timestamp;
22
23import java.util.Collection;
24import java.util.Map;
25
26public class RepresentativeElectionNode extends SingleInputNode implements Clearable, RepresentativeObserver,
27 ReinitializedNode {
28 private final RepresentativeElectionAlgorithm.Factory algorithmFactory;
29 private Graph<Object> graph;
30 private RepresentativeElectionAlgorithm algorithm;
31
32 public RepresentativeElectionNode(ReteContainer reteContainer,
33 RepresentativeElectionAlgorithm.Factory algorithmFactory) {
34 super(reteContainer);
35 this.algorithmFactory = algorithmFactory;
36 graph = new Graph<>();
37 algorithm = algorithmFactory.create(graph);
38 algorithm.setObserver(this);
39 reteContainer.registerClearable(this);
40 }
41
42 @Override
43 public void networkStructureChanged() {
44 if (reteContainer.isTimelyEvaluation() && reteContainer.getCommunicationTracker().isInRecursiveGroup(this)) {
45 throw new IllegalStateException(this + " cannot be used in recursive differential dataflow evaluation!");
46 }
47 super.networkStructureChanged();
48 }
49
50 @Override
51 public void reinitializeWith(Collection<Tuple> tuples) {
52 algorithm.dispose();
53 graph = new Graph<>();
54 for (var tuple : tuples) {
55 insertEdge(tuple.get(0), tuple.get(1));
56 }
57 algorithm = algorithmFactory.create(graph);
58 algorithm.setObserver(this);
59 }
60
61 @Override
62 public void tupleChanged(Object source, Object representative, Direction direction) {
63 var tuple = Tuples.staticArityFlatTupleOf(source, representative);
64 propagateUpdate(direction, tuple, Timestamp.ZERO);
65 }
66
67 @Override
68 public void clear() {
69 algorithm.dispose();
70 graph = new Graph<>();
71 algorithm = algorithmFactory.create(graph);
72 }
73
74 @Override
75 public void update(Direction direction, Tuple updateElement, Timestamp timestamp) {
76 var source = updateElement.get(0);
77 var target = updateElement.get(1);
78 switch (direction) {
79 case INSERT -> insertEdge(source, target);
80 case DELETE -> deleteEdge(source, target);
81 default -> throw new IllegalArgumentException("Unknown direction: " + direction);
82 }
83 }
84
85 private void insertEdge(Object source, Object target) {
86 graph.insertNode(source);
87 graph.insertNode(target);
88 graph.insertEdge(source, target);
89 }
90
91 private void deleteEdge(Object source, Object target) {
92 graph.deleteEdgeIfExists(source, target);
93 if (isIsolated(source)) {
94 graph.deleteNode(source);
95 }
96 if (!source.equals(target) && isIsolated(target)) {
97 graph.deleteNode(target);
98 }
99 }
100
101 private boolean isIsolated(Object node) {
102 return graph.getTargetNodes(node).isEmpty() && graph.getSourceNodes(node).isEmpty();
103 }
104
105 @Override
106 public void pullInto(Collection<Tuple> collector, boolean flush) {
107 for (var entry : algorithm.getComponents().entrySet()) {
108 var representative = entry.getKey();
109 for (var node : entry.getValue()) {
110 collector.add(Tuples.staticArityFlatTupleOf(node, representative));
111 }
112 }
113 }
114
115 @Override
116 public void pullIntoWithTimeline(Map<Tuple, Timeline<Timestamp>> collector, boolean flush) {
117 // Use all zero timestamps because this node cannot be used in recursive groups anyway.
118 for (var entry : algorithm.getComponents().entrySet()) {
119 var representative = entry.getKey();
120 for (var node : entry.getValue()) {
121 collector.put(Tuples.staticArityFlatTupleOf(node, representative), Timestamp.INSERT_AT_ZERO_TIMELINE);
122 }
123 }
124 }
125}