lib: rename graphs to graph
[nit.git] / lib / graphs / digraph.nit
diff --git a/lib/graphs/digraph.nit b/lib/graphs/digraph.nit
deleted file mode 100644 (file)
index 65e0162..0000000
+++ /dev/null
@@ -1,918 +0,0 @@
-# This file is part of NIT (http://www.nitlanguage.org).
-#
-# Copyright 2015 Alexandre Blondin Massé <blondin_masse.alexandre@uqam.ca>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Implementation of directed graphs, also called digraphs.
-#
-# Overview
-# ========
-#
-# This module provides a simple interface together with a concrete
-# implementation of directed graphs (or digraphs).
-#
-# The upper level interface is `Digraph` and contains all methods for digraphs
-# that do not depend on the underlying data structure. More precisely, if basic
-# operations such as `predecessors`, `successors`, `num_vertices`, etc.  are
-# implemented, then high level operations (such as computing the connected
-# components or a shortest path between two vertices) can be easily derived.
-# Also, all methods found in `Digraph` do no modify the graph. For mutable
-# methods, one needs to check the `MutableDigraph` child class. Vertices can be
-# any `Object`, but there is no information stored in the arcs, which are
-# simple arrays of the form `[u,v]`, where `u` is the source of the arc and `v`
-# is the target.
-#
-# There is currently only one concrete implementation named `HashDigraph` that
-# makes use of the HashMap class for storing the predecessors and successors.
-# It is therefore simple to provide another implementation: One only has to
-# create a concrete specialization of either `Digraph` or `MutableDigraph`.
-#
-# Basic methods
-# =============
-#
-# To create an (empty) new graph whose keys are integers, one simply type
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# ~~~
-#
-# Then we can add vertices and arcs. Note that if an arc is added whose source
-# and target are not already in the digraph, the vertices are added beforehand.
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# g.add_vertex(0)
-# g.add_vertex(1)
-# g.add_arc(0,1)
-# g.add_arc(1,2)
-# assert g.to_s == "Digraph of 3 vertices and 2 arcs"
-# ~~~
-#
-# One might also create digraphs with strings in vertices, for instance to
-# represent some directed relation. However, it is currently not possible to
-# store values in the arcs.
-# ~~~
-# import digraph
-# var g = new HashDigraph[String]
-# g.add_vertex("Amy")
-# g.add_vertex("Bill")
-# g.add_vertex("Chris")
-# g.add_vertex("Diane")
-# g.add_arc("Amy", "Bill")    # Amy likes Bill
-# g.add_arc("Bill", "Amy")    # Bill likes Amy
-# g.add_arc("Chris", "Diane") # and so on
-# g.add_arc("Diane", "Amy")   # and so on
-# ~~~
-#
-# `HashDigraph`s are mutable, i.e. one might remove arcs and/or vertices:
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# g.add_arc(0,1)
-# g.add_arc(0,2)
-# g.add_arc(1,2)
-# g.add_arc(2,3)
-# g.add_arc(2,4)
-# g.remove_vertex(1)
-# g.remove_arc(2, 4)
-# assert g.to_s == "Digraph of 4 vertices and 2 arcs"
-# ~~~
-#
-# If one has installed [Graphviz](http://graphviz.org), it is easy to produce a
-# *dot* file which Graphviz process into a picture:
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# g.add_arcs([[0,1],[0,2],[1,2],[2,3],[2,4]])
-# print g.to_dot
-# # Then call "dot -Tpng -o graph.png"
-# ~~~
-#
-# ![A graph drawing produced by Graphviz](https://github.com/nitlang/nit/blob/master/lib/graph.png)
-#
-# Other methods
-# =============
-#
-# There exist other methods available for digraphs and many other will be
-# implemented in the future. For more details, one should look at the methods
-# directly. For instance, the [strongly connected components]
-# (https://en.wikipedia.org/wiki/Strongly_connected_component) of a digraph are
-# returned as a [disjoint set data structure]
-# (https://en.wikipedia.org/wiki/Disjoint-set_data_structure) (i.e. a set of
-# sets):
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
-# for component in g.strongly_connected_components.to_partitions
-# do
-#      print component
-# end
-# # Prints [1,2] and [3,4,5]
-# ~~~
-#
-# It is also possible to compute a shortest (directed) path between two
-# vertices:
-# ~~~
-# import digraph
-# var g = new HashDigraph[Int]
-# g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
-# var path = g.a_shortest_path(2, 4)
-# if path != null then print path else print "No path"
-# # Prints [2,3,4]
-# path = g.a_shortest_path(4, 2)
-# if path != null then print path else print "No path"
-# # Prints "No path"
-# ~~~
-#
-# Extending the library
-# =====================
-#
-# There are at least two ways of providing new methods on digraphs. If the
-# method is standard and could be useful to other users, you should consider
-# including your implementation directly in this library.
-#
-# Otherwise, for personal use, you should simply define a new class inheriting
-# from `HashDigraph` and add the new services.
-module digraph
-
-# Interface for digraphs
-interface Digraph[V: Object]
-
-       ## ---------------- ##
-       ## Abstract methods ##
-       ## ---------------- ##
-
-       # The number of vertices in this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertex(0)
-       # g.add_vertex(1)
-       # assert g.num_vertices == 2
-       # g.add_vertex(0)
-       # assert g.num_vertices == 2
-       # ~~~
-       fun num_vertices: Int is abstract
-
-       # The number of arcs in this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # assert g.num_arcs == 1
-       # g.add_arc(0, 1)
-       # assert g.num_arcs == 1
-       # g.add_arc(2, 3)
-       # assert g.num_arcs == 2
-       # ~~~
-       fun num_arcs: Int is abstract
-
-       # Returns true if and only if `u` exists in this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertex(1)
-       # assert g.has_vertex(1)
-       # assert not g.has_vertex(0)
-       # g.add_vertex(1)
-       # assert g.has_vertex(1)
-       # assert not g.has_vertex(0)
-       # ~~~
-       fun has_vertex(u: V): Bool is abstract
-
-       # Returns true if and only if `(u,v)` is an arc in this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(1, 2)
-       # assert g.has_arc(0, 1)
-       # assert g.has_arc(1, 2)
-       # assert not g.has_arc(0, 2)
-       # ~~~
-       fun has_arc(u, v: V): Bool is abstract
-
-       # Returns the predecessors of `u`.
-       #
-       # If `u` does not exist, then it returns null.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(1, 2)
-       # g.add_arc(0, 2)
-       # assert g.predecessors(2).has(0)
-       # assert g.predecessors(2).has(1)
-       # assert not g.predecessors(2).has(2)
-       # ~~~
-       fun predecessors(u: V): Collection[V] is abstract
-
-       # Returns the successors of `u`.
-       #
-       # If `u` does not exist, then an empty collection is returned.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(1, 2)
-       # g.add_arc(0, 2)
-       # assert not g.successors(0).has(0)
-       # assert g.successors(0).has(1)
-       # assert g.successors(0).has(2)
-       # ~~~
-       fun successors(u: V): Collection[V] is abstract
-
-       # Returns an iterator over the vertices of this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(0, 2)
-       # g.add_arc(1, 2)
-       # var vs = new HashSet[Int]
-       # for v in g.vertices_iterator do vs.add(v)
-       # assert vs == new HashSet[Int].from([0,1,2])
-       # ~~~
-       fun vertices_iterator: Iterator[V] is abstract
-
-       ## -------------------- ##
-       ## Non abstract methods ##
-       ## -------------------- ##
-
-       ## ------------- ##
-       ## Basic methods ##
-       ## ------------- ##
-
-       # Returns true if and only if this graph is empty.
-       #
-       # An empty graph is a graph without vertex and arc.
-       #
-       # ~~~
-       # import digraph
-       # assert (new HashDigraph[Int]).is_empty
-       # ~~~
-       fun is_empty: Bool do return num_vertices == 0 and num_arcs == 0
-
-       # Returns an array containing the vertices of this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertices([0,2,4,5])
-       # assert g.vertices.length == 4
-       # ~~~
-       fun vertices: Array[V] do return [for u in vertices_iterator do u]
-
-       # Returns an iterator over the arcs of this graph
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(0, 2)
-       # g.add_arc(1, 2)
-       # for arc in g.arcs_iterator do
-       #       assert g.has_arc(arc[0], arc[1])
-       # end
-       # ~~~
-       fun arcs_iterator: Iterator[Array[V]] do return new ArcsIterator[V](self)
-
-       # Returns the arcs of this graph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # g.add_arc(2, 3)
-       # assert g.arcs.length == 2
-       # ~~~
-       fun arcs: Array[Array[V]] do return [for arc in arcs_iterator do arc]
-
-       # Returns the incoming arcs of vertex `u`.
-       #
-       # If `u` is not in this graph, an empty array is returned.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # g.add_arc(2, 3)
-       # for arc in g.incoming_arcs(3) do
-       #       assert g.is_predecessor(arc[0], arc[1])
-       # end
-       # ~~~
-       fun incoming_arcs(u: V): Collection[Array[V]]
-       do
-               if has_vertex(u) then
-                       return [for v in predecessors(u) do [v, u]]
-               else
-                       return new Array[Array[V]]
-               end
-       end
-
-       # Returns the outgoing arcs of vertex `u`.
-       #
-       # If `u` is not in this graph, an empty array is returned.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # g.add_arc(2, 3)
-       # g.add_arc(1, 2)
-       # for arc in g.outgoing_arcs(1) do
-       #       assert g.is_successor(arc[1], arc[0])
-       # end
-       # ~~~
-       fun outgoing_arcs(u: V): Collection[Array[V]]
-       do
-               if has_vertex(u) then
-                       return [for v in successors(u) do [u, v]]
-               else
-                       return new Array[Array[V]]
-               end
-       end
-
-       ## ---------------------- ##
-       ## String representations ##
-       ## ---------------------- ##
-
-       redef fun to_s
-       do
-               var vertex_word = "vertices"
-               var arc_word = "arcs"
-               if num_vertices <= 1 then vertex_word = "vertex"
-               if num_arcs <= 1 then arc_word = "arc"
-               return "Digraph of {num_vertices} {vertex_word} and {num_arcs} {arc_word}"
-       end
-
-       # Returns a GraphViz string representing this digraph.
-       fun to_dot: String
-       do
-               var s = "digraph \{\n"
-               var id_set = new HashMap[V, Int]
-               # Writing the vertices
-               for u in vertices_iterator, i in [0 .. vertices.length[ do
-                       id_set[u] = i
-                       s += "   \"{i}\" "
-                       s += "[label=\"{u.to_s.escape_to_dot}\"];\n"
-               end
-               # Writing the arcs
-               for arc in arcs do
-                       s += "   {id_set[arc[0]]} "
-                       s += "-> {id_set[arc[1]]};"
-               end
-               s += "\}"
-               return s
-       end
-
-       # Open Graphviz with `self.to_dot`.
-       #
-       # Mainly used for debugging.
-       fun show_dot do
-               var f = new ProcessWriter("dot", "-Txlib")
-               f.write to_dot
-               f.close
-       end
-
-       ## ------------ ##
-       ## Neighborhood ##
-       ## ------------ ##
-
-       # Returns true if and only if `u` is a predecessor of `v`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # assert g.is_predecessor(1, 3)
-       # assert not g.is_predecessor(3, 1)
-       # ~~~
-       fun is_predecessor(u, v: V): Bool do return has_arc(u, v)
-
-       # Returns true if and only if `u` is a successor of `v`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # assert not g.is_successor(1, 3)
-       # assert g.is_successor(3, 1)
-       # ~~~
-       fun is_successor(u, v: V): Bool do return has_arc(v, u)
-
-       # Returns the number of arcs whose target is `u`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 3)
-       # g.add_arc(2, 3)
-       # assert g.in_degree(3) == 2
-       # assert g.in_degree(1) == 0
-       # ~~~
-       fun in_degree(u: V): Int do return predecessors(u).length
-
-       # Returns the number of arcs whose source is `u`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(1, 3)
-       # g.add_arc(2, 3)
-       # assert g.out_degree(3) == 0
-       # assert g.out_degree(1) == 2
-       # ~~~
-       fun out_degree(u: V): Int do return successors(u).length
-
-       # ------------------ #
-       # Paths and circuits #
-       # ------------------ #
-
-       # Returns true if and only if `vertices` is a path of this digraph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(3, 4)
-       # assert g.has_path([1,2,3])
-       # assert not g.has_path([1,3,3])
-       # ~~~
-       fun has_path(vertices: SequenceRead[V]): Bool
-       do
-               for i in [0..vertices.length - 1[ do
-                       if not has_arc(vertices[i], vertices[i + 1]) then return false
-               end
-               return true
-       end
-
-       # Returns true if and only if `vertices` is a circuit of this digraph.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(3, 1)
-       # assert g.has_circuit([1,2,3,1])
-       # assert not g.has_circuit([1,3,2,1])
-       # ~~~
-       fun has_circuit(vertices: SequenceRead[V]): Bool
-       do
-               return vertices.is_empty or (has_path(vertices) and vertices.first == vertices.last)
-       end
-
-       # Returns a shortest path from vertex `u` to `v`.
-       #
-       # If no path exists between `u` and `v`, it returns `null`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(3, 4)
-       # assert g.a_shortest_path(1, 4).length == 4
-       # g.add_arc(1, 3)
-       # assert g.a_shortest_path(1, 4).length == 3
-       # assert g.a_shortest_path(4, 1) == null
-       # ~~~
-       fun a_shortest_path(u, v: V): nullable Sequence[V]
-       do
-               var queue = new List[V].from([u]).as_fifo
-               var pred = new HashMap[V, nullable V]
-               var visited = new HashSet[V]
-               var w: nullable V = null
-               pred[u] = null
-               while not queue.is_empty do
-                       w = queue.take
-                       if not visited.has(w) then
-                               visited.add(w)
-                               if w == v then break
-                               for wp in successors(w) do
-                                       if not pred.keys.has(wp) then
-                                               queue.add(wp)
-                                               pred[wp] = w
-                                       end
-                               end
-                       end
-               end
-               if w != v then
-                       return null
-               else
-                       var path = new List[V]
-                       path.add(v)
-                       w = v
-                       while pred[w] != null do
-                               path.unshift(pred[w].as(not null))
-                               w = pred[w]
-                       end
-                       return path
-               end
-       end
-
-       # Returns the distance between `u` and `v`
-       #
-       # If no path exists between `u` and `v`, it returns null. It is not
-       # symmetric, i.e. we may have `dist(u, v) != dist(v, u)`.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(3, 4)
-       # assert g.distance(1, 4) == 3
-       # g.add_arc(1, 3)
-       # assert g.distance(1, 4) == 2
-       # assert g.distance(4, 1) == null
-       # ~~~
-       fun distance(u, v: V): nullable Int
-       do
-               var queue = new List[V].from([u]).as_fifo
-               var dist = new HashMap[V, Int]
-               var visited = new HashSet[V]
-               var w: nullable V
-               dist[u] = 0
-               while not queue.is_empty do
-                       w = queue.take
-                       if not visited.has(w) then
-                               visited.add(w)
-                               if w == v then break
-                               for wp in successors(w) do
-                                       if not dist.keys.has(wp) then
-                                               queue.add(wp)
-                                               dist[wp] = dist[w] + 1
-                                       end
-                               end
-                       end
-               end
-               return dist.get_or_null(v)
-       end
-
-       # -------------------- #
-       # Connected components #
-       # -------------------- #
-
-       # Returns the weak connected components of this digraph.
-       #
-       # The weak connected components of a digraph are the usual
-       # connected components of its associated undirected graph,
-       # i.e. the graph obtained by replacing each arc by an edge.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(4, 5)
-       # assert g.weakly_connected_components.number_of_subsets == 2
-       # ~~~
-       fun weakly_connected_components: DisjointSet[V]
-       do
-               var components = new DisjointSet[V]
-               components.add_all(vertices)
-               for arc in arcs_iterator do
-                       components.union(arc[0], arc[1])
-               end
-               return components
-       end
-
-       # Returns the strongly connected components of this digraph.
-       #
-       # Two vertices `u` and `v` belong to the same strongly connected
-       # component if and only if there exists a path from `u` to `v`
-       # and there exists a path from `v` to `u`.
-       #
-       # This is computed in linear time (Tarjan's algorithm).
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(1, 2)
-       # g.add_arc(2, 3)
-       # g.add_arc(3, 1)
-       # g.add_arc(3, 4)
-       # g.add_arc(4, 5)
-       # g.add_arc(5, 6)
-       # g.add_arc(6, 5)
-       # assert g.strongly_connected_components.number_of_subsets == 3
-       # ~~~
-       fun strongly_connected_components: DisjointSet[V]
-       do
-               var tarjanAlgorithm = new TarjanAlgorithm[V](self)
-               return tarjanAlgorithm.strongly_connected_components
-       end
-end
-
-# Computing the strongly connected components using Tarjan's algorithm
-private class TarjanAlgorithm[V: Object]
-       # The graph whose strongly connected components will be computed
-       var graph: Digraph[V]
-       # The strongly connected components computed in Tarjan's algorithm
-       var sccs = new DisjointSet[V]
-       # An index used for Tarjan's algorithm
-       var index = 0
-       # A stack used for Tarjan's algorithm
-       var stack: Queue[V] = (new Array[V]).as_lifo
-       # A map associating with each vertex its index
-       var vertex_to_index = new HashMap[V, Int]
-       # A map associating with each vertex its ancestor in Tarjan's algorithm
-       var ancestor = new HashMap[V, Int]
-       # True if and only if the vertex is in the stack
-       var in_stack = new HashSet[V]
-
-       # Returns the strongly connected components of a graph
-       fun strongly_connected_components: DisjointSet[V]
-       do
-               for u in graph.vertices_iterator do sccs.add(u)
-               for v in graph.vertices_iterator do
-                       visit(v)
-               end
-               return sccs
-       end
-
-       # The recursive part of Tarjan's algorithm
-       fun visit(u: V)
-       do
-               vertex_to_index[u] = index
-               ancestor[u] = index
-               index += 1
-               stack.add(u)
-               in_stack.add(u)
-               for v in graph.successors(u) do
-                       if not vertex_to_index.keys.has(v) then
-                               visit(v)
-                               ancestor[u] = ancestor[u].min(ancestor[v])
-                       else if in_stack.has(v) then
-                               ancestor[u] = ancestor[u].min(vertex_to_index[v])
-                       end
-               end
-               if vertex_to_index[u] == ancestor[u] then
-                       var v
-                       loop
-                               v = stack.take
-                               in_stack.remove(v)
-                               sccs.union(u, v)
-                               if u == v then break
-                       end
-               end
-       end
-end
-
-# Arcs iterator
-class ArcsIterator[V: Object]
-       super Iterator[Array[V]]
-
-       # The graph whose arcs are iterated over
-       var graph: Digraph[V]
-       # Attributes
-       #
-       private var sources_iterator: Iterator[V] is noinit
-       private var targets_iterator: Iterator[V] is noinit
-       init
-       do
-               sources_iterator = graph.vertices_iterator
-               if sources_iterator.is_ok then
-                       targets_iterator = graph.successors(sources_iterator.item).iterator
-                       if not targets_iterator.is_ok then update_iterators
-               end
-       end
-
-       redef fun is_ok do return sources_iterator.is_ok and targets_iterator.is_ok
-
-       redef fun item do return [sources_iterator.item, targets_iterator.item]
-
-       redef fun next
-       do
-               targets_iterator.next
-               update_iterators
-       end
-
-       private fun update_iterators
-       do
-               while not targets_iterator.is_ok and sources_iterator.is_ok
-               do
-                       sources_iterator.next
-                       if sources_iterator.is_ok then
-                               targets_iterator = graph.successors(sources_iterator.item).iterator
-                       end
-               end
-       end
-end
-
-# Mutable digraph
-abstract class MutableDigraph[V: Object]
-       super Digraph[V]
-
-       ## ---------------- ##
-       ## Abstract methods ##
-       ## ---------------- ##
-
-       # Adds the vertex `u` to this graph.
-       #
-       # If `u` already belongs to the graph, then nothing happens.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertex(0)
-       # assert g.has_vertex(0)
-       # assert not g.has_vertex(1)
-       # g.add_vertex(1)
-       # assert g.num_vertices == 2
-       # ~~~
-       fun add_vertex(u: V) is abstract
-
-       # Removes the vertex `u` from this graph and all its incident arcs.
-       #
-       # If the vertex does not exist in the graph, then nothing happens.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertex(0)
-       # g.add_vertex(1)
-       # assert g.has_vertex(0)
-       # g.remove_vertex(0)
-       # assert not g.has_vertex(0)
-       # ~~~
-       fun remove_vertex(u: V) is abstract
-
-       # Adds the arc `(u,v)` to this graph.
-       #
-       # If there is already an arc from `u` to `v` in this graph, then
-       # nothing happens. If vertex `u` or vertex `v` do not exist in the
-       # graph, they are added.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # g.add_arc(1, 2)
-       # assert g.has_arc(0, 1)
-       # assert g.has_arc(1, 2)
-       # assert not g.has_arc(1, 0)
-       # g.add_arc(1, 2)
-       # assert g.num_arcs == 2
-       # ~~~
-       fun add_arc(u, v: V) is abstract
-
-       # Removes the arc `(u,v)` from this graph.
-       #
-       # If the arc does not exist in the graph, then nothing happens.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_arc(0, 1)
-       # assert g.num_arcs == 1
-       # g.remove_arc(0, 1)
-       # assert g.num_arcs == 0
-       # g.remove_arc(0, 1)
-       # assert g.num_arcs == 0
-       # ~~~
-       fun remove_arc(u, v: V) is abstract
-
-       ## -------------------- ##
-       ## Non abstract methods ##
-       ## -------------------- ##
-
-       # Adds all vertices of `vertices` to this digraph.
-       #
-       # If vertices appear more than once, they are only added once.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # g.add_vertices([0,1,2,3])
-       # assert g.num_vertices == 4
-       # g.add_vertices([2,3,4,5])
-       # assert g.num_vertices == 6
-       # ~~~
-       fun add_vertices(vertices: Collection[V])
-       do
-               for u in vertices do add_vertex(u)
-       end
-
-       # Adds all arcs of `arcs` to this digraph.
-       #
-       # If arcs appear more than once, they are only added once.
-       #
-       # ~~~
-       # import digraph
-       # var g = new HashDigraph[Int]
-       # var arcs = [[0,1], [1,2], [1,2]]
-       # g.add_arcs(arcs)
-       # assert g.num_arcs == 2
-       # ~~~
-       fun add_arcs(arcs: Collection[Array[V]])
-       do
-               for a in arcs do add_arc(a[0], a[1])
-       end
-end
-# A directed graph represented by hash maps
-class HashDigraph[V: Object]
-       super MutableDigraph[V]
-
-       # Attributes
-       #
-       private var incoming_vertices_map = new HashMap[V, Array[V]]
-       private var outgoing_vertices_map = new HashMap[V, Array[V]]
-       private var number_of_arcs = 0
-
-       redef fun num_vertices do return outgoing_vertices_map.keys.length end
-
-       redef fun num_arcs do return number_of_arcs end
-
-       redef fun add_vertex(u)
-       do
-               if not has_vertex(u) then
-                       incoming_vertices_map[u] = new Array[V]
-                       outgoing_vertices_map[u] = new Array[V]
-               end
-       end
-
-       redef fun has_vertex(u) do return outgoing_vertices_map.keys.has(u)
-
-       redef fun remove_vertex(u)
-       do
-               if has_vertex(u) then
-                       for v in successors(u) do
-                               remove_arc(u, v)
-                       end
-                       for v in predecessors(u) do
-                               remove_arc(v, u)
-                       end
-                       incoming_vertices_map.keys.remove(u)
-                       outgoing_vertices_map.keys.remove(u)
-               end
-       end
-
-       redef fun add_arc(u, v)
-       do
-               if not has_vertex(u) then add_vertex(u)
-               if not has_vertex(v) then add_vertex(v)
-               if not has_arc(u, v) then
-                       incoming_vertices_map[v].add(u)
-                       outgoing_vertices_map[u].add(v)
-                       number_of_arcs += 1
-               end
-       end
-
-       redef fun has_arc(u, v)
-       do
-               return outgoing_vertices_map[u].has(v)
-       end
-
-       redef fun remove_arc(u, v)
-       do
-               if has_arc(u, v) then
-                       outgoing_vertices_map[u].remove(v)
-                       incoming_vertices_map[v].remove(u)
-                       number_of_arcs -= 1
-               end
-       end
-
-       redef fun predecessors(u): Array[V]
-       do
-               if incoming_vertices_map.keys.has(u) then
-                       return incoming_vertices_map[u].clone
-               else
-                       return new Array[V]
-               end
-       end
-
-       redef fun successors(u): Array[V]
-       do
-               if outgoing_vertices_map.keys.has(u) then
-                       return outgoing_vertices_map[u].clone
-               else
-                       return new Array[V]
-               end
-       end
-
-       redef fun vertices_iterator: Iterator[V] do return outgoing_vertices_map.keys.iterator
-end