X-Git-Url: http://nitlanguage.org diff --git a/lib/poset.nit b/lib/poset.nit index e8f7e73..3288e5c 100644 --- a/lib/poset.nit +++ b/lib/poset.nit @@ -71,7 +71,7 @@ module poset # # Thanks to the `[]` method, elements can be considered relatively to the poset. # SEE `POSetElement` -class POSet[E: Object] +class POSet[E] super Collection[E] super Comparator @@ -149,20 +149,37 @@ class POSet[E: Object] # Update the transitive reduction if te.tos.has(f) then return # Skip the reduction if there is a loop - for x in te.dfroms.to_a do + # Remove transitive edges. + # Because the sets of direct is iterated, the list of edges to remove + # is stored and is applied after the iteration. + # The usual case is that no direct edges need to be removed, + # so start with a `null` list of edges. + var to_remove: nullable Array[E] = null + for x in te.dfroms do var xe = self.elements[x] if xe.tos.has(f) then - te.dfroms.remove(x) + if to_remove == null then to_remove = new Array[E] + to_remove.add x xe.dtos.remove(t) end end - for x in fe.dtos.to_a do + if to_remove != null then + for x in to_remove do te.dfroms.remove(x) + to_remove.clear + end + + for x in fe.dtos do var xe = self.elements[x] if xe.froms.has(t) then xe.dfroms.remove(f) - fe.dtos.remove(x) + if to_remove == null then to_remove = new Array[E] + to_remove.add x end end + if to_remove != null then + for x in to_remove do fe.dtos.remove(x) + end + fe.dtos.add t te.dfroms.add f end @@ -226,21 +243,26 @@ class POSet[E: Object] # Write the POSet as a graphviz digraph. # - # Nodes are identified with their `to_s`. + # Nodes are labeled with their `to_s` so homonymous nodes may appear. # Edges are unlabeled. - fun write_dot(f: OStream) + fun write_dot(f: Writer) do f.write "digraph \{\n" + var ids = new HashMap[E, Int] + for x in elements.keys do + ids[x] = ids.length + end for x in elements.keys do var xstr = x.to_s.escape_to_dot - f.write "\"{xstr}\";\n" + var nx = "n{ids[x]}" + f.write "{nx}[label=\"{xstr}\"];\n" var xe = self.elements[x] for y in xe.dtos do - var ystr = y.to_s.escape_to_dot + var ny = "n{ids[y]}" if self.has_edge(y,x) then - f.write "\"{xstr}\" -> \"{ystr}\"[dir=both];\n" + f.write "{nx} -> {ny}[dir=both];\n" else - f.write "\"{xstr}\" -> \"{ystr}\";\n" + f.write "{nx} -> {ny};\n" end end end @@ -253,8 +275,7 @@ class POSet[E: Object] # See `write_dot` for details. fun show_dot do - var f = new OProcess("dot", "-Txlib") - f.write "\}\n" + var f = new ProcessWriter("dot", "-Txlib") write_dot(f) f.close f.wait @@ -375,7 +396,7 @@ end # # ... # t.in_some_relation.greaters # ~~~ -class POSetElement[E: Object] +class POSetElement[E] # The poset self belong to var poset: POSet[E]