aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java')
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java179
1 files changed, 179 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java
new file mode 100644
index 00000000..892d048e
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/misc/scc/PKAlg.java
@@ -0,0 +1,179 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2012, Tamas Szabo, 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
10package tools.refinery.viatra.runtime.rete.itc.alg.misc.scc;
11
12import java.util.ArrayList;
13import java.util.Collections;
14import java.util.HashMap;
15import java.util.List;
16import java.util.Map;
17
18import tools.refinery.viatra.runtime.rete.itc.igraph.IBiDirectionalGraphDataSource;
19import tools.refinery.viatra.runtime.rete.itc.igraph.IBiDirectionalWrapper;
20import tools.refinery.viatra.runtime.rete.itc.igraph.IGraphDataSource;
21import tools.refinery.viatra.runtime.rete.itc.igraph.IGraphObserver;
22
23public class PKAlg<V> implements IGraphObserver<V> {
24
25 /**
26 * Maps the nodes to their indicies.
27 */
28 private Map<V, Integer> node2index;
29 private Map<Integer, V> index2node;
30 private Map<V, Boolean> node2mark;
31
32 /**
33 * Maps the index of a node to the index in the topsort.
34 */
35 private Map<Integer, Integer> index2topsort;
36 private Map<Integer, Integer> topsort2index;
37
38 /**
39 * Index associated to the inserted nodes (incrementing with every insertion).
40 */
41 private int index;
42
43 /**
44 * Index within the topsort for the target node when edge insertion occurs.
45 */
46 private int lower_bound;
47
48 /**
49 * Index within the topsort for the source node when edge insertion occurs.
50 */
51 private int upper_bound;
52
53 private List<V> RF;
54 private List<V> RB;
55 private IBiDirectionalGraphDataSource<V> gds;
56
57 public PKAlg(IGraphDataSource<V> gds) {
58 if (gds instanceof IBiDirectionalGraphDataSource<?>) {
59 this.gds = (IBiDirectionalGraphDataSource<V>) gds;
60 } else {
61 this.gds = new IBiDirectionalWrapper<V>(gds);
62 }
63
64 node2mark = new HashMap<V, Boolean>();
65 node2index = new HashMap<V, Integer>();
66 index2node = new HashMap<Integer, V>();
67 index2topsort = new HashMap<Integer, Integer>();
68 topsort2index = new HashMap<Integer, Integer>();
69 index = 0;
70
71 gds.attachObserver(this);
72 }
73
74 @Override
75 public void edgeInserted(V source, V target) {
76
77 RF = new ArrayList<V>();
78 RB = new ArrayList<V>();
79
80 lower_bound = index2topsort.get(node2index.get(target));
81 upper_bound = index2topsort.get(node2index.get(source));
82
83 if (lower_bound < upper_bound) {
84 dfsForward(target);
85 dfsBackward(source);
86 reorder();
87 }
88 }
89
90 private List<Integer> getIndicies(List<V> list) {
91 List<Integer> indicies = new ArrayList<Integer>();
92
93 for (V n : list)
94 indicies.add(index2topsort.get(node2index.get(n)));
95
96 return indicies;
97 }
98
99 private void reorder() {
100
101 Collections.reverse(RB);
102
103 // azon csomopontok indexei amelyek sorrendje nem jo
104 List<Integer> L = getIndicies(RF);
105 L.addAll(getIndicies(RB));
106 Collections.sort(L);
107
108 for (int i = 0; i < RB.size(); i++) {
109 index2topsort.put(node2index.get(RB.get(i)), L.get(i));
110 topsort2index.put(L.get(i), node2index.get(RB.get(i)));
111 }
112
113 for (int i = 0; i < RF.size(); i++) {
114 index2topsort.put(node2index.get(RF.get(i)), L.get(i + RB.size()));
115 topsort2index.put(L.get(i + RB.size()), node2index.get(RF.get(i)));
116 }
117 }
118
119 @SuppressWarnings("unused")
120 private List<V> getTopSort() {
121 List<V> topsort = new ArrayList<V>();
122
123 for (int i : topsort2index.values()) {
124 topsort.add(index2node.get(i));
125 }
126
127 return topsort;
128 }
129
130 private void dfsBackward(V node) {
131 node2mark.put(node, true);
132 RB.add(node);
133
134 for (V sn : gds.getSourceNodes(node).distinctValues()) {
135 int top_id = index2topsort.get(node2index.get(sn));
136
137 if (!node2mark.get(sn) && lower_bound < top_id)
138 dfsBackward(sn);
139 }
140 }
141
142 private void dfsForward(V node) {
143 node2mark.put(node, true);
144 RF.add(node);
145
146 for (V tn : gds.getTargetNodes(node).distinctValues()) {
147 int top_id = index2topsort.get(node2index.get(tn));
148
149 if (top_id == upper_bound)
150 System.out.println("!!!Cycle detected!!!");
151 else if (!node2mark.get(tn) && top_id < upper_bound)
152 dfsForward(tn);
153 }
154 }
155
156 @Override
157 public void edgeDeleted(V source, V target) {
158 // Edge deletion does not affect topsort
159 }
160
161 @Override
162 public void nodeInserted(V n) {
163 node2mark.put(n, false);
164 node2index.put(n, index);
165 index2node.put(index, n);
166 index2topsort.put(index, index);
167 topsort2index.put(index, index);
168 index++;
169 }
170
171 @Override
172 public void nodeDeleted(V n) {
173 node2mark.remove(n);
174 int node_id = node2index.remove(n);
175 index2node.remove(node_id);
176 int top_id = index2topsort.remove(node_id);
177 topsort2index.remove(top_id);
178 }
179}