lib/poset: add POSet::add_chain
[nit.git] / lib / poset.nit
index 7a26f90..ecb9e14 100644 (file)
@@ -31,7 +31,7 @@ class POSet[E: Object]
        redef fun iterator do return elements.keys.iterator
 
        # All the nodes
-       private var elements: HashMap[E, POSetElement[E]] = new HashMap[E, POSetElement[E]]
+       private var elements = new HashMap[E, POSetElement[E]]
 
        redef fun has(e) do return self.elements.keys.has(e)
 
@@ -108,6 +108,27 @@ class POSet[E: Object]
                te.dfroms.add f
        end
 
+       # Add an edge between all elements of `es` in order.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos.has_direct_edge("A", "B")
+       # assert pos.has_direct_edge("B", "C")
+       # assert pos.has_direct_edge("C", "D")
+       # ~~~~
+       fun add_chain(es: SequenceRead[E])
+       do
+               if es.is_empty then return
+               var i = es.iterator
+               var e = i.item
+               i.next
+               for f in i do
+                       add_edge(e, f)
+                       e = f
+               end
+       end
+
        # Is there an edge (transitive or not) from `f` to `t`?
        # Since the POSet is reflexive, true is returned if `f == t`.
        fun has_edge(f,t: E): Bool
@@ -126,28 +147,40 @@ class POSet[E: Object]
                return fe.dtos.has(t)
        end
 
-       # Display the POSet in a gaphical windows.
-       # Graphviz with a working -Txlib is expected.
-       # Used fo debugging.
-       fun show_dot
+       # Write the POSet as a graphviz digraph.
+       #
+       # Nodes are identified with their `to_s`.
+       # Edges are unlabeled.
+       fun write_dot(f: OStream)
        do
-               var f = new OProcess("dot", "-Txlib")
-               #var f = stdout
                f.write "digraph \{\n"
                for x in elements.keys do
-                       f.write "\"{x}\";\n"
+                       var xstr = x.to_s.escape_to_dot
+                       f.write "\"{xstr}\";\n"
                        var xe = self.elements[x]
                        for y in xe.dtos do
+                               var ystr = y.to_s.escape_to_dot
                                if self.has_edge(y,x) then
-                                       f.write "\"{x}\" -> \"{y}\"[dir=both];\n"
+                                       f.write "\"{xstr}\" -> \"{ystr}\"[dir=both];\n"
                                else
-                                       f.write "\"{x}\" -> \"{y}\";\n"
+                                       f.write "\"{xstr}\" -> \"{ystr}\";\n"
                                end
                        end
                end
                f.write "\}\n"
-               #f.close
-               #f.wait
+       end
+
+       # Display the POSet in a graphical windows.
+       # Graphviz with a working -Txlib is expected.
+       #
+       # See `write_dot` for details.
+       fun show_dot
+       do
+               var f = new OProcess("dot", "-Txlib")
+               f.write "\}\n"
+               write_dot(f)
+               f.close
+               f.wait
        end
 
        # Compare two elements in an arbitrary total order.