aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java')
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java259
1 files changed, 259 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java
new file mode 100644
index 00000000..474c7461
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/itc/alg/counting/CountingTcRelation.java
@@ -0,0 +1,259 @@
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.counting;
11
12import java.util.Collections;
13import java.util.List;
14import java.util.Set;
15
16import tools.refinery.viatra.runtime.rete.itc.alg.misc.topsort.TopologicalSorting;
17import tools.refinery.viatra.runtime.rete.itc.alg.misc.ITcRelation;
18import tools.refinery.viatra.runtime.rete.itc.igraph.IBiDirectionalGraphDataSource;
19import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory;
20import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType;
21import tools.refinery.viatra.runtime.matchers.util.IMemoryView;
22import tools.refinery.viatra.runtime.matchers.util.IMultiLookup;
23import tools.refinery.viatra.runtime.matchers.util.IMultiLookup.ChangeGranularity;
24
25/**
26 * Transitive closure relation implementation for the Counting algorithm.
27 *
28 * @author Tamas Szabo
29 *
30 * @param <V>
31 */
32public class CountingTcRelation<V> implements ITcRelation<V> {
33
34 private IMultiLookup<V, V> tuplesForward = null;
35 private IMultiLookup<V, V> tuplesBackward = null;
36
37 protected CountingTcRelation(boolean backwardIndexing) {
38 tuplesForward = CollectionsFactory.createMultiLookup(Object.class, MemoryType.MULTISETS, Object.class);
39 if (backwardIndexing)
40 tuplesBackward = CollectionsFactory.createMultiLookup(Object.class, MemoryType.MULTISETS, Object.class);
41 }
42
43 protected boolean isEmpty() {
44 return 0 == this.tuplesForward.countKeys();
45 }
46
47 protected void clear() {
48 this.tuplesForward.clear();
49
50 if (tuplesBackward != null) {
51 this.tuplesBackward.clear();
52 }
53 }
54
55 protected void union(CountingTcRelation<V> rA) {
56 IMultiLookup<V, V> rForward = rA.tuplesForward;
57 for (V source : rForward.distinctKeys()) {
58 IMemoryView<V> targetBag = rForward.lookup(source);
59 for (V target : targetBag.distinctValues()) {
60 this.addTuple(source, target, targetBag.getCount(target));
61 }
62 }
63 }
64
65 public int getCount(V source, V target) {
66 IMemoryView<V> bucket = tuplesForward.lookup(source);
67 return bucket == null ? 0 : bucket.getCount(target);
68 }
69
70 /**
71 * Returns true if the tc relation did not contain previously such a tuple that is defined by (source,target), false
72 * otherwise (in this case count is incremented with the given count parameter).
73 *
74 * @param source
75 * the source of the tuple
76 * @param target
77 * the target of the tuple
78 * @param count
79 * the count of the tuple, must be positive
80 * @return true if the relation did not contain previously the tuple
81 */
82 public boolean addTuple(V source, V target, int count) {
83 if (tuplesBackward != null) {
84 tuplesBackward.addPairPositiveMultiplicity(target, source, count);
85 }
86
87 ChangeGranularity change =
88 tuplesForward.addPairPositiveMultiplicity(source, target, count);
89
90 return change != ChangeGranularity.DUPLICATE;
91 }
92
93 /**
94 * Derivation count of the tuple (source,target) is incremented or decremented.
95 * Returns true iff updated to / from zero derivation count.
96 * @since 1.7
97 */
98 public boolean updateTuple(V source, V target, boolean isInsertion) {
99 if (isInsertion) {
100 if (tuplesBackward != null) {
101 tuplesBackward.addPair(target, source);
102 }
103 ChangeGranularity change =
104 tuplesForward.addPair(source, target);
105 return change != ChangeGranularity.DUPLICATE;
106 } else {
107 if (tuplesBackward != null) {
108 tuplesBackward.removePair(target, source);
109 }
110 ChangeGranularity change =
111 tuplesForward.removePair(source, target);
112 return change != ChangeGranularity.DUPLICATE;
113 }
114 }
115
116 public void deleteTupleEnd(V deleted) {
117 Set<V> sourcesToDelete = CollectionsFactory.createSet();
118 Set<V> targetsToDelete = CollectionsFactory.createSet();
119
120 for (V target : tuplesForward.lookupOrEmpty(deleted).distinctValues()) {
121 targetsToDelete.add(target);
122 }
123 if (tuplesBackward != null) {
124 for (V source : tuplesBackward.lookupOrEmpty(deleted).distinctValues()) {
125 sourcesToDelete.add(source);
126 }
127 } else {
128 for (V sourceCandidate : tuplesForward.distinctKeys()) {
129 if (tuplesForward.lookupOrEmpty(sourceCandidate).containsNonZero(deleted))
130 sourcesToDelete.add(sourceCandidate);
131 }
132 }
133
134 for (V source : sourcesToDelete) {
135 int count = tuplesForward.lookupOrEmpty(source).getCount(deleted);
136 for (int i=0; i< count; ++i) tuplesForward.removePair(source, deleted);
137 }
138 for (V target : targetsToDelete) {
139 int count = tuplesForward.lookupOrEmpty(deleted).getCount(target);
140 for (int i=0; i< count; ++i) tuplesForward.removePair(deleted, target);
141 }
142
143 if (tuplesBackward != null) {
144 for (V source : sourcesToDelete) {
145 int count = tuplesBackward.lookupOrEmpty(deleted).getCount(source);
146 for (int i=0; i< count; ++i) tuplesBackward.removePair(deleted, source);
147 }
148 for (V target : targetsToDelete) {
149 int count = tuplesBackward.lookupOrEmpty(target).getCount(deleted);
150 for (int i=0; i< count; ++i) tuplesBackward.removePair(target, deleted);
151 }
152 }
153 }
154
155 @Override
156 public String toString() {
157 StringBuilder sb = new StringBuilder("TcRelation = ");
158
159 for (V source : tuplesForward.distinctKeys()) {
160 IMemoryView<V> targets = tuplesForward.lookup(source);
161 for (V target : targets.distinctValues()) {
162 sb.append("{(" + source + "," + target + ")," + targets.getCount(target) + "} ");
163 }
164 }
165
166 return sb.toString();
167 }
168
169 @Override
170 public Set<V> getTupleEnds(V source) {
171 IMemoryView<V> tupEnds = tuplesForward.lookup(source);
172 if (tupEnds == null)
173 return null;
174 return tupEnds.distinctValues();
175 }
176
177 /**
178 * Returns the set of nodes from which the target node is reachable, if already computed.
179 *
180 * @param target
181 * the target node
182 * @return the set of source nodes
183 * @throws UnsupportedOperationException if backwards index not computed
184 */
185 public Set<V> getTupleStarts(V target) {
186 if (tuplesBackward != null) {
187 IMemoryView<V> tupStarts = tuplesBackward.lookup(target);
188 if (tupStarts == null)
189 return null;
190 return tupStarts.distinctValues();
191 } else {
192 throw new UnsupportedOperationException("built without backward indexing");
193 }
194 }
195
196 @Override
197 public Set<V> getTupleStarts() {
198 Set<V> nodes = CollectionsFactory.createSet();
199 for (V s : tuplesForward.distinctKeys()) {
200 nodes.add(s);
201 }
202 return nodes;
203 }
204
205 /**
206 * Returns true if a (source, target) node is present in the transitive closure relation, false otherwise.
207 *
208 * @param source
209 * the source node
210 * @param target
211 * the target node
212 * @return true if tuple is present, false otherwise
213 */
214 public boolean containsTuple(V source, V target) {
215 return tuplesForward.lookupOrEmpty(source).containsNonZero(target);
216 }
217
218 @SuppressWarnings("unchecked")
219 @Override
220 public boolean equals(Object obj) {
221 if (this == obj) {
222 return true;
223 } else if (obj == null || this.getClass() != obj.getClass()) {
224 return false;
225 } else {
226 CountingTcRelation<V> aTR = (CountingTcRelation<V>) obj;
227
228 return tuplesForward.equals(aTR.tuplesForward);
229 }
230 }
231
232 @Override
233 public int hashCode() {
234 return tuplesForward.hashCode();
235 }
236
237 public static <V> CountingTcRelation<V> createFrom(IBiDirectionalGraphDataSource<V> gds) {
238 List<V> topologicalSorting = TopologicalSorting.compute(gds);
239 CountingTcRelation<V> tc = new CountingTcRelation<V>(true);
240 Collections.reverse(topologicalSorting);
241 for (V n : topologicalSorting) {
242 IMemoryView<V> sourceNodes = gds.getSourceNodes(n);
243 Set<V> tupEnds = tc.getTupleEnds(n);
244 for (V s : sourceNodes.distinctValues()) {
245 int count = sourceNodes.getCount(s);
246 for (int i = 0; i < count; i++) {
247 tc.updateTuple(s, n, true);
248 if (tupEnds != null) {
249 for (V t : tupEnds) {
250 tc.updateTuple(s, t, true);
251 }
252 }
253 }
254 }
255 }
256
257 return tc;
258 }
259}