diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-10-15 15:57:52 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-10-15 15:57:52 +0200 |
commit | acb5e04319883ceb0dffe25635db5dc22448f247 (patch) | |
tree | a58ba07ae482ff1b850d040bb263e38ae0d50876 | |
parent | refactor(interpreter): generify RepresentativeElectionAlgorithm (diff) | |
download | refinery-acb5e04319883ceb0dffe25635db5dc22448f247.tar.gz refinery-acb5e04319883ceb0dffe25635db5dc22448f247.tar.zst refinery-acb5e04319883ceb0dffe25635db5dc22448f247.zip |
refactor(interpreter): communication tracker algorithm
Use a faster algorithm to detect cycles in the RETE network.
Only if cycles are detected fall back to the transitive closure algorithm to
construct the SCCs and the reduced graph.
5 files changed, 151 insertions, 35 deletions
diff --git a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/ReteContainer.java b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/ReteContainer.java index b5c91d32..3eafc149 100644 --- a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/ReteContainer.java +++ b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/ReteContainer.java | |||
@@ -90,15 +90,16 @@ public final class ReteContainer { | |||
90 | this.delayedCommandBuffer = new LinkedHashSet<DelayedCommand>(); | 90 | this.delayedCommandBuffer = new LinkedHashSet<DelayedCommand>(); |
91 | this.executingDelayedCommands = false; | 91 | this.executingDelayedCommands = false; |
92 | 92 | ||
93 | this.logger = network.getEngine().getLogger(); | ||
94 | |||
93 | if (this.isTimelyEvaluation()) { | 95 | if (this.isTimelyEvaluation()) { |
94 | this.tracker = new TimelyCommunicationTracker(this.getTimelyConfiguration()); | 96 | this.tracker = new TimelyCommunicationTracker(logger, this.getTimelyConfiguration()); |
95 | } else { | 97 | } else { |
96 | this.tracker = new TimelessCommunicationTracker(); | 98 | this.tracker = new TimelessCommunicationTracker(logger); |
97 | } | 99 | } |
98 | 100 | ||
99 | this.nodesById = CollectionsFactory.createMap(); | 101 | this.nodesById = CollectionsFactory.createMap(); |
100 | this.clearables = new LinkedList<Clearable>(); | 102 | this.clearables = new LinkedList<Clearable>(); |
101 | this.logger = network.getEngine().getLogger(); | ||
102 | 103 | ||
103 | this.connectionFactory = new ConnectionFactory(this); | 104 | this.connectionFactory = new ConnectionFactory(this); |
104 | this.nodeProvisioner = new NodeProvisioner(this); | 105 | this.nodeProvisioner = new NodeProvisioner(this); |
diff --git a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java index 2e8eb338..1d089ba6 100644 --- a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java +++ b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2017, Tamas Szabo, Istvan Rath and Daniel Varro | 2 | * Copyright (c) 2010-2017, Tamas Szabo, Istvan Rath and Daniel Varro |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
@@ -8,12 +9,13 @@ | |||
8 | *******************************************************************************/ | 9 | *******************************************************************************/ |
9 | package tools.refinery.interpreter.rete.network.communication; | 10 | package tools.refinery.interpreter.rete.network.communication; |
10 | 11 | ||
12 | import org.apache.log4j.Logger; | ||
13 | import org.jetbrains.annotations.Nullable; | ||
11 | import tools.refinery.interpreter.matchers.tuple.TupleMask; | 14 | import tools.refinery.interpreter.matchers.tuple.TupleMask; |
12 | import tools.refinery.interpreter.rete.aggregation.IAggregatorNode; | 15 | import tools.refinery.interpreter.rete.aggregation.IAggregatorNode; |
13 | import tools.refinery.interpreter.rete.boundary.ExternalInputEnumeratorNode; | 16 | import tools.refinery.interpreter.rete.boundary.ExternalInputEnumeratorNode; |
14 | import tools.refinery.interpreter.rete.eval.RelationEvaluatorNode; | 17 | import tools.refinery.interpreter.rete.eval.RelationEvaluatorNode; |
15 | import tools.refinery.interpreter.rete.index.*; | 18 | import tools.refinery.interpreter.rete.index.*; |
16 | import tools.refinery.interpreter.rete.itc.alg.incscc.IncSCCAlg; | ||
17 | import tools.refinery.interpreter.rete.itc.alg.misc.topsort.TopologicalSorting; | 19 | import tools.refinery.interpreter.rete.itc.alg.misc.topsort.TopologicalSorting; |
18 | import tools.refinery.interpreter.rete.itc.graphimpl.Graph; | 20 | import tools.refinery.interpreter.rete.itc.graphimpl.Graph; |
19 | import tools.refinery.interpreter.rete.network.*; | 21 | import tools.refinery.interpreter.rete.network.*; |
@@ -61,7 +63,7 @@ public abstract class CommunicationTracker { | |||
61 | /** | 63 | /** |
62 | * Incremental SCC information about the dependency graph | 64 | * Incremental SCC information about the dependency graph |
63 | */ | 65 | */ |
64 | protected final IncSCCAlg<Node> sccInformationProvider; | 66 | private final NetworkComponentDetector componentDetector; |
65 | 67 | ||
66 | /** | 68 | /** |
67 | * Precomputed node -> communication group map | 69 | * Precomputed node -> communication group map |
@@ -76,9 +78,9 @@ public abstract class CommunicationTracker { | |||
76 | // groups should have a simple integer flag which represents its position in a priority queue | 78 | // groups should have a simple integer flag which represents its position in a priority queue |
77 | // priority queue only contains the ACTIVE groups | 79 | // priority queue only contains the ACTIVE groups |
78 | 80 | ||
79 | public CommunicationTracker() { | 81 | public CommunicationTracker(Logger logger) { |
80 | this.dependencyGraph = new Graph<Node>(); | 82 | this.dependencyGraph = new Graph<Node>(); |
81 | this.sccInformationProvider = new IncSCCAlg<Node>(this.dependencyGraph); | 83 | this.componentDetector = new NetworkComponentDetector(logger, dependencyGraph); |
82 | this.groupQueue = new PriorityQueue<CommunicationGroup>(); | 84 | this.groupQueue = new PriorityQueue<CommunicationGroup>(); |
83 | this.groupMap = new HashMap<Node, CommunicationGroup>(); | 85 | this.groupMap = new HashMap<Node, CommunicationGroup>(); |
84 | } | 86 | } |
@@ -91,11 +93,33 @@ public abstract class CommunicationTracker { | |||
91 | return this.groupMap.get(node); | 93 | return this.groupMap.get(node); |
92 | } | 94 | } |
93 | 95 | ||
96 | @Nullable | ||
97 | protected Set<Node> getPartition(Node node) { | ||
98 | return componentDetector.getPartition(node); | ||
99 | } | ||
100 | |||
101 | protected boolean isSingleton(Node node) { | ||
102 | var partition = getPartition(node); | ||
103 | return partition == null || partition.isEmpty(); | ||
104 | } | ||
105 | |||
106 | protected Node getRepresentative(Node node) { | ||
107 | return componentDetector.getRepresentative(node); | ||
108 | } | ||
109 | |||
110 | protected boolean hasOutgoingEdges(Node representative) { | ||
111 | return componentDetector.hasOutgoingEdges(representative); | ||
112 | } | ||
113 | |||
114 | protected Graph<Node> getReducedGraph() { | ||
115 | return componentDetector.getReducedGraph(); | ||
116 | } | ||
117 | |||
94 | private void precomputeGroups() { | 118 | private void precomputeGroups() { |
95 | groupMap.clear(); | 119 | groupMap.clear(); |
96 | 120 | ||
97 | // reconstruct group map from dependency graph | 121 | // reconstruct group map from dependency graph |
98 | final Graph<Node> reducedGraph = sccInformationProvider.getReducedGraph(); | 122 | final Graph<Node> reducedGraph = getReducedGraph(); |
99 | final List<Node> representatives = TopologicalSorting.compute(reducedGraph); | 123 | final List<Node> representatives = TopologicalSorting.compute(reducedGraph); |
100 | 124 | ||
101 | for (int i = 0; i < representatives.size(); i++) { // groups for SCC representatives | 125 | for (int i = 0; i < representatives.size(); i++) { // groups for SCC representatives |
@@ -107,7 +131,7 @@ public abstract class CommunicationTracker { | |||
107 | maxGroupId = representatives.size() - 1; | 131 | maxGroupId = representatives.size() - 1; |
108 | 132 | ||
109 | for (final Node node : dependencyGraph.getAllNodes()) { // extend group map to the rest of nodes | 133 | for (final Node node : dependencyGraph.getAllNodes()) { // extend group map to the rest of nodes |
110 | final Node representative = sccInformationProvider.getRepresentative(node); | 134 | final Node representative = getRepresentative(node); |
111 | final CommunicationGroup group = groupMap.get(representative); | 135 | final CommunicationGroup group = groupMap.get(representative); |
112 | if (representative != node) { | 136 | if (representative != node) { |
113 | addToGroup(node, group); | 137 | addToGroup(node, group); |
@@ -285,9 +309,9 @@ public abstract class CommunicationTracker { | |||
285 | 309 | ||
286 | // query all these information before the actual edge insertion | 310 | // query all these information before the actual edge insertion |
287 | // because SCCs may be unified during the process | 311 | // because SCCs may be unified during the process |
288 | final Node sourceRepresentative = sccInformationProvider.getRepresentative(source); | 312 | final Node sourceRepresentative = getRepresentative(source); |
289 | final Node targetRepresentative = sccInformationProvider.getRepresentative(target); | 313 | final Node targetRepresentative = getRepresentative(target); |
290 | final boolean targetHadOutgoingEdges = sccInformationProvider.hasOutgoingEdges(targetRepresentative); | 314 | final boolean targetHadOutgoingEdges = hasOutgoingEdges(targetRepresentative); |
291 | 315 | ||
292 | // insert the edge | 316 | // insert the edge |
293 | dependencyGraph.insertEdge(source, target); | 317 | dependencyGraph.insertEdge(source, target); |
@@ -372,8 +396,8 @@ public abstract class CommunicationTracker { | |||
372 | // delete the edge first, and then query the SCC info provider | 396 | // delete the edge first, and then query the SCC info provider |
373 | this.dependencyGraph.deleteEdgeIfExists(source, target); | 397 | this.dependencyGraph.deleteEdgeIfExists(source, target); |
374 | 398 | ||
375 | final Node sourceRepresentative = sccInformationProvider.getRepresentative(source); | 399 | final Node sourceRepresentative = getRepresentative(source); |
376 | final Node targetRepresentative = sccInformationProvider.getRepresentative(target); | 400 | final Node targetRepresentative = getRepresentative(target); |
377 | 401 | ||
378 | // if they are still in the same SCC, | 402 | // if they are still in the same SCC, |
379 | // then this deletion did not affect the SCCs, | 403 | // then this deletion did not affect the SCCs, |
diff --git a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/NetworkComponentDetector.java b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/NetworkComponentDetector.java new file mode 100644 index 00000000..6ed84e45 --- /dev/null +++ b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/NetworkComponentDetector.java | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.interpreter.rete.network.communication; | ||
7 | |||
8 | import org.apache.log4j.Logger; | ||
9 | import org.jetbrains.annotations.Nullable; | ||
10 | import tools.refinery.interpreter.matchers.util.Direction; | ||
11 | import tools.refinery.interpreter.rete.itc.alg.incscc.IncSCCAlg; | ||
12 | import tools.refinery.interpreter.rete.itc.alg.representative.RepresentativeObserver; | ||
13 | import tools.refinery.interpreter.rete.itc.alg.representative.StronglyConnectedComponentAlgorithm; | ||
14 | import tools.refinery.interpreter.rete.itc.graphimpl.Graph; | ||
15 | import tools.refinery.interpreter.rete.network.Node; | ||
16 | |||
17 | import java.util.Set; | ||
18 | |||
19 | public class NetworkComponentDetector implements RepresentativeObserver<Node> { | ||
20 | private final Logger logger; | ||
21 | private final Graph<Node> dependencyGraph; | ||
22 | private StronglyConnectedComponentAlgorithm<Node> stronglyConnectedComponentAlgorithm; | ||
23 | private IncSCCAlg<Node> sccInformationProvider; | ||
24 | |||
25 | public NetworkComponentDetector(Logger logger, Graph<Node> dependencyGraph) { | ||
26 | this.logger = logger; | ||
27 | this.dependencyGraph = dependencyGraph; | ||
28 | stronglyConnectedComponentAlgorithm = new StronglyConnectedComponentAlgorithm<>(dependencyGraph); | ||
29 | stronglyConnectedComponentAlgorithm.setObserver(this); | ||
30 | if (stronglyConnectedComponentAlgorithm.getComponents() | ||
31 | .values() | ||
32 | .stream() | ||
33 | .anyMatch(component -> component.size() > 1)) { | ||
34 | switchToTransitiveClosureAlgorithm(); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | @Nullable | ||
39 | public Set<Node> getPartition(Node node) { | ||
40 | if (sccInformationProvider == null) { | ||
41 | return null; | ||
42 | } | ||
43 | return sccInformationProvider.sccs.getPartition(node); | ||
44 | } | ||
45 | |||
46 | public Node getRepresentative(Node node) { | ||
47 | if (sccInformationProvider == null) { | ||
48 | return node; | ||
49 | } | ||
50 | return sccInformationProvider.getRepresentative(node); | ||
51 | } | ||
52 | |||
53 | public boolean hasOutgoingEdges(Node representative) { | ||
54 | if (sccInformationProvider == null) { | ||
55 | return !dependencyGraph.getTargetNodes(representative).isEmpty(); | ||
56 | } | ||
57 | return sccInformationProvider.hasOutgoingEdges(representative); | ||
58 | } | ||
59 | |||
60 | public Graph<Node> getReducedGraph() { | ||
61 | if (sccInformationProvider == null) { | ||
62 | return dependencyGraph; | ||
63 | } | ||
64 | return sccInformationProvider.getReducedGraph(); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public void tupleChanged(Node node, Node representative, Direction direction) { | ||
69 | if (direction == Direction.INSERT && !node.equals(representative)) { | ||
70 | switchToTransitiveClosureAlgorithm(); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | private void switchToTransitiveClosureAlgorithm() { | ||
75 | logger.warn("RETE network cycle detected, switching to transitive closure algorithm for communication groups"); | ||
76 | if (stronglyConnectedComponentAlgorithm != null) { | ||
77 | stronglyConnectedComponentAlgorithm.dispose(); | ||
78 | stronglyConnectedComponentAlgorithm = null; | ||
79 | } | ||
80 | if (sccInformationProvider == null) { | ||
81 | sccInformationProvider = new IncSCCAlg<>(dependencyGraph); | ||
82 | } | ||
83 | } | ||
84 | } | ||
diff --git a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timeless/TimelessCommunicationTracker.java b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timeless/TimelessCommunicationTracker.java index 77f40fc3..02116d71 100644 --- a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timeless/TimelessCommunicationTracker.java +++ b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timeless/TimelessCommunicationTracker.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath and Daniel Varro | 2 | * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath and Daniel Varro |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
@@ -8,11 +9,7 @@ | |||
8 | *******************************************************************************/ | 9 | *******************************************************************************/ |
9 | package tools.refinery.interpreter.rete.network.communication.timeless; | 10 | package tools.refinery.interpreter.rete.network.communication.timeless; |
10 | 11 | ||
11 | import java.util.Collection; | 12 | import org.apache.log4j.Logger; |
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | import java.util.Map.Entry; | ||
15 | |||
16 | import tools.refinery.interpreter.rete.index.DualInputNode; | 13 | import tools.refinery.interpreter.rete.index.DualInputNode; |
17 | import tools.refinery.interpreter.rete.index.Indexer; | 14 | import tools.refinery.interpreter.rete.index.Indexer; |
18 | import tools.refinery.interpreter.rete.index.IndexerListener; | 15 | import tools.refinery.interpreter.rete.index.IndexerListener; |
@@ -26,6 +23,11 @@ import tools.refinery.interpreter.rete.network.communication.MessageSelector; | |||
26 | import tools.refinery.interpreter.rete.network.mailbox.Mailbox; | 23 | import tools.refinery.interpreter.rete.network.mailbox.Mailbox; |
27 | import tools.refinery.interpreter.rete.network.mailbox.timeless.BehaviorChangingMailbox; | 24 | import tools.refinery.interpreter.rete.network.mailbox.timeless.BehaviorChangingMailbox; |
28 | 25 | ||
26 | import java.util.Collection; | ||
27 | import java.util.HashSet; | ||
28 | import java.util.Map.Entry; | ||
29 | import java.util.Set; | ||
30 | |||
29 | /** | 31 | /** |
30 | * Timeless implementation of the communication tracker. | 32 | * Timeless implementation of the communication tracker. |
31 | * | 33 | * |
@@ -33,10 +35,13 @@ import tools.refinery.interpreter.rete.network.mailbox.timeless.BehaviorChanging | |||
33 | * @since 2.2 | 35 | * @since 2.2 |
34 | */ | 36 | */ |
35 | public class TimelessCommunicationTracker extends CommunicationTracker { | 37 | public class TimelessCommunicationTracker extends CommunicationTracker { |
38 | public TimelessCommunicationTracker(Logger logger) { | ||
39 | super(logger); | ||
40 | } | ||
36 | 41 | ||
37 | @Override | 42 | @Override |
38 | protected CommunicationGroup createGroup(Node representative, int index) { | 43 | protected CommunicationGroup createGroup(Node representative, int index) { |
39 | final boolean isSingleton = this.sccInformationProvider.sccs.getPartition(representative).size() == 1; | 44 | final boolean isSingleton = isSingleton(representative); |
40 | final boolean isReceiver = representative instanceof Receiver; | 45 | final boolean isReceiver = representative instanceof Receiver; |
41 | final boolean isPosetIndifferent = isReceiver | 46 | final boolean isPosetIndifferent = isReceiver |
42 | && ((Receiver) representative).getMailbox() instanceof BehaviorChangingMailbox; | 47 | && ((Receiver) representative).getMailbox() instanceof BehaviorChangingMailbox; |
@@ -95,14 +100,13 @@ public class TimelessCommunicationTracker extends CommunicationTracker { | |||
95 | final Mailbox mailbox = ((Receiver) node).getMailbox(); | 100 | final Mailbox mailbox = ((Receiver) node).getMailbox(); |
96 | if (mailbox instanceof BehaviorChangingMailbox) { | 101 | if (mailbox instanceof BehaviorChangingMailbox) { |
97 | final CommunicationGroup group = this.groupMap.get(node); | 102 | final CommunicationGroup group = this.groupMap.get(node); |
98 | final Set<Node> sccNodes = this.sccInformationProvider.sccs.getPartition(node); | ||
99 | // a default mailbox must split its messages iff | 103 | // a default mailbox must split its messages iff |
100 | // (1) its receiver is in a recursive group and | 104 | // (1) its receiver is in a recursive group and |
101 | final boolean c1 = group.isRecursive(); | 105 | final boolean c1 = group.isRecursive(); |
102 | // (2) its receiver is at the SCC boundary of that group | 106 | // (2) its receiver is at the SCC boundary of that group |
103 | final boolean c2 = isAtSCCBoundary(node); | 107 | final boolean c2 = isAtSCCBoundary(node); |
104 | // (3) its group consists of more than one node | 108 | // (3) its group consists of more than one node |
105 | final boolean c3 = sccNodes.size() > 1; | 109 | final boolean c3 = isSingleton(node); |
106 | ((BehaviorChangingMailbox) mailbox).setSplitFlag(c1 && c2 && c3); | 110 | ((BehaviorChangingMailbox) mailbox).setSplitFlag(c1 && c2 && c3); |
107 | } | 111 | } |
108 | } | 112 | } |
diff --git a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timely/TimelyCommunicationTracker.java b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timely/TimelyCommunicationTracker.java index a0cdc701..6a92ac91 100644 --- a/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timely/TimelyCommunicationTracker.java +++ b/subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/timely/TimelyCommunicationTracker.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath and Daniel Varro | 2 | * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath and Daniel Varro |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
@@ -8,20 +9,14 @@ | |||
8 | *******************************************************************************/ | 9 | *******************************************************************************/ |
9 | package tools.refinery.interpreter.rete.network.communication.timely; | 10 | package tools.refinery.interpreter.rete.network.communication.timely; |
10 | 11 | ||
11 | import java.util.Collection; | 12 | import org.apache.log4j.Logger; |
12 | import java.util.List; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Set; | ||
16 | import java.util.function.Function; | ||
17 | |||
18 | import tools.refinery.interpreter.rete.itc.alg.misc.topsort.TopologicalSorting; | ||
19 | import tools.refinery.interpreter.rete.itc.graphimpl.Graph; | ||
20 | import tools.refinery.interpreter.matchers.util.CollectionsFactory; | 13 | import tools.refinery.interpreter.matchers.util.CollectionsFactory; |
21 | import tools.refinery.interpreter.rete.index.IndexerListener; | 14 | import tools.refinery.interpreter.rete.index.IndexerListener; |
22 | import tools.refinery.interpreter.rete.index.SpecializedProjectionIndexer; | 15 | import tools.refinery.interpreter.rete.index.SpecializedProjectionIndexer; |
23 | import tools.refinery.interpreter.rete.index.SpecializedProjectionIndexer.ListenerSubscription; | 16 | import tools.refinery.interpreter.rete.index.SpecializedProjectionIndexer.ListenerSubscription; |
24 | import tools.refinery.interpreter.rete.index.StandardIndexer; | 17 | import tools.refinery.interpreter.rete.index.StandardIndexer; |
18 | import tools.refinery.interpreter.rete.itc.alg.misc.topsort.TopologicalSorting; | ||
19 | import tools.refinery.interpreter.rete.itc.graphimpl.Graph; | ||
25 | import tools.refinery.interpreter.rete.matcher.TimelyConfiguration; | 20 | import tools.refinery.interpreter.rete.matcher.TimelyConfiguration; |
26 | import tools.refinery.interpreter.rete.matcher.TimelyConfiguration.TimelineRepresentation; | 21 | import tools.refinery.interpreter.rete.matcher.TimelyConfiguration.TimelineRepresentation; |
27 | import tools.refinery.interpreter.rete.network.NetworkStructureChangeSensitiveNode; | 22 | import tools.refinery.interpreter.rete.network.NetworkStructureChangeSensitiveNode; |
@@ -35,6 +30,13 @@ import tools.refinery.interpreter.rete.network.communication.NodeComparator; | |||
35 | import tools.refinery.interpreter.rete.network.mailbox.Mailbox; | 30 | import tools.refinery.interpreter.rete.network.mailbox.Mailbox; |
36 | import tools.refinery.interpreter.rete.single.DiscriminatorDispatcherNode; | 31 | import tools.refinery.interpreter.rete.single.DiscriminatorDispatcherNode; |
37 | 32 | ||
33 | import java.util.Collection; | ||
34 | import java.util.List; | ||
35 | import java.util.Map; | ||
36 | import java.util.Map.Entry; | ||
37 | import java.util.Set; | ||
38 | import java.util.function.Function; | ||
39 | |||
38 | /** | 40 | /** |
39 | * Timely (DDF) implementation of the {@link CommunicationTracker}. | 41 | * Timely (DDF) implementation of the {@link CommunicationTracker}. |
40 | * | 42 | * |
@@ -45,13 +47,14 @@ public class TimelyCommunicationTracker extends CommunicationTracker { | |||
45 | 47 | ||
46 | protected final TimelyConfiguration configuration; | 48 | protected final TimelyConfiguration configuration; |
47 | 49 | ||
48 | public TimelyCommunicationTracker(final TimelyConfiguration configuration) { | 50 | public TimelyCommunicationTracker(final Logger logger, final TimelyConfiguration configuration) { |
51 | super(logger); | ||
49 | this.configuration = configuration; | 52 | this.configuration = configuration; |
50 | } | 53 | } |
51 | 54 | ||
52 | @Override | 55 | @Override |
53 | protected CommunicationGroup createGroup(final Node representative, final int index) { | 56 | protected CommunicationGroup createGroup(final Node representative, final int index) { |
54 | final boolean isSingleton = this.sccInformationProvider.sccs.getPartition(representative).size() == 1; | 57 | final boolean isSingleton = isSingleton(representative); |
55 | return new TimelyCommunicationGroup(this, representative, index, isSingleton); | 58 | return new TimelyCommunicationGroup(this, representative, index, isSingleton); |
56 | } | 59 | } |
57 | 60 | ||
@@ -130,8 +133,8 @@ public class TimelyCommunicationTracker extends CommunicationTracker { | |||
130 | protected void postProcessGroup(final CommunicationGroup group) { | 133 | protected void postProcessGroup(final CommunicationGroup group) { |
131 | if (this.configuration.getTimelineRepresentation() == TimelineRepresentation.FAITHFUL) { | 134 | if (this.configuration.getTimelineRepresentation() == TimelineRepresentation.FAITHFUL) { |
132 | final Node representative = group.getRepresentative(); | 135 | final Node representative = group.getRepresentative(); |
133 | final Set<Node> groupMembers = this.sccInformationProvider.sccs.getPartition(representative); | 136 | final Set<Node> groupMembers = getPartition(representative); |
134 | if (groupMembers.size() > 1) { | 137 | if (groupMembers != null && groupMembers.size() > 1) { |
135 | final Graph<Node> graph = new Graph<Node>(); | 138 | final Graph<Node> graph = new Graph<Node>(); |
136 | 139 | ||
137 | for (final Node node : groupMembers) { | 140 | for (final Node node : groupMembers) { |