| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 * | 105 * |
| 106 * @param key the token being mapped to the value | 106 * @param key the token being mapped to the value |
| 107 * @param value the token to which the key will be mapped | 107 * @param value the token to which the key will be mapped |
| 108 */ | 108 */ |
| 109 void put(Token key, Token value) { | 109 void put(Token key, Token value) { |
| 110 _map[key] = value; | 110 _map[key] = value; |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 /** | 114 /** |
| 115 * Instances of the class `DirectedGraph` implement a directed graph in which th
e nodes are |
| 116 * arbitrary (client provided) objects and edges are represented implicitly. The
graph will allow an |
| 117 * edge from any node to any other node, including itself, but will not represen
t multiple edges |
| 118 * between the same pair of nodes. |
| 119 * |
| 120 * @param N the type of the nodes in the graph |
| 121 */ |
| 122 class DirectedGraph<N> { |
| 123 /** |
| 124 * The table encoding the edges in the graph. An edge is represented by an ent
ry mapping the head |
| 125 * to a set of tails. Nodes that are not the head of any edge are represented
by an entry mapping |
| 126 * the node to an empty set of tails. |
| 127 */ |
| 128 Map<N, Set<N>> _edges = new Map<N, Set<N>>(); |
| 129 |
| 130 /** |
| 131 * Add an edge from the given head node to the given tail node. Both nodes wil
l be a part of the |
| 132 * graph after this method is invoked, whether or not they were before. |
| 133 * |
| 134 * @param head the node at the head of the edge |
| 135 * @param tail the node at the tail of the edge |
| 136 */ |
| 137 void addEdge(N head, N tail) { |
| 138 // |
| 139 // First, ensure that the tail is a node known to the graph. |
| 140 // |
| 141 if (_edges[tail] == null) { |
| 142 _edges[tail] = new Set<N>(); |
| 143 } |
| 144 // |
| 145 // Then create the edge. |
| 146 // |
| 147 Set<N> tails = _edges[head]; |
| 148 if (tails == null) { |
| 149 tails = new Set<N>(); |
| 150 _edges[head] = tails; |
| 151 } |
| 152 tails.add(tail); |
| 153 } |
| 154 |
| 155 /** |
| 156 * Add the given node to the set of nodes in the graph. |
| 157 * |
| 158 * @param node the node to be added |
| 159 */ |
| 160 void addNode(N node) { |
| 161 Set<N> tails = _edges[node]; |
| 162 if (tails == null) { |
| 163 _edges[node] = new Set<N>(); |
| 164 } |
| 165 } |
| 166 |
| 167 /** |
| 168 * Return a list of nodes that form a cycle, or `null` if there are no cycles
in this graph. |
| 169 * |
| 170 * @return a list of nodes that form a cycle |
| 171 */ |
| 172 List<N> findCycle() => null; |
| 173 |
| 174 /** |
| 175 * Return a list of nodes that form a cycle containing the given node. If the
node is not part of |
| 176 * this graph, then a list containing only the node itself will be returned. |
| 177 * |
| 178 * @return a list of nodes that form a cycle containing the given node |
| 179 */ |
| 180 List<N> findCycleContaining(N node) { |
| 181 if (node == null) { |
| 182 throw new IllegalArgumentException(); |
| 183 } |
| 184 DirectedGraph_SccFinder<N> finder = new DirectedGraph_SccFinder<N>(this); |
| 185 return finder.componentContaining(node); |
| 186 } |
| 187 |
| 188 /** |
| 189 * Return the number of nodes in this graph. |
| 190 * |
| 191 * @return the number of nodes in this graph |
| 192 */ |
| 193 int get nodeCount => _edges.length; |
| 194 |
| 195 /** |
| 196 * Return a set containing the tails of edges that have the given node as thei
r head. The set will |
| 197 * be empty if there are no such edges or if the node is not part of the graph
. Clients must not |
| 198 * modify the returned set. |
| 199 * |
| 200 * @param head the node at the head of all of the edges whose tails are to be
returned |
| 201 * @return a set containing the tails of edges that have the given node as the
ir head |
| 202 */ |
| 203 Set<N> getTails(N head) { |
| 204 Set<N> tails = _edges[head]; |
| 205 if (tails == null) { |
| 206 return new Set<N>(); |
| 207 } |
| 208 return tails; |
| 209 } |
| 210 |
| 211 /** |
| 212 * Return `true` if this graph is empty. |
| 213 * |
| 214 * @return `true` if this graph is empty |
| 215 */ |
| 216 bool get isEmpty => _edges.isEmpty; |
| 217 |
| 218 /** |
| 219 * Remove all of the given nodes from this graph. As a consequence, any edges
for which those |
| 220 * nodes were either a head or a tail will also be removed. |
| 221 * |
| 222 * @param nodes the nodes to be removed |
| 223 */ |
| 224 void removeAllNodes(List<N> nodes) { |
| 225 for (N node in nodes) { |
| 226 removeNode(node); |
| 227 } |
| 228 } |
| 229 |
| 230 /** |
| 231 * Remove the edge from the given head node to the given tail node. If there w
as no such edge then |
| 232 * the graph will be unmodified: the number of edges will be the same and the
set of nodes will be |
| 233 * the same (neither node will either be added or removed). |
| 234 * |
| 235 * @param head the node at the head of the edge |
| 236 * @param tail the node at the tail of the edge |
| 237 * @return `true` if the graph was modified as a result of this operation |
| 238 */ |
| 239 void removeEdge(N head, N tail) { |
| 240 Set<N> tails = _edges[head]; |
| 241 if (tails != null) { |
| 242 tails.remove(tail); |
| 243 } |
| 244 } |
| 245 |
| 246 /** |
| 247 * Remove the given node from this graph. As a consequence, any edges for whic
h that node was |
| 248 * either a head or a tail will also be removed. |
| 249 * |
| 250 * @param node the node to be removed |
| 251 */ |
| 252 void removeNode(N node) { |
| 253 _edges.remove(node); |
| 254 for (Set<N> tails in _edges.values) { |
| 255 tails.remove(node); |
| 256 } |
| 257 } |
| 258 |
| 259 /** |
| 260 * Find one node (referred to as a sink node) that has no outgoing edges (that
is, for which there |
| 261 * are no edges that have that node as the head of the edge) and remove it fro
m this graph. Return |
| 262 * the node that was removed, or `null` if there are no such nodes either beca
use the graph |
| 263 * is empty or because every node in the graph has at least one outgoing edge.
As a consequence of |
| 264 * removing the node from the graph any edges for which that node was a tail w
ill also be removed. |
| 265 * |
| 266 * @return the sink node that was removed |
| 267 */ |
| 268 N removeSink() { |
| 269 N sink = _findSink(); |
| 270 if (sink == null) { |
| 271 return null; |
| 272 } |
| 273 removeNode(sink); |
| 274 return sink; |
| 275 } |
| 276 |
| 277 /** |
| 278 * Return one node that has no outgoing edges (that is, for which there are no
edges that have |
| 279 * that node as the head of the edge), or `null` if there are no such nodes. |
| 280 * |
| 281 * @return a sink node |
| 282 */ |
| 283 N _findSink() { |
| 284 for (N key in _edges.keys) { |
| 285 if (_edges[key].isEmpty) return key; |
| 286 } |
| 287 return null; |
| 288 } |
| 289 } |
| 290 |
| 291 /** |
| 292 * Instances of the class `NodeInfo` are used by the [SccFinder] to maintain |
| 293 * information about the nodes that have been examined. |
| 294 * |
| 295 * @param N the type of the nodes corresponding to the entries |
| 296 */ |
| 297 class DirectedGraph_NodeInfo<N> { |
| 298 /** |
| 299 * The depth of this node. |
| 300 */ |
| 301 int index = 0; |
| 302 |
| 303 /** |
| 304 * The depth of the first node in a cycle. |
| 305 */ |
| 306 int lowlink = 0; |
| 307 |
| 308 /** |
| 309 * A flag indicating whether the corresponding node is on the stack. Used to r
emove the need for |
| 310 * searching a collection for the node each time the question needs to be aske
d. |
| 311 */ |
| 312 bool onStack = false; |
| 313 |
| 314 /** |
| 315 * The component that contains the corresponding node. |
| 316 */ |
| 317 List<N> component; |
| 318 |
| 319 /** |
| 320 * Initialize a newly created information holder to represent a node at the gi
ven depth. |
| 321 * |
| 322 * @param depth the depth of the node being represented |
| 323 */ |
| 324 DirectedGraph_NodeInfo(int depth) { |
| 325 index = depth; |
| 326 lowlink = depth; |
| 327 onStack = false; |
| 328 } |
| 329 } |
| 330 |
| 331 /** |
| 332 * Instances of the class `SccFinder` implement Tarjan's Algorithm for finding t
he strongly |
| 333 * connected components in a graph. |
| 334 */ |
| 335 class DirectedGraph_SccFinder<N> { |
| 336 /** |
| 337 * The graph to work with. |
| 338 */ |
| 339 DirectedGraph<N> _graph; |
| 340 |
| 341 /** |
| 342 * The index used to uniquely identify the depth of nodes. |
| 343 */ |
| 344 int _index = 0; |
| 345 |
| 346 /** |
| 347 * The stack of nodes that are being visited in order to identify components. |
| 348 */ |
| 349 List<N> _stack = new List<N>(); |
| 350 |
| 351 /** |
| 352 * A table mapping nodes to information about the nodes that is used by this a
lgorithm. |
| 353 */ |
| 354 Map<N, DirectedGraph_NodeInfo<N>> _nodeMap = new Map<N, DirectedGraph_NodeInfo
<N>>(); |
| 355 |
| 356 /** |
| 357 * Initialize a newly created finder. |
| 358 */ |
| 359 DirectedGraph_SccFinder(DirectedGraph<N> graph) : super() { |
| 360 this._graph = graph; |
| 361 } |
| 362 |
| 363 /** |
| 364 * Return a list containing the nodes that are part of the strongly connected
component that |
| 365 * contains the given node. |
| 366 * |
| 367 * @param node the node used to identify the strongly connected component to b
e returned |
| 368 * @return the nodes that are part of the strongly connected component that co
ntains the given |
| 369 * node |
| 370 */ |
| 371 List<N> componentContaining(N node) => _strongConnect(node).component; |
| 372 |
| 373 /** |
| 374 * Remove and return the top-most element from the stack. |
| 375 * |
| 376 * @return the element that was removed |
| 377 */ |
| 378 N _pop() { |
| 379 N node = _stack.removeAt(_stack.length - 1); |
| 380 _nodeMap[node].onStack = false; |
| 381 return node; |
| 382 } |
| 383 |
| 384 /** |
| 385 * Add the given node to the stack. |
| 386 * |
| 387 * @param node the node to be added to the stack |
| 388 */ |
| 389 void _push(N node) { |
| 390 _nodeMap[node].onStack = true; |
| 391 _stack.add(node); |
| 392 } |
| 393 |
| 394 /** |
| 395 * Compute the strongly connected component that contains the given node as we
ll as any |
| 396 * components containing nodes that are reachable from the given component. |
| 397 * |
| 398 * @param v the node from which the search will begin |
| 399 * @return the information about the given node |
| 400 */ |
| 401 DirectedGraph_NodeInfo<N> _strongConnect(N v) { |
| 402 // |
| 403 // Set the depth index for v to the smallest unused index |
| 404 // |
| 405 DirectedGraph_NodeInfo<N> vInfo = new DirectedGraph_NodeInfo<N>(_index++); |
| 406 _nodeMap[v] = vInfo; |
| 407 _push(v); |
| 408 // |
| 409 // Consider successors of v |
| 410 // |
| 411 Set<N> tails = _graph._edges[v]; |
| 412 if (tails != null) { |
| 413 for (N w in tails) { |
| 414 DirectedGraph_NodeInfo<N> wInfo = _nodeMap[w]; |
| 415 if (wInfo == null) { |
| 416 // Successor w has not yet been visited; recurse on it |
| 417 wInfo = _strongConnect(w); |
| 418 vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.lowlink); |
| 419 } else if (wInfo.onStack) { |
| 420 // Successor w is in stack S and hence in the current SCC |
| 421 vInfo.lowlink = Math.min(vInfo.lowlink, wInfo.index); |
| 422 } |
| 423 } |
| 424 } |
| 425 // |
| 426 // If v is a root node, pop the stack and generate an SCC |
| 427 // |
| 428 if (vInfo.lowlink == vInfo.index) { |
| 429 List<N> component = new List<N>(); |
| 430 N w; |
| 431 do { |
| 432 w = _pop(); |
| 433 component.add(w); |
| 434 _nodeMap[w].component = component; |
| 435 } while (w != v); |
| 436 } |
| 437 return vInfo; |
| 438 } |
| 439 } |
| 440 |
| 441 /** |
| 115 * The class `ListUtilities` defines utility methods useful for working with [Li
st | 442 * The class `ListUtilities` defines utility methods useful for working with [Li
st |
| 116 ]. | 443 ]. |
| 117 */ | 444 */ |
| 118 class ListUtilities { | 445 class ListUtilities { |
| 119 /** | 446 /** |
| 120 * Add all of the elements in the given array to the given list. | 447 * Add all of the elements in the given array to the given list. |
| 121 * | 448 * |
| 122 * @param list the list to which the elements are to be added | 449 * @param list the list to which the elements are to be added |
| 123 * @param elements the elements to be added to the list | 450 * @param elements the elements to be added to the list |
| 124 */ | 451 */ |
| 125 static void addAll(List list, List<Object> elements) { | 452 static void addAll(List list, List<Object> elements) { |
| 126 int count = elements.length; | 453 int count = elements.length; |
| 127 for (int i = 0; i < count; i++) { | 454 for (int i = 0; i < count; i++) { |
| 128 list.add(elements[i]); | 455 list.add(elements[i]); |
| 129 } | 456 } |
| 130 } | 457 } |
| 131 } | 458 } |
| OLD | NEW |