diff --git a/lib/algo/algo.mli b/lib/algo/algo.mli
index efdf853f555fdd01be52f04068cf85c0e2d662c2..6b823fc12c5fe9a378f2dfb3c6eb3979a2ec7afc 100644
--- a/lib/algo/algo.mli
+++ b/lib/algo/algo.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 25/04/2022 (at 15:40) by Erwan Jahier> *)
+(* Time-stamp: <modified the 26/05/2022 (at 12:16) by Erwan Jahier> *)
 (** {1 The Algorithm programming Interface}
 
     A SASA process is an instance of an algorithm defined via this
@@ -83,13 +83,14 @@ type 's fault_fun = int -> string -> 's -> 's
 (** Returns the neighbor processes local state *)
 val state : 's neighbor -> 's
 
-(** Returns the neighbor channel number, that let this neighbor access
-   to the content  of the current process, if its  neighbor can access
-   it.   The  channel  number  is  the  rank, starting  at 0,  in  the
-   neighbors' list.  Returns -1 if the  neighbor can not access to the
-   process, which may happen in directed graphs.
+(**  Returns the  neighbor  channel number,  that  let this  neighbor
+   access to the content of the  current process, if its neighbor can
+   access it.  The channel number is  the rank, starting at 0, in the
+   neighbors' list,  which are sorted alphabetically.   Returns -1 if
+   the neighbor  can not access to  the process, which may  happen in
+   directed graphs.
 
-   An  algorithm  that  uses  reply,   and  not  the  pid,  is  called
+   An  algorithm  that  uses  reply,  and  not  the  pid,  is  called
    semi-anonymous. It is called anonymous if it can access none. *)
 val reply : 's neighbor -> int
 
@@ -133,7 +134,7 @@ val is_out_tree : unit -> bool
   A rooted tree in a tree where one vertex is distinguished.
 
   By convention,  sasa considers a  tree to  be rooted if  exactly one
-  node id contains the string "root".
+  node id contains the string "root" or "Root".
 
   The following 4 functions only work on rooted trees
 *)
@@ -152,7 +153,7 @@ val level : string (* the node id *) -> int
 val parent : string (* the node id *) -> int option
 
 (** returns [true] iff [is_tree]  returns [true], and exactly one node
-   name contains the string "root" *)
+   name contains the string "root" or "Root" *)
 val is_rooted_tree : unit -> bool
 
 (** It is possible to set some global parameters in the dot file
diff --git a/lib/sasacore/topology.ml b/lib/sasacore/topology.ml
index de3de7d4030ff1bce5b8d963dfcf948bcd5ef2fa..60574d2189b6c4182bd7b76988322d230221592c 100644
--- a/lib/sasacore/topology.ml
+++ b/lib/sasacore/topology.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 24/05/2022 (at 23:03) by Erwan Jahier> *)
+(* Time-stamp: <modified the 30/05/2022 (at 14:49) by Erwan Jahier> *)
 
 open Graph
 open Graph.Dot_ast
@@ -68,6 +68,19 @@ let (get_init: Dot_ast.attr list -> string) =
     in
     init_list
 
+let compare_alpha_num str1 str2 =
+  (* if str1 and str2 are of the form [^0-9][0-9]+, we use the alphabetic
+     order for the first part, and the numeric order for the second part. 
+     nb : this is the case for node names generated by gg
+  *)
+    try
+      let to_int s = int_of_string (String.sub s 1 (String.length s - 1)) in
+      compare (str1.[0], to_int str1) (str2.[0], to_int str2)
+    with
+      _ -> String.compare str1 str2
+
+let compare_alpha_num_2 p1 p2 = compare_alpha_num (snd p1) (snd p2)
+
 let rec (get_weight: Dot_ast.attr -> int) =
   function
   | (Ident "weight", Some Number n)::_
@@ -145,8 +158,8 @@ let (read: string -> t) = fun f ->
        Hashtbl.add node_succ pid pid_pred
     )
     node_pred;
-  let succ str = List.sort compare (Hashtbl.find_all node_succ str) in
-  let pred str = List.sort compare (Hashtbl.find_all node_pred str) in
+  let succ str = List.sort compare_alpha_num (Hashtbl.find_all node_succ str) in
+  let pred str = List.sort compare_alpha_num_2 (Hashtbl.find_all node_pred str) in
   {
     nodes = List.rev nodes;
     succ = succ;
@@ -289,7 +302,7 @@ let is_tree : t -> bool =
   fun g ->
   (not (is_cyclic g)) && (is_connected g)
 
-let is_root_pid pid = Str.string_match (Str.regexp ".*root.*") pid 0
+let is_root_pid pid = Str.string_match (Str.regexp ".*[rR]oot.*") pid 0
 let is_root_node n = is_root_pid n.id
 
 (* cf algo.mli for the spec *)
diff --git a/test/Makefile.dot b/test/Makefile.dot
index fa1d7ae1c4080f386fb26559775875e95f0ac023..ca52b491d0e75c0baf33ef8926b8b0a0370ca168 100644
--- a/test/Makefile.dot
+++ b/test/Makefile.dot
@@ -1,4 +1,4 @@
-# Time-stamp: <modified the 02/09/2021 (at 10:38) by Erwan Jahier>
+# Time-stamp: <modified the 26/05/2022 (at 10:28) by Erwan Jahier>
 
 # Rules to generate various dot files.
 # The DECO_PATTERN variable should be defined
@@ -40,6 +40,10 @@ tree%.dot:
 	gg tree -n $* -o $@ $(SEED)
 	gg-deco $(DECO_PATTERN) $@ -o $@
 
+rtree%.dot:
+	gg tree --rooted-tree -n $* -o $@ $(SEED)
+	gg-deco $(DECO_PATTERN) $@ -o $@
+
 intree%.dot:
 	gg tree --in-tree -n $* -o $@ $(SEED)
 	gg-deco $(DECO_PATTERN) $@ -o $@
diff --git a/test/k-clustering/Makefile b/test/k-clustering/Makefile
index f97a71c398ac5cdf3c0a5bf6e72686f56b815d70..ff0ccbdd041dfb5dbd94a18ef204f4f73d6fea58 100644
--- a/test/k-clustering/Makefile
+++ b/test/k-clustering/Makefile
@@ -1,15 +1,27 @@
-# Time-stamp: <modified the 11/05/2021 (at 16:49) by Erwan Jahier>
+# Time-stamp: <modified the 30/05/2022 (at 14:49) by Erwan Jahier>
 
+DECO_PATTERN="0-:p.ml"
+-include ../Makefile.inc
+-include Makefile.untracked
+
+# dot files cannot be autommatically generated as the algo inputs a spanning tree
+-include ../Makefile.dot
 
-test: fig52_kcl.cmxs 
-	sasa -gcd  fig52_kcl.dot 
+##############################################################################
+# Non-regression tests
+
+test: fig52_kcl.cmxs fig52_kcl.rdbg-test
+	sasa -gcd  fig52_kcl.dot && make clean
+
+clean: genclean
+	rm -f fig52_kcl.ml
+
+##############################################################################
+# Other examples of use
 
 cd: fig52_kcl.cmxs 
 	sasa -cd  fig52_kcl.dot 
 
-DECO_PATTERN="0-:p.ml" 
--include ../Makefile.dot
-
 sim2chrogtk: fig52_kcl.rif
 	sim2chrogtk -ecran -in $< > /dev/null
 
@@ -19,14 +31,10 @@ gnuplot: fig52_kcl.rif
 rdbg: fig52_kcl.ml 
 	rdbg --sasa -o fig52_kcl.rif -env "sasa fig52_kcl.dot -gcd" 
 
-rdbgcd: fig52_kcl.ml 
+rdbg: fig52_kcl.ml
 	rdbg --sasa -o fig52_kcl.rif -env "sasa fig52_kcl.dot -cd" 
 
 dtree50: dtree50.cmxs
 	sasa -cd dtree50.dot
 
-clean: genclean
-	rm -f fig52_kcl.ml
 
--include ../Makefile.inc
--include Makefile.untracked
diff --git a/test/k-clustering/fig52_kcl.dot b/test/k-clustering/fig52_kcl.dot
index 8e94c2cdfaee2a0b609fe64483a27254e63930b7..8fb08ebbeaa67e70e389cb96999168ab4a6e965c 100644
--- a/test/k-clustering/fig52_kcl.dot
+++ b/test/k-clustering/fig52_kcl.dot
@@ -1,14 +1,14 @@
 digraph fig52 {
 
- root [algo="p.ml" init="{is_root=1 ; alpha=0}"]
- p2 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
- p3 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
- p4 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
- p5 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
- p6 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
- p7 [algo="p.ml"   init="{is_root=0 ; alpha=0}"]
+ root [algo="p.ml" init="{is_root=1 ; alpha=0; par=-1}"]
+ p2 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=1}"]
+ p3 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=1}"]
+ p4 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=1}"]
+ p5 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=2}"]
+ p6 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=1}"]
+ p7 [algo="p.ml"   init="{is_root=0 ; alpha=0; par=0}"]
 
  root -> p2 -> p3 -> p4 -> p5 -> p6 
  p5 -> p7
  }
- 
\ No newline at end of file
+ 
diff --git a/test/k-clustering/p.ml b/test/k-clustering/p.ml
index 7309645f94ac42cb823a103625af1b62f8408be0..490ab21ac69334180140b01835ff6accbe370042 100644
--- a/test/k-clustering/p.ml
+++ b/test/k-clustering/p.ml
@@ -3,62 +3,72 @@ Algorithm 1 of:
   A Framework for Certified Self-Stabilization
   Case Study: Silent Self-Stabilizing k-Dominating Set on a Tree
 https://hal.archives-ouvertes.fr/hal-01272158/document
+
+Encoded by Hugo Hannot
 *)
+(* nb:  it is meant to  start with a spanning  trees. The rtree%i.dot
+   rules in ../Makefile.dot generates rooted tree. We can use them as
+   spanning trees by taking advantage of  the fact that the nodes are
+   sorted alphabetically if we perform a bread-first traversal of the
+   tree : we then the just need  to consider the first neigbor as the
+   parent in the tree.  *)
 
 open Algo
 open State
    
-
-(* State predicates *)
+type s = State.t
+type sl = s list
+type n = State.t neighbor
+type nl = n list
   
-let isRoot p = p.isRoot
+let isRoot p = (state p).isRoot
 
-let (isShort: State.t -> bool) =
-  fun p -> p.alpha < k
+let (isShort: n -> bool) =
+  fun p -> (state p).alpha < k
 
-let (isTall: State.t -> bool) =
-  fun p -> p.alpha >= k
+let (isTall: n -> bool) =
+  fun p -> (state p).alpha >= k
 
 (* Actually unused *)
-let (kDominator: 'v -> bool) = 
-  fun p -> (p.alpha = k) || ((isShort p) && (isRoot p)) 
-
+let (_kDominator: 'v -> bool) = 
+  fun p -> ((state p).alpha = k) || ((isShort p) && (isRoot p)) 
 
-let (children: State.t -> State.t list -> State.t list) =
-  fun p nl ->
-  List.filter (fun q -> q.par = reply q) nl
+let (children: s -> nl -> nl) =
+  fun _p nl ->
+  List.filter (fun q -> (state q).par = reply q) nl
     
-let (shortChildren: State.t -> State.t list -> State.t list) =
+let (shortChildren: s -> nl -> nl) =
   fun p nl ->
-  let cl = List.filter (children p) nl in
-  List.filter isShort cl
+  List.filter isShort (children p nl)
 
-let (tallChildren: State.t -> State.t list -> State.t list) =
+let (tallChildren: s -> nl -> nl) =
   fun p nl ->
-  let cl = List.filter (children p) nl in
-  List.filter isTall cl
+  List.filter isTall (children p nl)
 
-let rec (max: State.t list -> int -> int) =
+let rec (max: nl -> int -> int) =
   fun sl cur ->
   match sl with
-    [] -> cur
-  | s::liste -> if (s.alpha) > cur then max liste (s.alpha) else max liste cur
-  
-let rec (min: State.t list -> int -> int) =
+  | [] -> cur
+  | n::tail ->
+    let s = state n in
+    if (s.alpha) > cur then max tail (s.alpha) else max tail cur
+
+let rec (min: nl -> int -> int) =
   fun sl cur ->
   match sl with
-    [] -> cur
-  | s::liste -> if (s.alpha) < cur then min liste (s.alpha) else min liste cur
+  | [] -> cur
+  | n::tail ->
+    let s = state n in
+    if (s.alpha) < cur then min tail (s.alpha) else min tail cur
   
-let (maxAShort: State.t -> State.t list -> int) =
+let (maxAShort: s -> nl -> int) =
   fun p nl -> max (shortChildren p nl) (-1)
 
-let (minATall: State.t -> State.t list -> int) =
+let (minATall: s -> nl -> int) =
   fun p nl -> min (tallChildren p nl) (2*k+1)
 
-let (newAlpha: State.t -> State.t neighbor list -> int) =
+let (newAlpha: s -> nl -> int) =
   fun p nl ->
-  let nl = List.map state nl in
   let mas = (maxAShort p nl) in
   let mit = (minATall p nl) in
   let res = if (mas + mit) <= (2*k - 2) then (mit + 1) else (mas + 1) in
@@ -66,16 +76,18 @@ let (newAlpha: State.t -> State.t neighbor list -> int) =
   res
 (*end macros*)
 
-let (init_state: int -> string -> State.t) =
+let (init_state: int -> string -> s) =
   fun _ pid ->
-  (* assert(is_tree()); *)
+  assert(is_rooted_tree());
   {
-    isRoot = pid = "root"; (* ZZZ: The root of the tree should be named "root"! *)
-    alpha = Random.int (2*k+1)
+    isRoot = pid = "Root"; (* ZZZ: The root of the tree should be named "Root"! *)
+    alpha = Random.int (2*k+1);
+    par = 0 (* the input tree should be sorted alphabetically (wrt a bf traversal) *)
   }   
       
-let (enable_f: State.t -> State.t neighbor list -> action list) =
+let (enable_f: s -> nl -> action list) =
   fun p nl -> if (p.alpha <> (newAlpha p nl)) then ["change_alpha"] else []
 
-let (step_f : State.t -> State.t neighbor list -> action -> State.t ) =
-  fun p nl a -> if a = "change_alpha" then {p with alpha = (newAlpha nl)} else assert false
+let (step_f : s -> nl -> action -> s) =
+  fun p nl a ->
+  if a = "change_alpha" then {p with alpha = (newAlpha p nl)} else assert false
diff --git a/test/k-clustering/state.ml b/test/k-clustering/state.ml
index 8985084259ea5adc24ce690f037f930688b111ed..00b9556c555dbaf984d68132aa80492557609844 100644
--- a/test/k-clustering/state.ml
+++ b/test/k-clustering/state.ml
@@ -5,6 +5,7 @@ let d = max_degree()
 type t = {
   isRoot:bool;
   alpha:int;
+  par:int
 }
 
 let (to_string: (t -> string)) =
@@ -13,8 +14,8 @@ let (to_string: (t -> string)) =
 
 let (of_string: (string -> t) option) =
   Some (fun s ->
-      Scanf.sscanf s "{is_root=%d ; alpha=%d}"
-        (fun i alpha -> {isRoot = (i=1) ; alpha = alpha}))
+      Scanf.sscanf s "{is_root=%d ; alpha=%d ; par=%d}"
+        (fun i alpha p -> {isRoot = (i=1) ; alpha = alpha ; par = p }))
 
 let (copy : ('v -> 'v)) = fun x -> x
 let actions = ["change_alpha"]
diff --git a/tools/gg/graphGen.ml b/tools/gg/graphGen.ml
index ae4418d38174893a3a353a297a4a8b5d3bf269e8..90e5a6e5e50428ddeb91eaa2958420e072a7a97b 100644
--- a/tools/gg/graphGen.ml
+++ b/tools/gg/graphGen.ml
@@ -250,7 +250,7 @@ let () = (
         | "HC" -> (gen_hyper_cube dir t.n)
         | "ER" -> (gen_ER dir t.n t.er)
         | "BA" -> (gen_BA dir t.n t.ba)
-        | "tree" -> (rand_tree t.tree_edge dir t.n)
+        | "tree" -> (rand_tree t.tree_edge t.rooted dir t.n)
         | "UDG" ->
            let (graph, plan) =
              gen_udg dir t.n t.qudg.width t.qudg.height t.qudg.radius
diff --git a/tools/gg/randomGraph.ml b/tools/gg/randomGraph.ml
index 6abfefa08204a2e991b4128deaf4c84dcb7113eb..cb8f62837ba044d786978ba730af59db036cc0c6 100644
--- a/tools/gg/randomGraph.ml
+++ b/tools/gg/randomGraph.ml
@@ -195,11 +195,12 @@ let (pre_rand_tree : bool -> GraphGen_arg.tree_edge -> node_succ_t ->
     (fun n -> Hashtbl.find_all node_succ n),
     (fun n -> Hashtbl.find_all node_pred n)
 
-let (rand_tree: GraphGen_arg.tree_edge -> bool -> int -> Topology.t) =
-  fun tree_edge directed nb ->
+let (rand_tree: GraphGen_arg.tree_edge -> bool -> bool -> int -> Topology.t) =
+  fun tree_edge _rooted directed nb ->
   let (node_succ:node_succ_t) = Hashtbl.create nb in
   let (node_pred:node_pred_t) = Hashtbl.create nb in
-  let nodes = "root"::(create_nodes "p" (1,nb)) in
+  let node_base_name =  "p" in
+  let nodes = "Root"::(create_nodes node_base_name (1,nb)) in
   let nl = id_to_empty_nodes nodes in
   let succ, pred = pre_rand_tree directed tree_edge node_succ node_pred nodes in
   {
diff --git a/tools/gg/randomGraph.mli b/tools/gg/randomGraph.mli
index 90bdfcdd99ecbb559847525663524609382a3c1a..31116bf1ad58fbe014e18ed506c86838beabf26c 100644
--- a/tools/gg/randomGraph.mli
+++ b/tools/gg/randomGraph.mli
@@ -19,8 +19,8 @@ val gen_ER : bool -> int -> probability -> Topology.t
 val gen_BA : bool -> int -> int -> Topology.t
 
 
-(** [rand_tree n] generate a random tree of n nodes *)
-val rand_tree: GraphGen_arg.tree_edge -> bool -> int -> Topology.t
+(** [rand_tree rooted directed n] generate a random tree of n nodes *)
+val rand_tree: GraphGen_arg.tree_edge -> bool -> bool -> int -> Topology.t
 
 (** [gen_udg  nb x  y r] generate  a graph using  the Unit  Disc Graph
    model, of  n nodes.  w and  h are the  width and the height  of the