lib: rename graphs to graph
[nit.git] / lib / graph / digraph.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2015 Alexandre Blondin Massé <blondin_masse.alexandre@uqam.ca>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Implementation of directed graphs, also called digraphs.
18 #
19 # Overview
20 # ========
21 #
22 # This module provides a simple interface together with a concrete
23 # implementation of directed graphs (or digraphs).
24 #
25 # The upper level interface is `Digraph` and contains all methods for digraphs
26 # that do not depend on the underlying data structure. More precisely, if basic
27 # operations such as `predecessors`, `successors`, `num_vertices`, etc. are
28 # implemented, then high level operations (such as computing the connected
29 # components or a shortest path between two vertices) can be easily derived.
30 # Also, all methods found in `Digraph` do no modify the graph. For mutable
31 # methods, one needs to check the `MutableDigraph` child class. Vertices can be
32 # any `Object`, but there is no information stored in the arcs, which are
33 # simple arrays of the form `[u,v]`, where `u` is the source of the arc and `v`
34 # is the target.
35 #
36 # There is currently only one concrete implementation named `HashDigraph` that
37 # makes use of the HashMap class for storing the predecessors and successors.
38 # It is therefore simple to provide another implementation: One only has to
39 # create a concrete specialization of either `Digraph` or `MutableDigraph`.
40 #
41 # Basic methods
42 # =============
43 #
44 # To create an (empty) new graph whose keys are integers, one simply type
45 # ~~~
46 # import digraph
47 # var g = new HashDigraph[Int]
48 # ~~~
49 #
50 # Then we can add vertices and arcs. Note that if an arc is added whose source
51 # and target are not already in the digraph, the vertices are added beforehand.
52 # ~~~
53 # import digraph
54 # var g = new HashDigraph[Int]
55 # g.add_vertex(0)
56 # g.add_vertex(1)
57 # g.add_arc(0,1)
58 # g.add_arc(1,2)
59 # assert g.to_s == "Digraph of 3 vertices and 2 arcs"
60 # ~~~
61 #
62 # One might also create digraphs with strings in vertices, for instance to
63 # represent some directed relation. However, it is currently not possible to
64 # store values in the arcs.
65 # ~~~
66 # import digraph
67 # var g = new HashDigraph[String]
68 # g.add_vertex("Amy")
69 # g.add_vertex("Bill")
70 # g.add_vertex("Chris")
71 # g.add_vertex("Diane")
72 # g.add_arc("Amy", "Bill") # Amy likes Bill
73 # g.add_arc("Bill", "Amy") # Bill likes Amy
74 # g.add_arc("Chris", "Diane") # and so on
75 # g.add_arc("Diane", "Amy") # and so on
76 # ~~~
77 #
78 # `HashDigraph`s are mutable, i.e. one might remove arcs and/or vertices:
79 # ~~~
80 # import digraph
81 # var g = new HashDigraph[Int]
82 # g.add_arc(0,1)
83 # g.add_arc(0,2)
84 # g.add_arc(1,2)
85 # g.add_arc(2,3)
86 # g.add_arc(2,4)
87 # g.remove_vertex(1)
88 # g.remove_arc(2, 4)
89 # assert g.to_s == "Digraph of 4 vertices and 2 arcs"
90 # ~~~
91 #
92 # If one has installed [Graphviz](http://graphviz.org), it is easy to produce a
93 # *dot* file which Graphviz process into a picture:
94 # ~~~
95 # import digraph
96 # var g = new HashDigraph[Int]
97 # g.add_arcs([[0,1],[0,2],[1,2],[2,3],[2,4]])
98 # print g.to_dot
99 # # Then call "dot -Tpng -o graph.png"
100 # ~~~
101 #
102 # ![A graph drawing produced by Graphviz](https://github.com/nitlang/nit/blob/master/lib/graph.png)
103 #
104 # Other methods
105 # =============
106 #
107 # There exist other methods available for digraphs and many other will be
108 # implemented in the future. For more details, one should look at the methods
109 # directly. For instance, the [strongly connected components]
110 # (https://en.wikipedia.org/wiki/Strongly_connected_component) of a digraph are
111 # returned as a [disjoint set data structure]
112 # (https://en.wikipedia.org/wiki/Disjoint-set_data_structure) (i.e. a set of
113 # sets):
114 # ~~~
115 # import digraph
116 # var g = new HashDigraph[Int]
117 # g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
118 # for component in g.strongly_connected_components.to_partitions
119 # do
120 # print component
121 # end
122 # # Prints [1,2] and [3,4,5]
123 # ~~~
124 #
125 # It is also possible to compute a shortest (directed) path between two
126 # vertices:
127 # ~~~
128 # import digraph
129 # var g = new HashDigraph[Int]
130 # g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
131 # var path = g.a_shortest_path(2, 4)
132 # if path != null then print path else print "No path"
133 # # Prints [2,3,4]
134 # path = g.a_shortest_path(4, 2)
135 # if path != null then print path else print "No path"
136 # # Prints "No path"
137 # ~~~
138 #
139 # Extending the library
140 # =====================
141 #
142 # There are at least two ways of providing new methods on digraphs. If the
143 # method is standard and could be useful to other users, you should consider
144 # including your implementation directly in this library.
145 #
146 # Otherwise, for personal use, you should simply define a new class inheriting
147 # from `HashDigraph` and add the new services.
148 module digraph
149
150 # Interface for digraphs
151 interface Digraph[V: Object]
152
153 ## ---------------- ##
154 ## Abstract methods ##
155 ## ---------------- ##
156
157 # The number of vertices in this graph.
158 #
159 # ~~~
160 # import digraph
161 # var g = new HashDigraph[Int]
162 # g.add_vertex(0)
163 # g.add_vertex(1)
164 # assert g.num_vertices == 2
165 # g.add_vertex(0)
166 # assert g.num_vertices == 2
167 # ~~~
168 fun num_vertices: Int is abstract
169
170 # The number of arcs in this graph.
171 #
172 # ~~~
173 # import digraph
174 # var g = new HashDigraph[Int]
175 # g.add_arc(0, 1)
176 # assert g.num_arcs == 1
177 # g.add_arc(0, 1)
178 # assert g.num_arcs == 1
179 # g.add_arc(2, 3)
180 # assert g.num_arcs == 2
181 # ~~~
182 fun num_arcs: Int is abstract
183
184 # Returns true if and only if `u` exists in this graph.
185 #
186 # ~~~
187 # import digraph
188 # var g = new HashDigraph[Int]
189 # g.add_vertex(1)
190 # assert g.has_vertex(1)
191 # assert not g.has_vertex(0)
192 # g.add_vertex(1)
193 # assert g.has_vertex(1)
194 # assert not g.has_vertex(0)
195 # ~~~
196 fun has_vertex(u: V): Bool is abstract
197
198 # Returns true if and only if `(u,v)` is an arc in this graph.
199 #
200 # ~~~
201 # import digraph
202 # var g = new HashDigraph[Int]
203 # g.add_arc(0, 1)
204 # g.add_arc(1, 2)
205 # assert g.has_arc(0, 1)
206 # assert g.has_arc(1, 2)
207 # assert not g.has_arc(0, 2)
208 # ~~~
209 fun has_arc(u, v: V): Bool is abstract
210
211 # Returns the predecessors of `u`.
212 #
213 # If `u` does not exist, then it returns null.
214 #
215 # ~~~
216 # import digraph
217 # var g = new HashDigraph[Int]
218 # g.add_arc(0, 1)
219 # g.add_arc(1, 2)
220 # g.add_arc(0, 2)
221 # assert g.predecessors(2).has(0)
222 # assert g.predecessors(2).has(1)
223 # assert not g.predecessors(2).has(2)
224 # ~~~
225 fun predecessors(u: V): Collection[V] is abstract
226
227 # Returns the successors of `u`.
228 #
229 # If `u` does not exist, then an empty collection is returned.
230 #
231 # ~~~
232 # import digraph
233 # var g = new HashDigraph[Int]
234 # g.add_arc(0, 1)
235 # g.add_arc(1, 2)
236 # g.add_arc(0, 2)
237 # assert not g.successors(0).has(0)
238 # assert g.successors(0).has(1)
239 # assert g.successors(0).has(2)
240 # ~~~
241 fun successors(u: V): Collection[V] is abstract
242
243 # Returns an iterator over the vertices of this graph.
244 #
245 # ~~~
246 # import digraph
247 # var g = new HashDigraph[Int]
248 # g.add_arc(0, 1)
249 # g.add_arc(0, 2)
250 # g.add_arc(1, 2)
251 # var vs = new HashSet[Int]
252 # for v in g.vertices_iterator do vs.add(v)
253 # assert vs == new HashSet[Int].from([0,1,2])
254 # ~~~
255 fun vertices_iterator: Iterator[V] is abstract
256
257 ## -------------------- ##
258 ## Non abstract methods ##
259 ## -------------------- ##
260
261 ## ------------- ##
262 ## Basic methods ##
263 ## ------------- ##
264
265 # Returns true if and only if this graph is empty.
266 #
267 # An empty graph is a graph without vertex and arc.
268 #
269 # ~~~
270 # import digraph
271 # assert (new HashDigraph[Int]).is_empty
272 # ~~~
273 fun is_empty: Bool do return num_vertices == 0 and num_arcs == 0
274
275 # Returns an array containing the vertices of this graph.
276 #
277 # ~~~
278 # import digraph
279 # var g = new HashDigraph[Int]
280 # g.add_vertices([0,2,4,5])
281 # assert g.vertices.length == 4
282 # ~~~
283 fun vertices: Array[V] do return [for u in vertices_iterator do u]
284
285 # Returns an iterator over the arcs of this graph
286 #
287 # ~~~
288 # import digraph
289 # var g = new HashDigraph[Int]
290 # g.add_arc(0, 1)
291 # g.add_arc(0, 2)
292 # g.add_arc(1, 2)
293 # for arc in g.arcs_iterator do
294 # assert g.has_arc(arc[0], arc[1])
295 # end
296 # ~~~
297 fun arcs_iterator: Iterator[Array[V]] do return new ArcsIterator[V](self)
298
299 # Returns the arcs of this graph.
300 #
301 # ~~~
302 # import digraph
303 # var g = new HashDigraph[Int]
304 # g.add_arc(1, 3)
305 # g.add_arc(2, 3)
306 # assert g.arcs.length == 2
307 # ~~~
308 fun arcs: Array[Array[V]] do return [for arc in arcs_iterator do arc]
309
310 # Returns the incoming arcs of vertex `u`.
311 #
312 # If `u` is not in this graph, an empty array is returned.
313 #
314 # ~~~
315 # import digraph
316 # var g = new HashDigraph[Int]
317 # g.add_arc(1, 3)
318 # g.add_arc(2, 3)
319 # for arc in g.incoming_arcs(3) do
320 # assert g.is_predecessor(arc[0], arc[1])
321 # end
322 # ~~~
323 fun incoming_arcs(u: V): Collection[Array[V]]
324 do
325 if has_vertex(u) then
326 return [for v in predecessors(u) do [v, u]]
327 else
328 return new Array[Array[V]]
329 end
330 end
331
332 # Returns the outgoing arcs of vertex `u`.
333 #
334 # If `u` is not in this graph, an empty array is returned.
335 #
336 # ~~~
337 # import digraph
338 # var g = new HashDigraph[Int]
339 # g.add_arc(1, 3)
340 # g.add_arc(2, 3)
341 # g.add_arc(1, 2)
342 # for arc in g.outgoing_arcs(1) do
343 # assert g.is_successor(arc[1], arc[0])
344 # end
345 # ~~~
346 fun outgoing_arcs(u: V): Collection[Array[V]]
347 do
348 if has_vertex(u) then
349 return [for v in successors(u) do [u, v]]
350 else
351 return new Array[Array[V]]
352 end
353 end
354
355 ## ---------------------- ##
356 ## String representations ##
357 ## ---------------------- ##
358
359 redef fun to_s
360 do
361 var vertex_word = "vertices"
362 var arc_word = "arcs"
363 if num_vertices <= 1 then vertex_word = "vertex"
364 if num_arcs <= 1 then arc_word = "arc"
365 return "Digraph of {num_vertices} {vertex_word} and {num_arcs} {arc_word}"
366 end
367
368 # Returns a GraphViz string representing this digraph.
369 fun to_dot: String
370 do
371 var s = "digraph \{\n"
372 var id_set = new HashMap[V, Int]
373 # Writing the vertices
374 for u in vertices_iterator, i in [0 .. vertices.length[ do
375 id_set[u] = i
376 s += " \"{i}\" "
377 s += "[label=\"{u.to_s.escape_to_dot}\"];\n"
378 end
379 # Writing the arcs
380 for arc in arcs do
381 s += " {id_set[arc[0]]} "
382 s += "-> {id_set[arc[1]]};"
383 end
384 s += "\}"
385 return s
386 end
387
388 # Open Graphviz with `self.to_dot`.
389 #
390 # Mainly used for debugging.
391 fun show_dot do
392 var f = new ProcessWriter("dot", "-Txlib")
393 f.write to_dot
394 f.close
395 end
396
397 ## ------------ ##
398 ## Neighborhood ##
399 ## ------------ ##
400
401 # Returns true if and only if `u` is a predecessor of `v`.
402 #
403 # ~~~
404 # import digraph
405 # var g = new HashDigraph[Int]
406 # g.add_arc(1, 3)
407 # assert g.is_predecessor(1, 3)
408 # assert not g.is_predecessor(3, 1)
409 # ~~~
410 fun is_predecessor(u, v: V): Bool do return has_arc(u, v)
411
412 # Returns true if and only if `u` is a successor of `v`.
413 #
414 # ~~~
415 # import digraph
416 # var g = new HashDigraph[Int]
417 # g.add_arc(1, 3)
418 # assert not g.is_successor(1, 3)
419 # assert g.is_successor(3, 1)
420 # ~~~
421 fun is_successor(u, v: V): Bool do return has_arc(v, u)
422
423 # Returns the number of arcs whose target is `u`.
424 #
425 # ~~~
426 # import digraph
427 # var g = new HashDigraph[Int]
428 # g.add_arc(1, 3)
429 # g.add_arc(2, 3)
430 # assert g.in_degree(3) == 2
431 # assert g.in_degree(1) == 0
432 # ~~~
433 fun in_degree(u: V): Int do return predecessors(u).length
434
435 # Returns the number of arcs whose source is `u`.
436 #
437 # ~~~
438 # import digraph
439 # var g = new HashDigraph[Int]
440 # g.add_arc(1, 2)
441 # g.add_arc(1, 3)
442 # g.add_arc(2, 3)
443 # assert g.out_degree(3) == 0
444 # assert g.out_degree(1) == 2
445 # ~~~
446 fun out_degree(u: V): Int do return successors(u).length
447
448 # ------------------ #
449 # Paths and circuits #
450 # ------------------ #
451
452 # Returns true if and only if `vertices` is a path of this digraph.
453 #
454 # ~~~
455 # import digraph
456 # var g = new HashDigraph[Int]
457 # g.add_arc(1, 2)
458 # g.add_arc(2, 3)
459 # g.add_arc(3, 4)
460 # assert g.has_path([1,2,3])
461 # assert not g.has_path([1,3,3])
462 # ~~~
463 fun has_path(vertices: SequenceRead[V]): Bool
464 do
465 for i in [0..vertices.length - 1[ do
466 if not has_arc(vertices[i], vertices[i + 1]) then return false
467 end
468 return true
469 end
470
471 # Returns true if and only if `vertices` is a circuit of this digraph.
472 #
473 # ~~~
474 # import digraph
475 # var g = new HashDigraph[Int]
476 # g.add_arc(1, 2)
477 # g.add_arc(2, 3)
478 # g.add_arc(3, 1)
479 # assert g.has_circuit([1,2,3,1])
480 # assert not g.has_circuit([1,3,2,1])
481 # ~~~
482 fun has_circuit(vertices: SequenceRead[V]): Bool
483 do
484 return vertices.is_empty or (has_path(vertices) and vertices.first == vertices.last)
485 end
486
487 # Returns a shortest path from vertex `u` to `v`.
488 #
489 # If no path exists between `u` and `v`, it returns `null`.
490 #
491 # ~~~
492 # import digraph
493 # var g = new HashDigraph[Int]
494 # g.add_arc(1, 2)
495 # g.add_arc(2, 3)
496 # g.add_arc(3, 4)
497 # assert g.a_shortest_path(1, 4).length == 4
498 # g.add_arc(1, 3)
499 # assert g.a_shortest_path(1, 4).length == 3
500 # assert g.a_shortest_path(4, 1) == null
501 # ~~~
502 fun a_shortest_path(u, v: V): nullable Sequence[V]
503 do
504 var queue = new List[V].from([u]).as_fifo
505 var pred = new HashMap[V, nullable V]
506 var visited = new HashSet[V]
507 var w: nullable V = null
508 pred[u] = null
509 while not queue.is_empty do
510 w = queue.take
511 if not visited.has(w) then
512 visited.add(w)
513 if w == v then break
514 for wp in successors(w) do
515 if not pred.keys.has(wp) then
516 queue.add(wp)
517 pred[wp] = w
518 end
519 end
520 end
521 end
522 if w != v then
523 return null
524 else
525 var path = new List[V]
526 path.add(v)
527 w = v
528 while pred[w] != null do
529 path.unshift(pred[w].as(not null))
530 w = pred[w]
531 end
532 return path
533 end
534 end
535
536 # Returns the distance between `u` and `v`
537 #
538 # If no path exists between `u` and `v`, it returns null. It is not
539 # symmetric, i.e. we may have `dist(u, v) != dist(v, u)`.
540 #
541 # ~~~
542 # import digraph
543 # var g = new HashDigraph[Int]
544 # g.add_arc(1, 2)
545 # g.add_arc(2, 3)
546 # g.add_arc(3, 4)
547 # assert g.distance(1, 4) == 3
548 # g.add_arc(1, 3)
549 # assert g.distance(1, 4) == 2
550 # assert g.distance(4, 1) == null
551 # ~~~
552 fun distance(u, v: V): nullable Int
553 do
554 var queue = new List[V].from([u]).as_fifo
555 var dist = new HashMap[V, Int]
556 var visited = new HashSet[V]
557 var w: nullable V
558 dist[u] = 0
559 while not queue.is_empty do
560 w = queue.take
561 if not visited.has(w) then
562 visited.add(w)
563 if w == v then break
564 for wp in successors(w) do
565 if not dist.keys.has(wp) then
566 queue.add(wp)
567 dist[wp] = dist[w] + 1
568 end
569 end
570 end
571 end
572 return dist.get_or_null(v)
573 end
574
575 # -------------------- #
576 # Connected components #
577 # -------------------- #
578
579 # Returns the weak connected components of this digraph.
580 #
581 # The weak connected components of a digraph are the usual
582 # connected components of its associated undirected graph,
583 # i.e. the graph obtained by replacing each arc by an edge.
584 #
585 # ~~~
586 # import digraph
587 # var g = new HashDigraph[Int]
588 # g.add_arc(1, 2)
589 # g.add_arc(2, 3)
590 # g.add_arc(4, 5)
591 # assert g.weakly_connected_components.number_of_subsets == 2
592 # ~~~
593 fun weakly_connected_components: DisjointSet[V]
594 do
595 var components = new DisjointSet[V]
596 components.add_all(vertices)
597 for arc in arcs_iterator do
598 components.union(arc[0], arc[1])
599 end
600 return components
601 end
602
603 # Returns the strongly connected components of this digraph.
604 #
605 # Two vertices `u` and `v` belong to the same strongly connected
606 # component if and only if there exists a path from `u` to `v`
607 # and there exists a path from `v` to `u`.
608 #
609 # This is computed in linear time (Tarjan's algorithm).
610 #
611 # ~~~
612 # import digraph
613 # var g = new HashDigraph[Int]
614 # g.add_arc(1, 2)
615 # g.add_arc(2, 3)
616 # g.add_arc(3, 1)
617 # g.add_arc(3, 4)
618 # g.add_arc(4, 5)
619 # g.add_arc(5, 6)
620 # g.add_arc(6, 5)
621 # assert g.strongly_connected_components.number_of_subsets == 3
622 # ~~~
623 fun strongly_connected_components: DisjointSet[V]
624 do
625 var tarjanAlgorithm = new TarjanAlgorithm[V](self)
626 return tarjanAlgorithm.strongly_connected_components
627 end
628 end
629
630 # Computing the strongly connected components using Tarjan's algorithm
631 private class TarjanAlgorithm[V: Object]
632 # The graph whose strongly connected components will be computed
633 var graph: Digraph[V]
634 # The strongly connected components computed in Tarjan's algorithm
635 var sccs = new DisjointSet[V]
636 # An index used for Tarjan's algorithm
637 var index = 0
638 # A stack used for Tarjan's algorithm
639 var stack: Queue[V] = (new Array[V]).as_lifo
640 # A map associating with each vertex its index
641 var vertex_to_index = new HashMap[V, Int]
642 # A map associating with each vertex its ancestor in Tarjan's algorithm
643 var ancestor = new HashMap[V, Int]
644 # True if and only if the vertex is in the stack
645 var in_stack = new HashSet[V]
646
647 # Returns the strongly connected components of a graph
648 fun strongly_connected_components: DisjointSet[V]
649 do
650 for u in graph.vertices_iterator do sccs.add(u)
651 for v in graph.vertices_iterator do
652 visit(v)
653 end
654 return sccs
655 end
656
657 # The recursive part of Tarjan's algorithm
658 fun visit(u: V)
659 do
660 vertex_to_index[u] = index
661 ancestor[u] = index
662 index += 1
663 stack.add(u)
664 in_stack.add(u)
665 for v in graph.successors(u) do
666 if not vertex_to_index.keys.has(v) then
667 visit(v)
668 ancestor[u] = ancestor[u].min(ancestor[v])
669 else if in_stack.has(v) then
670 ancestor[u] = ancestor[u].min(vertex_to_index[v])
671 end
672 end
673 if vertex_to_index[u] == ancestor[u] then
674 var v
675 loop
676 v = stack.take
677 in_stack.remove(v)
678 sccs.union(u, v)
679 if u == v then break
680 end
681 end
682 end
683 end
684
685 # Arcs iterator
686 class ArcsIterator[V: Object]
687 super Iterator[Array[V]]
688
689 # The graph whose arcs are iterated over
690 var graph: Digraph[V]
691 # Attributes
692 #
693 private var sources_iterator: Iterator[V] is noinit
694 private var targets_iterator: Iterator[V] is noinit
695 init
696 do
697 sources_iterator = graph.vertices_iterator
698 if sources_iterator.is_ok then
699 targets_iterator = graph.successors(sources_iterator.item).iterator
700 if not targets_iterator.is_ok then update_iterators
701 end
702 end
703
704 redef fun is_ok do return sources_iterator.is_ok and targets_iterator.is_ok
705
706 redef fun item do return [sources_iterator.item, targets_iterator.item]
707
708 redef fun next
709 do
710 targets_iterator.next
711 update_iterators
712 end
713
714 private fun update_iterators
715 do
716 while not targets_iterator.is_ok and sources_iterator.is_ok
717 do
718 sources_iterator.next
719 if sources_iterator.is_ok then
720 targets_iterator = graph.successors(sources_iterator.item).iterator
721 end
722 end
723 end
724 end
725
726 # Mutable digraph
727 abstract class MutableDigraph[V: Object]
728 super Digraph[V]
729
730 ## ---------------- ##
731 ## Abstract methods ##
732 ## ---------------- ##
733
734 # Adds the vertex `u` to this graph.
735 #
736 # If `u` already belongs to the graph, then nothing happens.
737 #
738 # ~~~
739 # import digraph
740 # var g = new HashDigraph[Int]
741 # g.add_vertex(0)
742 # assert g.has_vertex(0)
743 # assert not g.has_vertex(1)
744 # g.add_vertex(1)
745 # assert g.num_vertices == 2
746 # ~~~
747 fun add_vertex(u: V) is abstract
748
749 # Removes the vertex `u` from this graph and all its incident arcs.
750 #
751 # If the vertex does not exist in the graph, then nothing happens.
752 #
753 # ~~~
754 # import digraph
755 # var g = new HashDigraph[Int]
756 # g.add_vertex(0)
757 # g.add_vertex(1)
758 # assert g.has_vertex(0)
759 # g.remove_vertex(0)
760 # assert not g.has_vertex(0)
761 # ~~~
762 fun remove_vertex(u: V) is abstract
763
764 # Adds the arc `(u,v)` to this graph.
765 #
766 # If there is already an arc from `u` to `v` in this graph, then
767 # nothing happens. If vertex `u` or vertex `v` do not exist in the
768 # graph, they are added.
769 #
770 # ~~~
771 # import digraph
772 # var g = new HashDigraph[Int]
773 # g.add_arc(0, 1)
774 # g.add_arc(1, 2)
775 # assert g.has_arc(0, 1)
776 # assert g.has_arc(1, 2)
777 # assert not g.has_arc(1, 0)
778 # g.add_arc(1, 2)
779 # assert g.num_arcs == 2
780 # ~~~
781 fun add_arc(u, v: V) is abstract
782
783 # Removes the arc `(u,v)` from this graph.
784 #
785 # If the arc does not exist in the graph, then nothing happens.
786 #
787 # ~~~
788 # import digraph
789 # var g = new HashDigraph[Int]
790 # g.add_arc(0, 1)
791 # assert g.num_arcs == 1
792 # g.remove_arc(0, 1)
793 # assert g.num_arcs == 0
794 # g.remove_arc(0, 1)
795 # assert g.num_arcs == 0
796 # ~~~
797 fun remove_arc(u, v: V) is abstract
798
799 ## -------------------- ##
800 ## Non abstract methods ##
801 ## -------------------- ##
802
803 # Adds all vertices of `vertices` to this digraph.
804 #
805 # If vertices appear more than once, they are only added once.
806 #
807 # ~~~
808 # import digraph
809 # var g = new HashDigraph[Int]
810 # g.add_vertices([0,1,2,3])
811 # assert g.num_vertices == 4
812 # g.add_vertices([2,3,4,5])
813 # assert g.num_vertices == 6
814 # ~~~
815 fun add_vertices(vertices: Collection[V])
816 do
817 for u in vertices do add_vertex(u)
818 end
819
820 # Adds all arcs of `arcs` to this digraph.
821 #
822 # If arcs appear more than once, they are only added once.
823 #
824 # ~~~
825 # import digraph
826 # var g = new HashDigraph[Int]
827 # var arcs = [[0,1], [1,2], [1,2]]
828 # g.add_arcs(arcs)
829 # assert g.num_arcs == 2
830 # ~~~
831 fun add_arcs(arcs: Collection[Array[V]])
832 do
833 for a in arcs do add_arc(a[0], a[1])
834 end
835 end
836 # A directed graph represented by hash maps
837 class HashDigraph[V: Object]
838 super MutableDigraph[V]
839
840 # Attributes
841 #
842 private var incoming_vertices_map = new HashMap[V, Array[V]]
843 private var outgoing_vertices_map = new HashMap[V, Array[V]]
844 private var number_of_arcs = 0
845
846 redef fun num_vertices do return outgoing_vertices_map.keys.length end
847
848 redef fun num_arcs do return number_of_arcs end
849
850 redef fun add_vertex(u)
851 do
852 if not has_vertex(u) then
853 incoming_vertices_map[u] = new Array[V]
854 outgoing_vertices_map[u] = new Array[V]
855 end
856 end
857
858 redef fun has_vertex(u) do return outgoing_vertices_map.keys.has(u)
859
860 redef fun remove_vertex(u)
861 do
862 if has_vertex(u) then
863 for v in successors(u) do
864 remove_arc(u, v)
865 end
866 for v in predecessors(u) do
867 remove_arc(v, u)
868 end
869 incoming_vertices_map.keys.remove(u)
870 outgoing_vertices_map.keys.remove(u)
871 end
872 end
873
874 redef fun add_arc(u, v)
875 do
876 if not has_vertex(u) then add_vertex(u)
877 if not has_vertex(v) then add_vertex(v)
878 if not has_arc(u, v) then
879 incoming_vertices_map[v].add(u)
880 outgoing_vertices_map[u].add(v)
881 number_of_arcs += 1
882 end
883 end
884
885 redef fun has_arc(u, v)
886 do
887 return outgoing_vertices_map[u].has(v)
888 end
889
890 redef fun remove_arc(u, v)
891 do
892 if has_arc(u, v) then
893 outgoing_vertices_map[u].remove(v)
894 incoming_vertices_map[v].remove(u)
895 number_of_arcs -= 1
896 end
897 end
898
899 redef fun predecessors(u): Array[V]
900 do
901 if incoming_vertices_map.keys.has(u) then
902 return incoming_vertices_map[u].clone
903 else
904 return new Array[V]
905 end
906 end
907
908 redef fun successors(u): Array[V]
909 do
910 if outgoing_vertices_map.keys.has(u) then
911 return outgoing_vertices_map[u].clone
912 else
913 return new Array[V]
914 end
915 end
916
917 redef fun vertices_iterator: Iterator[V] do return outgoing_vertices_map.keys.iterator
918 end