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 /subprojects/interpreter-rete/src/main/java/tools | |
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.
Diffstat (limited to 'subprojects/interpreter-rete/src/main/java/tools')
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) { |