diff options
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/TransitiveClosureNode.java')
-rw-r--r-- | subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/TransitiveClosureNode.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/TransitiveClosureNode.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/TransitiveClosureNode.java new file mode 100644 index 00000000..fdda4ef4 --- /dev/null +++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/single/TransitiveClosureNode.java | |||
@@ -0,0 +1,147 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2012, Tamas Szabo, Gabor Bergmann, Istvan Rath and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.rete.single; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.rete.itc.alg.incscc.IncSCCAlg; | ||
12 | import tools.refinery.viatra.runtime.rete.itc.alg.misc.Tuple; | ||
13 | import tools.refinery.viatra.runtime.rete.itc.graphimpl.Graph; | ||
14 | import tools.refinery.viatra.runtime.rete.itc.igraph.ITcDataSource; | ||
15 | import tools.refinery.viatra.runtime.rete.itc.igraph.ITcObserver; | ||
16 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
17 | import tools.refinery.viatra.runtime.matchers.util.Clearable; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Direction; | ||
19 | import tools.refinery.viatra.runtime.matchers.util.timeline.Timeline; | ||
20 | import tools.refinery.viatra.runtime.rete.network.NetworkStructureChangeSensitiveNode; | ||
21 | import tools.refinery.viatra.runtime.rete.network.ReinitializedNode; | ||
22 | import tools.refinery.viatra.runtime.rete.network.ReteContainer; | ||
23 | import tools.refinery.viatra.runtime.rete.network.communication.CommunicationGroup; | ||
24 | import tools.refinery.viatra.runtime.rete.network.communication.Timestamp; | ||
25 | |||
26 | import java.util.Collection; | ||
27 | import java.util.Map; | ||
28 | |||
29 | /** | ||
30 | * This class represents a transitive closure node in the Rete net. | ||
31 | * <p> | ||
32 | * This node must not be used in recursive {@link CommunicationGroup}s. | ||
33 | * | ||
34 | * @author Gabor Bergmann | ||
35 | * | ||
36 | */ | ||
37 | public class TransitiveClosureNode extends SingleInputNode | ||
38 | implements Clearable, ITcObserver<Object>, NetworkStructureChangeSensitiveNode, ReinitializedNode { | ||
39 | |||
40 | private Graph<Object> graphDataSource; | ||
41 | private ITcDataSource<Object> transitiveClosureAlgorithm; | ||
42 | |||
43 | /** | ||
44 | * Create a new transitive closure rete node. | ||
45 | * | ||
46 | * Client may optionally call {@link #reinitializeWith(Collection)} before using the node, instead of inserting the | ||
47 | * initial set of tuples one by one. | ||
48 | * | ||
49 | * @param reteContainer | ||
50 | * the rete container of the node | ||
51 | */ | ||
52 | public TransitiveClosureNode(ReteContainer reteContainer) { | ||
53 | super(reteContainer); | ||
54 | graphDataSource = new Graph<Object>(); | ||
55 | transitiveClosureAlgorithm = new IncSCCAlg<Object>(graphDataSource); | ||
56 | transitiveClosureAlgorithm.attachObserver(this); | ||
57 | reteContainer.registerClearable(this); | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public void networkStructureChanged() { | ||
62 | if (this.reteContainer.isTimelyEvaluation() && this.reteContainer.getCommunicationTracker().isInRecursiveGroup(this)) { | ||
63 | throw new IllegalStateException(this.toString() + " cannot be used in recursive differential dataflow evaluation!"); | ||
64 | } | ||
65 | super.networkStructureChanged(); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Initializes the graph data source with the given collection of tuples. | ||
70 | * | ||
71 | * @param tuples | ||
72 | * the initial collection of tuples | ||
73 | */ | ||
74 | @Override | ||
75 | public void reinitializeWith(Collection<tools.refinery.viatra.runtime.matchers.tuple.Tuple> tuples) { | ||
76 | clear(); | ||
77 | |||
78 | for (tools.refinery.viatra.runtime.matchers.tuple.Tuple t : tuples) { | ||
79 | graphDataSource.insertNode(t.get(0)); | ||
80 | graphDataSource.insertNode(t.get(1)); | ||
81 | graphDataSource.insertEdge(t.get(0), t.get(1)); | ||
82 | } | ||
83 | transitiveClosureAlgorithm.attachObserver(this); | ||
84 | } | ||
85 | |||
86 | @Override | ||
87 | public void pullInto(final Collection<tools.refinery.viatra.runtime.matchers.tuple.Tuple> collector, final boolean flush) { | ||
88 | for (final Tuple<Object> tuple : ((IncSCCAlg<Object>) transitiveClosureAlgorithm).getTcRelation()) { | ||
89 | collector.add(Tuples.staticArityFlatTupleOf(tuple.getSource(), tuple.getTarget())); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public void pullIntoWithTimeline( | ||
95 | final Map<tools.refinery.viatra.runtime.matchers.tuple.Tuple, Timeline<Timestamp>> collector, | ||
96 | final boolean flush) { | ||
97 | // use all zero timestamps because this node cannot be used in recursive groups anyway | ||
98 | for (final Tuple<Object> tuple : ((IncSCCAlg<Object>) transitiveClosureAlgorithm).getTcRelation()) { | ||
99 | collector.put(Tuples.staticArityFlatTupleOf(tuple.getSource(), tuple.getTarget()), Timestamp.INSERT_AT_ZERO_TIMELINE); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | @Override | ||
104 | public void update(Direction direction, tools.refinery.viatra.runtime.matchers.tuple.Tuple updateElement, | ||
105 | Timestamp timestamp) { | ||
106 | if (updateElement.getSize() == 2) { | ||
107 | Object source = updateElement.get(0); | ||
108 | Object target = updateElement.get(1); | ||
109 | |||
110 | if (direction == Direction.INSERT) { | ||
111 | graphDataSource.insertNode(source); | ||
112 | graphDataSource.insertNode(target); | ||
113 | graphDataSource.insertEdge(source, target); | ||
114 | } | ||
115 | if (direction == Direction.DELETE) { | ||
116 | graphDataSource.deleteEdgeIfExists(source, target); | ||
117 | |||
118 | if (((IncSCCAlg<Object>) transitiveClosureAlgorithm).isIsolated(source)) { | ||
119 | graphDataSource.deleteNode(source); | ||
120 | } | ||
121 | if (!source.equals(target) && ((IncSCCAlg<Object>) transitiveClosureAlgorithm).isIsolated(target)) { | ||
122 | graphDataSource.deleteNode(target); | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public void clear() { | ||
130 | transitiveClosureAlgorithm.dispose(); | ||
131 | graphDataSource = new Graph<Object>(); | ||
132 | transitiveClosureAlgorithm = new IncSCCAlg<Object>(graphDataSource); | ||
133 | } | ||
134 | |||
135 | @Override | ||
136 | public void tupleInserted(Object source, Object target) { | ||
137 | tools.refinery.viatra.runtime.matchers.tuple.Tuple tuple = Tuples.staticArityFlatTupleOf(source, target); | ||
138 | propagateUpdate(Direction.INSERT, tuple, Timestamp.ZERO); | ||
139 | } | ||
140 | |||
141 | @Override | ||
142 | public void tupleDeleted(Object source, Object target) { | ||
143 | tools.refinery.viatra.runtime.matchers.tuple.Tuple tuple = Tuples.staticArityFlatTupleOf(source, target); | ||
144 | propagateUpdate(Direction.DELETE, tuple, Timestamp.ZERO); | ||
145 | } | ||
146 | |||
147 | } | ||