digraph: Implementation of a reflexive directed 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 # var g0 = new HashDigraph[Int]
47 # ~~~
48 #
49 # Then we can add vertices and arcs. Note that if an arc is added whose source
50 # and target are not already in the digraph, the vertices are added beforehand.
51 # ~~~
52 # var g1 = new HashDigraph[Int]
53 # g1.add_vertex(0)
54 # g1.add_vertex(1)
55 # g1.add_arc(0,1)
56 # g1.add_arc(1,2)
57 # assert g1.to_s == "Digraph of 3 vertices and 2 arcs"
58 # ~~~
59 #
60 # One might also create digraphs with strings in vertices, for instance to
61 # represent some directed relation. However, it is currently not possible to
62 # store values in the arcs.
63 # ~~~
64 # var g2 = new HashDigraph[String]
65 # g2.add_vertex("Amy")
66 # g2.add_vertex("Bill")
67 # g2.add_vertex("Chris")
68 # g2.add_vertex("Diane")
69 # g2.add_arc("Amy", "Bill") # Amy likes Bill
70 # g2.add_arc("Bill", "Amy") # Bill likes Amy
71 # g2.add_arc("Chris", "Diane") # and so on
72 # g2.add_arc("Diane", "Amy") # and so on
73 # ~~~
74 #
75 # `HashDigraph`s are mutable, i.e. one might remove arcs and/or vertices:
76 # ~~~
77 # var g3 = new HashDigraph[Int]
78 # g3.add_arc(0,1)
79 # g3.add_arc(0,2)
80 # g3.add_arc(1,2)
81 # g3.add_arc(2,3)
82 # g3.add_arc(2,4)
83 # g3.remove_vertex(1)
84 # g3.remove_arc(2, 4)
85 # assert g3.to_s == "Digraph of 4 vertices and 2 arcs"
86 # ~~~
87 #
88 # If one has installed [Graphviz](http://graphviz.org), it is easy to produce a
89 # *dot* file which Graphviz process into a picture:
90 # ~~~
91 # var g4 = new HashDigraph[Int]
92 # g4.add_arcs([[0,1],[0,2],[1,2],[2,3],[2,4]])
93 # print g4.to_dot
94 # # Then call "dot -Tpng -o graph.png"
95 # ~~~
96 #
97 # ![A graph drawing produced by Graphviz](https://github.com/nitlang/nit/blob/master/lib/graph.png)
98 #
99 # Other methods
100 # =============
101 #
102 # There exist other methods available for digraphs and many other will be
103 # implemented in the future. For more details, one should look at the methods
104 # directly. For instance, the [strongly connected components]
105 # (https://en.wikipedia.org/wiki/Strongly_connected_component) of a digraph are
106 # returned as a [disjoint set data structure]
107 # (https://en.wikipedia.org/wiki/Disjoint-set_data_structure) (i.e. a set of
108 # sets):
109 # ~~~
110 # var g5 = new HashDigraph[Int]
111 # g5.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
112 # for component in g5.strongly_connected_components.to_partitions
113 # do
114 # print component
115 # end
116 # # Prints [1,2] and [3,4,5]
117 # ~~~
118 #
119 # It is also possible to compute a shortest (directed) path between two
120 # vertices:
121 # ~~~
122 # var g6 = new HashDigraph[Int]
123 # g6.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
124 # var path = g6.a_shortest_path(2, 4)
125 # if path != null then print path else print "No path"
126 # # Prints [2,3,4]
127 # path = g6.a_shortest_path(4, 2)
128 # if path != null then print path else print "No path"
129 # # Prints "No path"
130 # ~~~
131 #
132 # Extending the library
133 # =====================
134 #
135 # There are at least two ways of providing new methods on digraphs. If the
136 # method is standard and could be useful to other users, you should consider
137 # including your implementation directly in this library.
138 #
139 # Otherwise, for personal use, you should simply define a new class inheriting
140 # from `HashDigraph` and add the new services.
141 module digraph
142
143 # Interface for digraphs
144 interface Digraph[V: Object]
145
146 ## ---------------- ##
147 ## Abstract methods ##
148 ## ---------------- ##
149
150 # The number of vertices in this graph.
151 #
152 # ~~~
153 # var g = new HashDigraph[Int]
154 # g.add_vertex(0)
155 # g.add_vertex(1)
156 # assert g.num_vertices == 2
157 # g.add_vertex(0)
158 # assert g.num_vertices == 2
159 # ~~~
160 fun num_vertices: Int is abstract
161
162 # The number of arcs in this graph.
163 #
164 # ~~~
165 # var g = new HashDigraph[Int]
166 # g.add_arc(0, 1)
167 # assert g.num_arcs == 1
168 # g.add_arc(0, 1)
169 # assert g.num_arcs == 1
170 # g.add_arc(2, 3)
171 # assert g.num_arcs == 2
172 # ~~~
173 fun num_arcs: Int is abstract
174
175 # Returns true if and only if `u` exists in this graph.
176 #
177 # ~~~
178 # var g = new HashDigraph[Int]
179 # g.add_vertex(1)
180 # assert g.has_vertex(1)
181 # assert not g.has_vertex(0)
182 # g.add_vertex(1)
183 # assert g.has_vertex(1)
184 # assert not g.has_vertex(0)
185 # ~~~
186 fun has_vertex(u: V): Bool is abstract
187
188 # Returns true if and only if `(u,v)` is an arc in this graph.
189 #
190 # ~~~
191 # var g = new HashDigraph[Int]
192 # g.add_arc(0, 1)
193 # g.add_arc(1, 2)
194 # assert g.has_arc(0, 1)
195 # assert g.has_arc(1, 2)
196 # assert not g.has_arc(0, 2)
197 # ~~~
198 fun has_arc(u, v: V): Bool is abstract
199
200 # Returns the predecessors of `u`.
201 #
202 # If `u` does not exist, then it returns null.
203 #
204 # ~~~
205 # var g = new HashDigraph[Int]
206 # g.add_arc(0, 1)
207 # g.add_arc(1, 2)
208 # g.add_arc(0, 2)
209 # assert g.predecessors(2).has(0)
210 # assert g.predecessors(2).has(1)
211 # assert not g.predecessors(2).has(2)
212 # ~~~
213 fun predecessors(u: V): Collection[V] is abstract
214
215 # Returns the successors of `u`.
216 #
217 # If `u` does not exist, then an empty collection is returned.
218 #
219 # ~~~
220 # var g = new HashDigraph[Int]
221 # g.add_arc(0, 1)
222 # g.add_arc(1, 2)
223 # g.add_arc(0, 2)
224 # assert not g.successors(0).has(0)
225 # assert g.successors(0).has(1)
226 # assert g.successors(0).has(2)
227 # ~~~
228 fun successors(u: V): Collection[V] is abstract
229
230 # Returns an iterator over the vertices of this graph.
231 #
232 # ~~~
233 # var g = new HashDigraph[Int]
234 # g.add_arc(0, 1)
235 # g.add_arc(0, 2)
236 # g.add_arc(1, 2)
237 # var vs = new HashSet[Int]
238 # for v in g.vertices_iterator do vs.add(v)
239 # assert vs == new HashSet[Int].from([0,1,2])
240 # ~~~
241 fun vertices_iterator: Iterator[V] is abstract
242
243 ## -------------------- ##
244 ## Non abstract methods ##
245 ## -------------------- ##
246
247 ## ------------- ##
248 ## Basic methods ##
249 ## ------------- ##
250
251 # Returns true if and only if this graph is empty.
252 #
253 # An empty graph is a graph without vertex and arc.
254 #
255 # ~~~
256 # assert (new HashDigraph[Int]).is_empty
257 # ~~~
258 fun is_empty: Bool do return num_vertices == 0 and num_arcs == 0
259
260 # Returns an array containing the vertices of this graph.
261 #
262 # ~~~
263 # var g = new HashDigraph[Int]
264 # g.add_vertices([0,2,4,5])
265 # assert g.vertices.length == 4
266 # ~~~
267 fun vertices: Array[V] do return [for u in vertices_iterator do u]
268
269 # Returns an iterator over the arcs of this graph
270 #
271 # ~~~
272 # var g = new HashDigraph[Int]
273 # g.add_arc(0, 1)
274 # g.add_arc(0, 2)
275 # g.add_arc(1, 2)
276 # for arc in g.arcs_iterator do
277 # assert g.has_arc(arc[0], arc[1])
278 # end
279 # ~~~
280 fun arcs_iterator: Iterator[Array[V]] do return new ArcsIterator[V](self)
281
282 # Returns the arcs of this graph.
283 #
284 # ~~~
285 # var g = new HashDigraph[Int]
286 # g.add_arc(1, 3)
287 # g.add_arc(2, 3)
288 # assert g.arcs.length == 2
289 # ~~~
290 fun arcs: Array[Array[V]] do return [for arc in arcs_iterator do arc]
291
292 # Returns the incoming arcs of vertex `u`.
293 #
294 # If `u` is not in this graph, an empty array is returned.
295 #
296 # ~~~
297 # var g = new HashDigraph[Int]
298 # g.add_arc(1, 3)
299 # g.add_arc(2, 3)
300 # for arc in g.incoming_arcs(3) do
301 # assert g.is_predecessor(arc[0], arc[1])
302 # end
303 # ~~~
304 fun incoming_arcs(u: V): Collection[Array[V]]
305 do
306 if has_vertex(u) then
307 return [for v in predecessors(u) do [v, u]]
308 else
309 return new Array[Array[V]]
310 end
311 end
312
313 # Returns the outgoing arcs of vertex `u`.
314 #
315 # If `u` is not in this graph, an empty array is returned.
316 #
317 # ~~~
318 # var g = new HashDigraph[Int]
319 # g.add_arc(1, 3)
320 # g.add_arc(2, 3)
321 # g.add_arc(1, 2)
322 # for arc in g.outgoing_arcs(1) do
323 # assert g.is_successor(arc[1], arc[0])
324 # end
325 # ~~~
326 fun outgoing_arcs(u: V): Collection[Array[V]]
327 do
328 if has_vertex(u) then
329 return [for v in successors(u) do [u, v]]
330 else
331 return new Array[Array[V]]
332 end
333 end
334
335 ## ---------------------- ##
336 ## String representations ##
337 ## ---------------------- ##
338
339 redef fun to_s
340 do
341 var vertex_word = "vertices"
342 var arc_word = "arcs"
343 if num_vertices <= 1 then vertex_word = "vertex"
344 if num_arcs <= 1 then arc_word = "arc"
345 return "Digraph of {num_vertices} {vertex_word} and {num_arcs} {arc_word}"
346 end
347
348 # Returns a GraphViz string representing this digraph.
349 fun to_dot: String
350 do
351 var s = "digraph \{\n"
352 var id_set = new HashMap[V, Int]
353 # Writing the vertices
354 for u in vertices_iterator, i in [0 .. vertices.length[ do
355 id_set[u] = i
356 s += " \"{i}\" "
357 s += "[label=\"{u.to_s.escape_to_dot}\"];\n"
358 end
359 # Writing the arcs
360 for arc in arcs do
361 s += " {id_set[arc[0]]} "
362 s += "-> {id_set[arc[1]]};"
363 end
364 s += "\}"
365 return s
366 end
367
368 # Open Graphviz with `self.to_dot`.
369 #
370 # Mainly used for debugging.
371 fun show_dot do
372 var f = new ProcessWriter("dot", "-Txlib")
373 f.write to_dot
374 f.close
375 end
376
377 ## ------------ ##
378 ## Neighborhood ##
379 ## ------------ ##
380
381 # Returns true if and only if `u` is a predecessor of `v`.
382 #
383 # ~~~
384 # var g = new HashDigraph[Int]
385 # g.add_arc(1, 3)
386 # assert g.is_predecessor(1, 3)
387 # assert not g.is_predecessor(3, 1)
388 # ~~~
389 fun is_predecessor(u, v: V): Bool do return has_arc(u, v)
390
391 # Returns true if and only if `u` is a successor of `v`.
392 #
393 # ~~~
394 # var g = new HashDigraph[Int]
395 # g.add_arc(1, 3)
396 # assert not g.is_successor(1, 3)
397 # assert g.is_successor(3, 1)
398 # ~~~
399 fun is_successor(u, v: V): Bool do return has_arc(v, u)
400
401 # Returns the number of arcs whose target is `u`.
402 #
403 # ~~~
404 # var g = new HashDigraph[Int]
405 # g.add_arc(1, 3)
406 # g.add_arc(2, 3)
407 # assert g.in_degree(3) == 2
408 # assert g.in_degree(1) == 0
409 # ~~~
410 fun in_degree(u: V): Int do return predecessors(u).length
411
412 # Returns the number of arcs whose source is `u`.
413 #
414 # ~~~
415 # var g = new HashDigraph[Int]
416 # g.add_arc(1, 2)
417 # g.add_arc(1, 3)
418 # g.add_arc(2, 3)
419 # assert g.out_degree(3) == 0
420 # assert g.out_degree(1) == 2
421 # ~~~
422 fun out_degree(u: V): Int do return successors(u).length
423
424 # ------------------ #
425 # Paths and circuits #
426 # ------------------ #
427
428 # Returns true if and only if `vertices` is a path of this digraph.
429 #
430 # ~~~
431 # var g = new HashDigraph[Int]
432 # g.add_arc(1, 2)
433 # g.add_arc(2, 3)
434 # g.add_arc(3, 4)
435 # assert g.has_path([1,2,3])
436 # assert not g.has_path([1,3,3])
437 # ~~~
438 fun has_path(vertices: SequenceRead[V]): Bool
439 do
440 for i in [0..vertices.length - 1[ do
441 if not has_arc(vertices[i], vertices[i + 1]) then return false
442 end
443 return true
444 end
445
446 # Returns true if and only if `vertices` is a circuit of this digraph.
447 #
448 # ~~~
449 # var g = new HashDigraph[Int]
450 # g.add_arc(1, 2)
451 # g.add_arc(2, 3)
452 # g.add_arc(3, 1)
453 # assert g.has_circuit([1,2,3,1])
454 # assert not g.has_circuit([1,3,2,1])
455 # ~~~
456 fun has_circuit(vertices: SequenceRead[V]): Bool
457 do
458 return vertices.is_empty or (has_path(vertices) and vertices.first == vertices.last)
459 end
460
461 # Returns a shortest path from vertex `u` to `v`.
462 #
463 # If no path exists between `u` and `v`, it returns `null`.
464 #
465 # ~~~
466 # var g = new HashDigraph[Int]
467 # g.add_arc(1, 2)
468 # g.add_arc(2, 3)
469 # g.add_arc(3, 4)
470 # assert g.a_shortest_path(1, 4).length == 4
471 # g.add_arc(1, 3)
472 # assert g.a_shortest_path(1, 4).length == 3
473 # assert g.a_shortest_path(4, 1) == null
474 # ~~~
475 fun a_shortest_path(u, v: V): nullable Sequence[V]
476 do
477 var queue = new List[V].from([u]).as_fifo
478 var pred = new HashMap[V, nullable V]
479 var visited = new HashSet[V]
480 var w: nullable V = null
481 pred[u] = null
482 while not queue.is_empty do
483 w = queue.take
484 if not visited.has(w) then
485 visited.add(w)
486 if w == v then break
487 for wp in successors(w) do
488 if not pred.keys.has(wp) then
489 queue.add(wp)
490 pred[wp] = w
491 end
492 end
493 end
494 end
495 if w != v then
496 return null
497 else
498 var path = new List[V]
499 path.add(v)
500 w = v
501 while pred[w] != null do
502 path.unshift(pred[w].as(not null))
503 w = pred[w]
504 end
505 return path
506 end
507 end
508
509 # Build a path (or circuit) from the vertex `start` that visits every edge exactly once.
510 #
511 # ~~~
512 # var g = new HashDigraph[Int]
513 # g.add_arc(1, 2)
514 # g.add_arc(2, 3)
515 # g.add_arc(3, 4)
516 # assert g.eulerian_path(1) == [1, 2, 3, 4]
517 # ~~~
518 fun eulerian_path(start: V): Array[V]
519 do
520 var visited = new HashDigraph[V]
521 visited.add_graph(self)
522 return visited.remove_eulerian_path(start)
523 end
524
525 # Returns the distance between `u` and `v`
526 #
527 # If no path exists between `u` and `v`, it returns null. It is not
528 # symmetric, i.e. we may have `dist(u, v) != dist(v, u)`.
529 #
530 # ~~~
531 # var g = new HashDigraph[Int]
532 # g.add_arc(1, 2)
533 # g.add_arc(2, 3)
534 # g.add_arc(3, 4)
535 # assert g.distance(1, 4) == 3
536 # g.add_arc(1, 3)
537 # assert g.distance(1, 4) == 2
538 # assert g.distance(4, 1) == null
539 # ~~~
540 fun distance(u, v: V): nullable Int
541 do
542 var queue = new List[V].from([u]).as_fifo
543 var dist = new HashMap[V, Int]
544 var visited = new HashSet[V]
545 var w: nullable V
546 dist[u] = 0
547 while not queue.is_empty do
548 w = queue.take
549 if not visited.has(w) then
550 visited.add(w)
551 if w == v then break
552 for wp in successors(w) do
553 if not dist.keys.has(wp) then
554 queue.add(wp)
555 dist[wp] = dist[w] + 1
556 end
557 end
558 end
559 end
560 return dist.get_or_null(v)
561 end
562
563 # -------------------- #
564 # Connected components #
565 # -------------------- #
566
567 # Returns the weak connected components of this digraph.
568 #
569 # The weak connected components of a digraph are the usual
570 # connected components of its associated undirected graph,
571 # i.e. the graph obtained by replacing each arc by an edge.
572 #
573 # ~~~
574 # var g = new HashDigraph[Int]
575 # g.add_arc(1, 2)
576 # g.add_arc(2, 3)
577 # g.add_arc(4, 5)
578 # assert g.weakly_connected_components.number_of_subsets == 2
579 # ~~~
580 fun weakly_connected_components: DisjointSet[V]
581 do
582 var components = new DisjointSet[V]
583 components.add_all(vertices)
584 for arc in arcs_iterator do
585 components.union(arc[0], arc[1])
586 end
587 return components
588 end
589
590 # Returns the strongly connected components of this digraph.
591 #
592 # Two vertices `u` and `v` belong to the same strongly connected
593 # component if and only if there exists a path from `u` to `v`
594 # and there exists a path from `v` to `u`.
595 #
596 # This is computed in linear time (Tarjan's algorithm).
597 #
598 # ~~~
599 # var g = new HashDigraph[Int]
600 # g.add_arc(1, 2)
601 # g.add_arc(2, 3)
602 # g.add_arc(3, 1)
603 # g.add_arc(3, 4)
604 # g.add_arc(4, 5)
605 # g.add_arc(5, 6)
606 # g.add_arc(6, 5)
607 # assert g.strongly_connected_components.number_of_subsets == 3
608 # ~~~
609 fun strongly_connected_components: DisjointSet[V]
610 do
611 var tarjanAlgorithm = new TarjanAlgorithm[V](self)
612 return tarjanAlgorithm.strongly_connected_components
613 end
614 end
615
616 # Computing the strongly connected components using Tarjan's algorithm
617 private class TarjanAlgorithm[V: Object]
618 # The graph whose strongly connected components will be computed
619 var graph: Digraph[V]
620 # The strongly connected components computed in Tarjan's algorithm
621 var sccs = new DisjointSet[V]
622 # An index used for Tarjan's algorithm
623 var index = 0
624 # A stack used for Tarjan's algorithm
625 var stack: Queue[V] = (new Array[V]).as_lifo
626 # A map associating with each vertex its index
627 var vertex_to_index = new HashMap[V, Int]
628 # A map associating with each vertex its ancestor in Tarjan's algorithm
629 var ancestor = new HashMap[V, Int]
630 # True if and only if the vertex is in the stack
631 var in_stack = new HashSet[V]
632
633 # Returns the strongly connected components of a graph
634 fun strongly_connected_components: DisjointSet[V]
635 do
636 for u in graph.vertices_iterator do sccs.add(u)
637 for v in graph.vertices_iterator do
638 visit(v)
639 end
640 return sccs
641 end
642
643 # The recursive part of Tarjan's algorithm
644 fun visit(u: V)
645 do
646 vertex_to_index[u] = index
647 ancestor[u] = index
648 index += 1
649 stack.add(u)
650 in_stack.add(u)
651 for v in graph.successors(u) do
652 if not vertex_to_index.keys.has(v) then
653 visit(v)
654 ancestor[u] = ancestor[u].min(ancestor[v])
655 else if in_stack.has(v) then
656 ancestor[u] = ancestor[u].min(vertex_to_index[v])
657 end
658 end
659 if vertex_to_index[u] == ancestor[u] then
660 var v
661 loop
662 v = stack.take
663 in_stack.remove(v)
664 sccs.union(u, v)
665 if u == v then break
666 end
667 end
668 end
669 end
670
671 # Arcs iterator
672 class ArcsIterator[V: Object]
673 super Iterator[Array[V]]
674
675 # The graph whose arcs are iterated over
676 var graph: Digraph[V]
677 # Attributes
678 #
679 private var sources_iterator: Iterator[V] is noinit
680 private var targets_iterator: Iterator[V] is noinit
681 init
682 do
683 sources_iterator = graph.vertices_iterator
684 if sources_iterator.is_ok then
685 targets_iterator = graph.successors(sources_iterator.item).iterator
686 if not targets_iterator.is_ok then update_iterators
687 end
688 end
689
690 redef fun is_ok do return sources_iterator.is_ok and targets_iterator.is_ok
691
692 redef fun item do return [sources_iterator.item, targets_iterator.item]
693
694 redef fun next
695 do
696 targets_iterator.next
697 update_iterators
698 end
699
700 private fun update_iterators
701 do
702 while not targets_iterator.is_ok and sources_iterator.is_ok
703 do
704 sources_iterator.next
705 if sources_iterator.is_ok then
706 targets_iterator = graph.successors(sources_iterator.item).iterator
707 end
708 end
709 end
710 end
711
712 # Mutable digraph
713 abstract class MutableDigraph[V: Object]
714 super Digraph[V]
715
716 ## ---------------- ##
717 ## Abstract methods ##
718 ## ---------------- ##
719
720 # Adds the vertex `u` to this graph.
721 #
722 # If `u` already belongs to the graph, then nothing happens.
723 #
724 # ~~~
725 # var g = new HashDigraph[Int]
726 # g.add_vertex(0)
727 # assert g.has_vertex(0)
728 # assert not g.has_vertex(1)
729 # g.add_vertex(1)
730 # assert g.num_vertices == 2
731 # ~~~
732 fun add_vertex(u: V) is abstract
733
734 # Removes the vertex `u` from this graph and all its incident arcs.
735 #
736 # If the vertex does not exist in the graph, then nothing happens.
737 #
738 # ~~~
739 # var g = new HashDigraph[Int]
740 # g.add_vertex(0)
741 # g.add_vertex(1)
742 # assert g.has_vertex(0)
743 # g.remove_vertex(0)
744 # assert not g.has_vertex(0)
745 # ~~~
746 fun remove_vertex(u: V) is abstract
747
748 # Adds the arc `(u,v)` to this graph.
749 #
750 # If there is already an arc from `u` to `v` in this graph, then
751 # nothing happens. If vertex `u` or vertex `v` do not exist in the
752 # graph, they are added.
753 #
754 # ~~~
755 # var g = new HashDigraph[Int]
756 # g.add_arc(0, 1)
757 # g.add_arc(1, 2)
758 # assert g.has_arc(0, 1)
759 # assert g.has_arc(1, 2)
760 # assert not g.has_arc(1, 0)
761 # g.add_arc(1, 2)
762 # assert g.num_arcs == 2
763 # ~~~
764 fun add_arc(u, v: V) is abstract
765
766 # Removes the arc `(u,v)` from this graph.
767 #
768 # If the arc does not exist in the graph, then nothing happens.
769 #
770 # ~~~
771 # var g = new HashDigraph[Int]
772 # g.add_arc(0, 1)
773 # assert g.num_arcs == 1
774 # g.remove_arc(0, 1)
775 # assert g.num_arcs == 0
776 # g.remove_arc(0, 1)
777 # assert g.num_arcs == 0
778 # ~~~
779 fun remove_arc(u, v: V) is abstract
780
781 ## -------------------- ##
782 ## Non abstract methods ##
783 ## -------------------- ##
784
785 # Adds all vertices of `vertices` to this digraph.
786 #
787 # If vertices appear more than once, they are only added once.
788 #
789 # ~~~
790 # var g = new HashDigraph[Int]
791 # g.add_vertices([0,1,2,3])
792 # assert g.num_vertices == 4
793 # g.add_vertices([2,3,4,5])
794 # assert g.num_vertices == 6
795 # ~~~
796 fun add_vertices(vertices: Collection[V])
797 do
798 for u in vertices do add_vertex(u)
799 end
800
801 # Adds all arcs of `arcs` to this digraph.
802 #
803 # If arcs appear more than once, they are only added once.
804 #
805 # ~~~
806 # var g = new HashDigraph[Int]
807 # var arcs = [[0,1], [1,2], [1,2]]
808 # g.add_arcs(arcs)
809 # assert g.num_arcs == 2
810 # ~~~
811 fun add_arcs(arcs: Collection[Array[V]])
812 do
813 for a in arcs do add_arc(a[0], a[1])
814 end
815
816 # Add all vertices and arcs from the `other` graph.
817 #
818 # ~~~
819 # var g1 = new HashDigraph[Int]
820 # var arcs1 = [[0,1], [1,2]]
821 # g1.add_arcs(arcs1)
822 # g1.add_arcs(arcs1)
823 # g1.add_vertex(3)
824 # var g2 = new HashDigraph[Int]
825 # var arcs2 = [[0,1], [1,4]]
826 # g2.add_arcs(arcs2)
827 # g2.add_vertex(5)
828 # g2.add_graph(g1)
829 # assert g2.vertices.has_exactly([0, 1, 2, 3, 4, 5])
830 # var arcs3 = [[0,1], [1,2], [1,4]]
831 # assert g2.arcs.has_exactly(arcs3)
832 # ~~~
833 fun add_graph(other: Digraph[V])
834 do
835 for v in other.vertices do
836 add_vertex(v)
837 for w in other.successors(v) do
838 add_arc(v, w)
839 end
840 end
841 end
842
843 # Build a path (or circuit) that removes every edge exactly once.
844 #
845 # See `eulerian_path` for details
846 fun remove_eulerian_path(start: V): Array[V]
847 do
848 var stack = new Array[V]
849 var path = new Array[V]
850 var current = start
851 loop
852 if out_degree(current) == 0 then
853 path.unshift current
854 if stack.is_empty then break
855 current = stack.pop
856 else
857 stack.add current
858 var n = successors(current).first
859 remove_arc(current, n)
860 current = n
861 end
862 end
863 return path
864 end
865 end
866 # A directed graph represented by hash maps
867 class HashDigraph[V: Object]
868 super MutableDigraph[V]
869
870 # Attributes
871 #
872 private var incoming_vertices_map = new HashMap[V, Array[V]]
873 private var outgoing_vertices_map = new HashMap[V, Array[V]]
874 private var number_of_arcs = 0
875
876 redef fun num_vertices do return outgoing_vertices_map.keys.length end
877
878 redef fun num_arcs do return number_of_arcs end
879
880 redef fun add_vertex(u)
881 do
882 if not has_vertex(u) then
883 incoming_vertices_map[u] = new Array[V]
884 outgoing_vertices_map[u] = new Array[V]
885 end
886 end
887
888 redef fun has_vertex(u) do return outgoing_vertices_map.keys.has(u)
889
890 redef fun remove_vertex(u)
891 do
892 if has_vertex(u) then
893 for v in successors(u) do
894 remove_arc(u, v)
895 end
896 for v in predecessors(u) do
897 remove_arc(v, u)
898 end
899 incoming_vertices_map.keys.remove(u)
900 outgoing_vertices_map.keys.remove(u)
901 end
902 end
903
904 redef fun add_arc(u, v)
905 do
906 if not has_vertex(u) then add_vertex(u)
907 if not has_vertex(v) then add_vertex(v)
908 if not has_arc(u, v) then
909 incoming_vertices_map[v].add(u)
910 outgoing_vertices_map[u].add(v)
911 number_of_arcs += 1
912 end
913 end
914
915 redef fun has_arc(u, v)
916 do
917 return outgoing_vertices_map[u].has(v)
918 end
919
920 redef fun remove_arc(u, v)
921 do
922 if has_arc(u, v) then
923 outgoing_vertices_map[u].remove(v)
924 incoming_vertices_map[v].remove(u)
925 number_of_arcs -= 1
926 end
927 end
928
929 redef fun predecessors(u): Array[V]
930 do
931 if incoming_vertices_map.keys.has(u) then
932 return incoming_vertices_map[u].clone
933 else
934 return new Array[V]
935 end
936 end
937
938 redef fun successors(u): Array[V]
939 do
940 if outgoing_vertices_map.keys.has(u) then
941 return outgoing_vertices_map[u].clone
942 else
943 return new Array[V]
944 end
945 end
946
947 redef fun vertices_iterator: Iterator[V] do return outgoing_vertices_map.keys.iterator
948 end
949
950 # A reflexive directed graph
951 # i.e an element is in relation with itself (ie is implies `self.has_arc(u,u)`))
952 # This class avoids manually adding the reflexive vertices and at the same time it's avoids adding useless data to the hashmap.
953 class ReflexiveHashDigraph[V: Object]
954 super HashDigraph[V]
955
956 # Adds the arc (u,v) to this graph.
957 # if `u` is the same as `v` do nothing
958 #
959 # ~~~
960 # var g = new ReflexiveHashDigraph[Int]
961 # g.add_arc(1, 2)
962 # g.add_arc(3, 1)
963 # assert g.has_arc(2,2)
964 # assert g.has_arc(1,2)
965 # assert g.has_arc(3,1)
966 # ~~~
967 redef fun add_arc(u, v)
968 do
969 # Check `u` is the same as `v`
970 if u != v then
971 super
972 end
973 end
974
975 # Is (u,v) an arc in this graph?
976 # If `u` is the same as `v` return true
977 #
978 # ~~~
979 # var g = new ReflexiveHashDigraph[Int]
980 # g.add_arc(1, 2)
981 # g.add_arc(3, 1)
982 # g.add_vertex(4)
983 # assert g.has_arc(1,1)
984 # assert g.has_arc(2,2)
985 # assert g.has_arc(2,2)
986 # assert g.has_arc(3,2) == false
987 # assert g.has_arc(4,4)
988 # ~~~
989 redef fun has_arc(u, v)
990 do
991 return u == v or super
992 end
993
994 redef fun show_dot
995 do
996 var f = new ProcessWriter("dot", "-Txlib")
997 f.write to_dot
998 f.close
999 f.wait
1000 end
1001
1002 # Returns a shortest path from vertex `u` to `v`.
1003 #
1004 # If `u` is the same as `v` return `[u]`
1005 #
1006 # ~~~
1007 # var g = new ReflexiveHashDigraph[Int]
1008 # g.add_arc(1, 2)
1009 # g.add_arc(2, 3)
1010 # g.add_arc(3, 4)
1011 # assert g.a_shortest_path(1, 4).length == 4
1012 # assert g.a_shortest_path(1, 1).length == 1
1013 # ~~~
1014 redef fun a_shortest_path(u, v)
1015 do
1016 if u == v then
1017 var path = new List[V]
1018 path.add(u)
1019 return path
1020 end
1021 return super
1022 end
1023
1024 # Returns the distance between `u` and `v`
1025 #
1026 # If `u` is the same as `v` return `1`
1027 #
1028 # ~~~
1029 # var g = new ReflexiveHashDigraph[Int]
1030 # g.add_arc(1, 2)
1031 # g.add_arc(2, 3)
1032 # g.add_arc(3, 4)
1033 # assert g.distance(1, 1) == 1
1034 # assert g.distance(2, 2) == 1
1035 # ~~~
1036 redef fun distance(u, v)
1037 do
1038 if has_arc(u, v) and u == v then return 1
1039 return super
1040 end
1041
1042 # Returns the predecessors of `u`.
1043 #
1044 # `u` is include in the returned collection
1045 #
1046 # ~~~
1047 # var g = new ReflexiveHashDigraph[Int]
1048 # g.add_arc(1, 2)
1049 # g.add_arc(2, 3)
1050 # g.add_arc(3, 1)
1051 # assert g.predecessors(2).has(1)
1052 # assert g.predecessors(2).has(2)
1053 # ~~~
1054 redef fun predecessors(u)
1055 do
1056 var super_predecessors = super
1057 if incoming_vertices_map.has_key(u) then super_predecessors.add(u)
1058 return super_predecessors
1059 end
1060
1061 # Returns the successors of `u`.
1062 #
1063 # `u` is include in the returned collection
1064 #
1065 # ~~~
1066 # var g = new ReflexiveHashDigraph[Int]
1067 # g.add_arc(1, 2)
1068 # g.add_arc(2, 3)
1069 # g.add_arc(3, 1)
1070 # assert g.successors(2).has(3)
1071 # assert g.successors(2).has(2)
1072 # ~~~
1073 redef fun successors(u: V)
1074 do
1075 var super_successors = super
1076 if outgoing_vertices_map.has_key(u) then super_successors.add(u)
1077 return super_successors
1078 end
1079 end