diff options
author | 2023-10-15 15:57:52 +0200 | |
---|---|---|
committer | 2023-10-15 15:57:52 +0200 | |
commit | acb5e04319883ceb0dffe25635db5dc22448f247 (patch) | |
tree | a58ba07ae482ff1b850d040bb263e38ae0d50876 /subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java | |
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/refinery/interpreter/rete/network/communication/CommunicationTracker.java')
-rw-r--r-- | subprojects/interpreter-rete/src/main/java/tools/refinery/interpreter/rete/network/communication/CommunicationTracker.java | 46 |
1 files changed, 35 insertions, 11 deletions
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, |