OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // This code was auto-generated, is not intended to be edited, and is subject to | 5 // This code was auto-generated, is not intended to be edited, and is subject to |
6 // significant change. Please see the README file for more information. | 6 // significant change. Please see the README file for more information. |
7 | 7 |
8 library engine.utilities.collection; | 8 library engine.utilities.collection; |
9 | 9 |
10 import 'java_core.dart'; | 10 import 'java_core.dart'; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 * @param node the node to be added | 127 * @param node the node to be added |
128 */ | 128 */ |
129 void addNode(N node) { | 129 void addNode(N node) { |
130 Set<N> tails = _edges[node]; | 130 Set<N> tails = _edges[node]; |
131 if (tails == null) { | 131 if (tails == null) { |
132 _edges[node] = new Set<N>(); | 132 _edges[node] = new Set<N>(); |
133 } | 133 } |
134 } | 134 } |
135 | 135 |
136 /** | 136 /** |
137 * Return a list of nodes that form a cycle, or `null` if there are no cycles
in this graph. | 137 * Run a topological sort of the graph. Since the graph may contain cycles, th
is results in a list |
138 * | 138 * of strongly connected components rather than a list of nodes. The nodes in
each strongly |
139 * @return a list of nodes that form a cycle | 139 * connected components only have edges that point to nodes in the same compon
ent or earlier |
| 140 * components. |
140 */ | 141 */ |
141 List<N> findCycle() => null; | 142 List<List<N>> computeTopologicalSort() { |
| 143 DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this); |
| 144 return finder.computeTopologicalSort(); |
| 145 } |
| 146 |
| 147 /** |
| 148 * Return true if the graph contains at least one path from `source` to `desti
nation`. |
| 149 */ |
| 150 bool containsPath(N source, N destination) { |
| 151 Set<N> nodesVisited = new Set<N>(); |
| 152 return _containsPathInternal(source, destination, nodesVisited); |
| 153 } |
142 | 154 |
143 /** | 155 /** |
144 * Return a list of nodes that form a cycle containing the given node. If the
node is not part of | 156 * Return a list of nodes that form a cycle containing the given node. If the
node is not part of |
145 * this graph, then a list containing only the node itself will be returned. | 157 * this graph, then a list containing only the node itself will be returned. |
146 * | 158 * |
147 * @return a list of nodes that form a cycle containing the given node | 159 * @return a list of nodes that form a cycle containing the given node |
148 */ | 160 */ |
149 List<N> findCycleContaining(N node) { | 161 List<N> findCycleContaining(N node) { |
150 if (node == null) { | 162 if (node == null) { |
151 throw new IllegalArgumentException(); | 163 throw new IllegalArgumentException(); |
152 } | 164 } |
153 DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this); | 165 DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this); |
154 return finder.componentContaining(node); | 166 return finder.componentContaining(node); |
155 } | 167 } |
156 | 168 |
157 /** | 169 /** |
158 * Return the number of nodes in this graph. | 170 * Return the number of nodes in this graph. |
159 * | 171 * |
160 * @return the number of nodes in this graph | 172 * @return the number of nodes in this graph |
161 */ | 173 */ |
162 int get nodeCount => _edges.length; | 174 int get nodeCount => _edges.length; |
163 | 175 |
164 /** | 176 /** |
| 177 * Return a set of all nodes in the graph. |
| 178 */ |
| 179 Set<N> get nodes => _edges.keys.toSet(); |
| 180 |
| 181 /** |
165 * Return a set containing the tails of edges that have the given node as thei
r head. The set will | 182 * Return a set containing the tails of edges that have the given node as thei
r head. The set will |
166 * be empty if there are no such edges or if the node is not part of the graph
. Clients must not | 183 * be empty if there are no such edges or if the node is not part of the graph
. Clients must not |
167 * modify the returned set. | 184 * modify the returned set. |
168 * | 185 * |
169 * @param head the node at the head of all of the edges whose tails are to be
returned | 186 * @param head the node at the head of all of the edges whose tails are to be
returned |
170 * @return a set containing the tails of edges that have the given node as the
ir head | 187 * @return a set containing the tails of edges that have the given node as the
ir head |
171 */ | 188 */ |
172 Set<N> getTails(N head) { | 189 Set<N> getTails(N head) { |
173 Set<N> tails = _edges[head]; | 190 Set<N> tails = _edges[head]; |
174 if (tails == null) { | 191 if (tails == null) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 */ | 253 */ |
237 N removeSink() { | 254 N removeSink() { |
238 N sink = _findSink(); | 255 N sink = _findSink(); |
239 if (sink == null) { | 256 if (sink == null) { |
240 return null; | 257 return null; |
241 } | 258 } |
242 removeNode(sink); | 259 removeNode(sink); |
243 return sink; | 260 return sink; |
244 } | 261 } |
245 | 262 |
| 263 bool _containsPathInternal(N source, N destination, Set<N> nodesVisited) { |
| 264 if (identical(source, destination)) { |
| 265 return true; |
| 266 } |
| 267 Set<N> tails = _edges[source]; |
| 268 if (tails != null) { |
| 269 nodesVisited.add(source); |
| 270 for (N tail in tails) { |
| 271 if (!nodesVisited.contains(tail)) { |
| 272 if (_containsPathInternal(tail, destination, nodesVisited)) { |
| 273 return true; |
| 274 } |
| 275 } |
| 276 } |
| 277 } |
| 278 return false; |
| 279 } |
| 280 |
246 /** | 281 /** |
247 * Return one node that has no outgoing edges (that is, for which there are no
edges that have | 282 * Return one node that has no outgoing edges (that is, for which there are no
edges that have |
248 * that node as the head of the edge), or `null` if there are no such nodes. | 283 * that node as the head of the edge), or `null` if there are no such nodes. |
249 * | 284 * |
250 * @return a sink node | 285 * @return a sink node |
251 */ | 286 */ |
252 N _findSink() { | 287 N _findSink() { |
253 for (N key in _edges.keys) { | 288 for (N key in _edges.keys) { |
254 if (_edges[key].isEmpty) return key; | 289 if (_edges[key].isEmpty) return key; |
255 } | 290 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 * The stack of nodes that are being visited in order to identify components. | 351 * The stack of nodes that are being visited in order to identify components. |
317 */ | 352 */ |
318 List<N> _stack = new List<N>(); | 353 List<N> _stack = new List<N>(); |
319 | 354 |
320 /** | 355 /** |
321 * A table mapping nodes to information about the nodes that is used by this a
lgorithm. | 356 * A table mapping nodes to information about the nodes that is used by this a
lgorithm. |
322 */ | 357 */ |
323 Map<N, DirectedGraph_NodeInfo<N>> _nodeMap = new Map<N, DirectedGraph_NodeInfo
<N>>(); | 358 Map<N, DirectedGraph_NodeInfo<N>> _nodeMap = new Map<N, DirectedGraph_NodeInfo
<N>>(); |
324 | 359 |
325 /** | 360 /** |
| 361 * A list of all strongly connected components found, in topological sort orde
r (each node in a |
| 362 * strongly connected component only has edges that point to nodes in the same
component or |
| 363 * earlier components). |
| 364 */ |
| 365 List<List<N>> _allComponents = new List<List<N>>(); |
| 366 |
| 367 /** |
326 * Initialize a newly created finder. | 368 * Initialize a newly created finder. |
327 */ | 369 */ |
328 DirectedGraph_SccFinder(this._graph) : super(); | 370 DirectedGraph_SccFinder(this._graph) : super(); |
329 | 371 |
330 /** | 372 /** |
331 * Return a list containing the nodes that are part of the strongly connected
component that | 373 * Return a list containing the nodes that are part of the strongly connected
component that |
332 * contains the given node. | 374 * contains the given node. |
333 * | 375 * |
334 * @param node the node used to identify the strongly connected component to b
e returned | 376 * @param node the node used to identify the strongly connected component to b
e returned |
335 * @return the nodes that are part of the strongly connected component that co
ntains the given | 377 * @return the nodes that are part of the strongly connected component that co
ntains the given |
336 * node | 378 * node |
337 */ | 379 */ |
338 List<N> componentContaining(N node) => _strongConnect(node).component; | 380 List<N> componentContaining(N node) => _strongConnect(node).component; |
339 | 381 |
340 /** | 382 /** |
| 383 * Run Tarjan's algorithm and return the resulting list of strongly connected
components. The |
| 384 * list is in topological sort order (each node in a strongly connected compon
ent only has edges |
| 385 * that point to nodes in the same component or earlier components). |
| 386 */ |
| 387 List<List<N>> computeTopologicalSort() { |
| 388 for (N node in _graph._edges.keys.toSet()) { |
| 389 DirectedGraph_NodeInfo<N> nodeInfo = _nodeMap[node]; |
| 390 if (nodeInfo == null) { |
| 391 _strongConnect(node); |
| 392 } |
| 393 } |
| 394 return _allComponents; |
| 395 } |
| 396 |
| 397 /** |
341 * Remove and return the top-most element from the stack. | 398 * Remove and return the top-most element from the stack. |
342 * | 399 * |
343 * @return the element that was removed | 400 * @return the element that was removed |
344 */ | 401 */ |
345 N _pop() { | 402 N _pop() { |
346 N node = _stack.removeAt(_stack.length - 1); | 403 N node = _stack.removeAt(_stack.length - 1); |
347 _nodeMap[node].onStack = false; | 404 _nodeMap[node].onStack = false; |
348 return node; | 405 return node; |
349 } | 406 } |
350 | 407 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 // If v is a root node, pop the stack and generate an SCC | 450 // If v is a root node, pop the stack and generate an SCC |
394 // | 451 // |
395 if (vInfo.lowlink == vInfo.index) { | 452 if (vInfo.lowlink == vInfo.index) { |
396 List<N> component = new List<N>(); | 453 List<N> component = new List<N>(); |
397 N w; | 454 N w; |
398 do { | 455 do { |
399 w = _pop(); | 456 w = _pop(); |
400 component.add(w); | 457 component.add(w); |
401 _nodeMap[w].component = component; | 458 _nodeMap[w].component = component; |
402 } while (!identical(w, v)); | 459 } while (!identical(w, v)); |
| 460 _allComponents.add(component); |
403 } | 461 } |
404 return vInfo; | 462 return vInfo; |
405 } | 463 } |
406 } | 464 } |
407 | 465 |
408 /** | 466 /** |
409 * The class `ListUtilities` defines utility methods useful for working with [Li
st | 467 * The class `ListUtilities` defines utility methods useful for working with [Li
st |
410 ]. | 468 ]. |
411 */ | 469 */ |
412 class ListUtilities { | 470 class ListUtilities { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 | 729 |
672 @override | 730 @override |
673 void set value(V newValue) { | 731 void set value(V newValue) { |
674 if (_currentKey == null) { | 732 if (_currentKey == null) { |
675 throw new NoSuchElementException(); | 733 throw new NoSuchElementException(); |
676 } | 734 } |
677 _currentValue = newValue; | 735 _currentValue = newValue; |
678 _map[_currentKey] = newValue; | 736 _map[_currentKey] = newValue; |
679 } | 737 } |
680 } | 738 } |
OLD | NEW |