diff --git a/lib/algo/algo.mli b/lib/algo/algo.mli
index a9a1741fd4af61926dc61336de6fdf6bbd130347..352842b0805faf9ccd8bf60e1a4d6a9195b37f3b 100644
--- a/lib/algo/algo.mli
+++ b/lib/algo/algo.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 11/10/2021 (at 14:38) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/10/2021 (at 23:39) by Erwan Jahier> *)
 (** {1 The Algorithm programming Interface}
 
     A SASA process is an instance of an algorithm defined via this
@@ -51,7 +51,8 @@ type 's state_init_fun = int -> string -> 's
 (** {3 Potential function}
 
     Let the user define what the potential of a configuration is.
-    Used to explore best/worst case daemons (--worst-daemon)
+    Used to explore best/worst case daemons (e.g., --greedy-daemon,
+    or --exhaustive-daemon)
 *)
 
 type pid = string
@@ -244,8 +245,8 @@ val register : 's to_register -> unit
     None is fine. This is mandatory only if one wants to define initial values
     in the dot file.
 
-    Defining a copy that is not the identity is necessary if the state is not
-    functional (e.g., if it contains an array or an Hashtbl).
+    Defining a copy that is not the identity is necessary if the state is opaque
+    (e.g., if it contains an array or an Hashtbl).
 
     In the file "state.ml" does not exist in the current directory, a skeleton
     is generated.
diff --git a/lib/sasacore/daemon.ml b/lib/sasacore/daemon.ml
index cd95b78d20535afe8e4e87aaae5151fa7100242b..58b61ff7e5c1bf84834963f8488d6ab8d66bd5c2 100644
--- a/lib/sasacore/daemon.ml
+++ b/lib/sasacore/daemon.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 14/10/2021 (at 15:47) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/10/2021 (at 23:20) by Erwan Jahier> *)
 
 (* Enabled processes (with its enabling action + neighbors) *)           
 type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action
@@ -171,5 +171,6 @@ let (f: bool -> bool -> DaemonType.t -> 'v Process.t list ->
        get_activate_val al pl, al
     | Custom -> custom all pl enab get_action_value
 
+    | ExhaustCentralSearch
     | ExhaustSearch -> assert false (* SNO *)
   )
diff --git a/lib/sasacore/daemonType.ml b/lib/sasacore/daemonType.ml
index 400719828306167f97c4415c07743af4ef7a789f..a269c5308b11561261581e4f7983b33acd1aba3c 100644
--- a/lib/sasacore/daemonType.ml
+++ b/lib/sasacore/daemonType.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 16/10/2021 (at 15:07) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/10/2021 (at 23:16) by Erwan Jahier> *)
 
 type t =
   | Synchronous (* select all actions *) 
@@ -8,7 +8,8 @@ type t =
   | Custom (* enable/actions are communicated via stdin/stdout in RIF *)
   | Greedy (* always choose the set that maximize the potential function *)
   | GreedyCentral (* Ditto, but chooses one action only *)
-  | ExhaustSearch (* *)
+  | ExhaustSearch (* Explore all possible paths *)
+  | ExhaustCentralSearch (* Explore all possible paths of central daemons *)
 
   (* not yet implemented *)  
   | Bad of int (* try  to choose the  set actions that  maximize the
diff --git a/lib/sasacore/sasArg.ml b/lib/sasacore/sasArg.ml
index 087aa88dbb9da5b67c8197e26dcf1e3ae1b02a84..44238c5087d5f82408e099b9fad2b15440040b8f 100644
--- a/lib/sasacore/sasArg.ml
+++ b/lib/sasacore/sasArg.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 14/10/2021 (at 15:47) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/10/2021 (at 23:33) by Erwan Jahier> *)
 
 
 type t = {
@@ -8,6 +8,7 @@ type t = {
   mutable verbose: int;
   mutable daemon: DaemonType.t;
   mutable rif: bool;
+  mutable output_file_name: string option;
   mutable no_data_file: bool;
   mutable quiet: bool;
   mutable ifi: bool;
@@ -41,6 +42,7 @@ let (make_args : unit -> t) =
       verbose = 0;
       daemon = DaemonType.Distributed;
       rif = false;
+      output_file_name = None;
       no_data_file = false;
       quiet = false;
       ifi = false;
@@ -100,6 +102,11 @@ let myexit i = exit i
 let (mkoptab : string array -> t -> unit) = 
   fun argv args ->  
     (
+    mkopt args ["--length";"-l"] ~arg:" <int>"
+      (Arg.Int (fun i -> args.length <- i))
+      ["Maximum number of steps to be done (" ^
+       (string_of_int args.length) ^ " by default).\n"];
+
     mkopt args  ["--synchronous-daemon";"-sd"]
       (Arg.Unit(fun () -> args.daemon <- DaemonType.Synchronous))
       ["Use a Synchronous daemon"];
@@ -121,20 +128,24 @@ let (mkoptab : string array -> t -> unit) =
       (Arg.Unit(fun () -> args.daemon <- DaemonType.Custom;args.rif <- true))
       ["Use a Custom daemon (forces --rif)"];
 
-    mkopt args  ["--greedy-central-daemon";"-gcd"]
-      (Arg.Unit(fun () -> args.daemon <- DaemonType.GreedyCentral))
-      ["Use the central daemon that maximizes the potential function";
-       "for the next step (greedy). Performs |enabled| trials)"];
-
     mkopt args  ["--greedy-daemon";"-gd"]
       (Arg.Unit(fun () -> args.daemon <- DaemonType.Greedy))
-      ["Use the daemon that maximizes the potential function";
-       "for the next step (greedy). Performs 2^|enabled| trials) "];
+      ["Use the daemon that maximizes the potential function at each step.";
+       "Performs 2^|enabled| trials (per step). "];
+
+    mkopt args  ["--greedy-central-daemon";"-gcd"]
+      (Arg.Unit(fun () -> args.daemon <- DaemonType.GreedyCentral))
+      ["Ditto, but restricted to central daemons. Performs |enabled| trials."];
 
     mkopt args  ["--exhaustive-daemon";"-ed"]
       (Arg.Unit(fun () -> args.daemon <- DaemonType.ExhaustSearch))
-      ["Use the daemon that maximizes the potential function. ";
-       "Performs *a lot* of trials)"];
+      ["Use the daemon that maximizes the number of steps. ";
+       "The search is stopped when the maximum number of steps has been reached ";
+       "(which is controlled by the -l/--length option)" ];
+
+    mkopt args  ["--exhaustive-central-daemon";"-ecd"]
+      (Arg.Unit(fun () -> args.daemon <- DaemonType.ExhaustCentralSearch))
+      ["Ditto, but for central daemons" ];
 
     (*     mkopt args  ["--bad-daemon";"-bd"] ~arg:" <int>" *)
     (*       (Arg.Int (fun i -> args.daemon <- DaemonType.Bad i)) *)
@@ -148,15 +159,19 @@ let (mkoptab : string array -> t -> unit) =
 
     mkopt args  ["--cores-nb";"-cn"]
       (Arg.Int(fun i -> args.cores_nb <- i))
-      ["Number of cores to use during the simulation (default is 1)"];
+      ["Number of cores to use during --init-search simulations (default is 1)"];
 
    mkopt args ~hide:true ["--rif";"-rif"]
       (Arg.Unit(fun () -> args.rif <- true))
-      ["Display only outputs on stdout (i.e., behave as a rif input file)"];
+      ["Print only outputs (i.e., behave as a rif input file)"];
 
    mkopt args  ~hide:true  ["--no-data-file";"-nd"]
       (Arg.Unit(fun () -> args.no_data_file <- true))
-      ["Do not generate any data file"];
+      ["Do not print any data"];
+
+    mkopt args  ~hide:false  ["--outfile";"-o"]
+      (Arg.String(fun fn -> args.output_file_name <- Some fn))
+      ["Generate simulation data in a file (use stdout otherwise)"];
 
     mkopt args  ["--seed";"-seed"]
       (Arg.Int(fun i -> Seed.set i))  ~arg:" <int>"
@@ -168,7 +183,7 @@ let (mkoptab : string array -> t -> unit) =
 
    mkopt args ~hide:true ["--gen-lutin-daemon";"-gld"]
       (Arg.Unit(fun () -> args.gen_lutin <- true))
-      ["Generate Lutin daemons and exit"];
+      ["Generate Lutin daemons and exit (not finished)"];
 
    mkopt args ~hide:true ["--gen-lustre-oracle-skeleton";"-glos"]
       (Arg.Unit(fun () -> args.gen_oracle <- true))
@@ -178,9 +193,9 @@ let (mkoptab : string array -> t -> unit) =
      (Arg.Unit(fun () -> args.output_algos <- true))
       ["Output the algo files used in the dot file and exit. "];
     
-   mkopt args ~hide:false ["--gen-register";"-reg"]
+   mkopt args ~hide:true ["--gen-register";"-reg"]
      (Arg.Unit(fun () -> args.gen_register <- true))
-      ["Generates the registering file and exit. "];
+      ["Generates the registering files and exit. "];
     
    mkopt args ~hide:true ["--dummy-input"]
       (Arg.Unit(fun () -> args.dummy_input <- true))
@@ -190,11 +205,6 @@ let (mkoptab : string array -> t -> unit) =
       (Arg.Unit(fun () -> args.ifi <- true))
       ["[Deprecated] make sasa ignore its first input vector"];
 
-    mkopt args ["--length";"-l"] ~arg:" <int>"
-      (Arg.Int (fun i -> args.length <- i))
-      ["Maximum number of steps to be done (" ^
-       (string_of_int args.length) ^ " by default).\n"];
-
     mkopt args ["--version";"-version";"-v"]
       (Arg.Unit (fun _ ->
            (print_string (SasaVersion.str^"-"^SasaVersion.sha^"\n");
diff --git a/lib/sasacore/sasArg.mli b/lib/sasacore/sasArg.mli
index d97784efd11332cc1ac4b19978f5696203cd6c4c..461b0cd252069b5ed8c3eaf7dccff5697aacbc37 100644
--- a/lib/sasacore/sasArg.mli
+++ b/lib/sasacore/sasArg.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 05/10/2021 (at 10:15) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/10/2021 (at 15:11) by Erwan Jahier> *)
 
 type t = {
   mutable topo: string;
@@ -7,6 +7,7 @@ type t = {
   mutable verbose: int;
   mutable daemon: DaemonType.t;
   mutable rif: bool;
+  mutable output_file_name: string option;
   mutable no_data_file: bool;
   mutable quiet: bool;
   mutable ifi: bool;
diff --git a/src/sasaMain.ml b/src/sasaMain.ml
index 61532c2917c7a5ae1333aeba7b55cb74cb42ed5e..1f0178777df53ff52c37570d84afe3b2dd82959d 100644
--- a/src/sasaMain.ml
+++ b/src/sasaMain.ml
@@ -82,7 +82,7 @@ let (simustep: out_channel -> int -> int -> string -> 'v SimuState.t -> 'v SimuS
   let verb = !Register.verbose_level > 0 in
   if verb then Printf.fprintf log "==> SasaSimuState.simustp :1: Get enable processes\n%!";
   let all, enab_ll = Sasacore.SimuState.get_enable_processes st in
-  let pot = string_of_float (SimuState.compute_potentiel st) in
+  let pot = try string_of_float (SimuState.compute_potentiel st) with _ -> "" in
   let pl = st.network in
   let leg = legitimate st in
   let st, all, enab_ll =
@@ -187,18 +187,30 @@ let sob = fun b -> if b then "t" else "f"
 let () =
   let st = Sasacore.SimuState.make true Sys.argv in
   let n = st.sasarg.length in
+  let oc_rif = match st.sasarg.output_file_name with None -> stdout | Some fn -> open_out fn in
   try
     match st.sasarg.init_search_max_trials, st.sasarg.daemon with
-    | None, ExhaustSearch ->
+    | None, (ExhaustSearch|ExhaustCentralSearch) ->
       let log = open_out (st.sasarg.topo ^ ".log") in
-      let path = ExhaustSearch.f log n st in
+      let path = ExhaustSearch.f log (st.sasarg.daemon=ExhaustCentralSearch) n st in
       List.iteri
         (fun i (enab, trig, leg, pot, conf) ->
-           Printf.printf "#step %d\n#outs %s %s %s %s %s\n" (i+1)
+           if trig <> [] then
+             update_round trig enab
+           else (* update_round requires list of the same size *)
+             update_round (List.map (fun l -> List.map (fun _ -> false) l) enab) enab;
+           List.iter (List.iter (fun b -> if b then incr moves)) trig;
+           Printf.fprintf oc_rif "#step %d\n#outs %s %s %s %s %s\n" (i)
              (StringOf.env_rif conf st.network) (bll2str enab) (bll2str trig)
              (sob leg) (string_of_float pot);
         )
-        path
+        path;
+      let i = List.length path - 1 in
+      Printf.printf
+        "\n%sThis algo reached a null potential after %i move%s, %i step%s, %i round%s.\n%!"
+        (if st.sasarg.rif then "#" else "#")
+         !moves (plur !moves) i (plur i) !rounds (plur !rounds);
+
     | None,_ ->
       ignore (simuloop stdout n n "" st)
 
@@ -214,7 +226,12 @@ let () =
         Printf.fprintf log "------------- New simu from %s\n%!"
           (StringOf.env_rif s.config s.network);
         let res =
-          try simuloop log n n "" s
+          try if st.sasarg.daemon = ExhaustSearch ||
+                 st.sasarg.daemon = ExhaustCentralSearch
+            then
+              List.length (ExhaustSearch.f log (st.sasarg.daemon=ExhaustCentralSearch) n st)
+            else
+              simuloop log n n "" s
           with error ->
             (* We consider that error here mean that a meaningless configuration
                has been tried
diff --git a/test/dijkstra-ring/config.ml b/test/dijkstra-ring/config.ml
index a640751f278ca8ba5827dbb941c1a99f4b846449..b6dc28452145c3f7a381e05e4e0901ed8803d42a 100644
--- a/test/dijkstra-ring/config.ml
+++ b/test/dijkstra-ring/config.ml
@@ -107,8 +107,8 @@ let (legitimate: pid list -> (pid -> t * (t neighbor * pid) list) -> bool) =
 
 let legitimate = Some legitimate
 
+(* init search *)
 let maxi = card () + 1
-    
 let s2n s = [I (0, s.v, maxi)]
 let n2s nl s =
   match nl with
diff --git a/test/dijkstra-ring/ring.dot b/test/dijkstra-ring/ring.dot
index b36f7cc71129a0d14531970abd5e63411b5ff1ea..5e9d65a2f97b9b40eda1aa0fe6268a8da4332701 100644
--- a/test/dijkstra-ring/ring.dot
+++ b/test/dijkstra-ring/ring.dot
@@ -1,14 +1,14 @@
 digraph ring7 {
- graph [k=3]  
-
- root [algo="root.ml" init="{root=1;c=1}" ]
- p2   [algo="p.ml" init="{root=0;c=3}" ]
- p3   [algo="p.ml" init="{root=0;c=3}" ]
- p4   [algo="p.ml" init="{root=0;c=2}" ]
- p5   [algo="p.ml" init="{root=0;c=2}" ]
- p6   [algo="p.ml" init="{root=0;c=1}" ]
- p7   [algo="p.ml" init="{root=0;c=1}" ]
- p8   [algo="p.ml" init="{root=0;c=0}" ]
-
- root -> p2 -> p3 -> p4 -> p5 -> p6 -> p7 -> p8 -> root 
+	graph 
+	
+	root [algo="root.ml" init="{root=1;c=1}" ]
+	p2   [algo="p.ml" init="{root=0;c=3}" ]
+	p3   [algo="p.ml" init="{root=0;c=3}" ]
+	p4   [algo="p.ml" init="{root=0;c=2}" ]
+	p5   [algo="p.ml" init="{root=0;c=2}" ]
+	p6   [algo="p.ml" init="{root=0;c=1}" ]
+	p7   [algo="p.ml" init="{root=0;c=1}" ]
+	p8   [algo="p.ml" init="{root=0;c=0}" ]
+	
+	root -> p2 -> p3 -> p4 -> p5 -> p6 -> p7 -> p8 -> root 
 }
diff --git a/test/skeleton/ring.dot b/test/skeleton/ring.dot
index 80cff9f13c7134d3d5f00c5b0a9e06e7fdee50d4..bacf56c5919691c28fbb9f0178a43c4dbdfca30f 100644
--- a/test/skeleton/ring.dot
+++ b/test/skeleton/ring.dot
@@ -1,11 +1,11 @@
 graph ring {
- p1 [algo="some_algo.ml"]
- p2 [algo="some_algo.ml"]
- p3 [algo="some_algo.ml"]
- p4 [algo="some_algo.ml"]
- p5 [algo="some_algo.ml"]
- p6 [algo="some_algo.ml"]
- p7 [algo="some_algo.ml"]
+ p1 [algo="p.ml"]
+ p2 [algo="p.ml"]
+ p3 [algo="p.ml"]
+ p4 [algo="p.ml"]
+ p5 [algo="p.ml"]
+ p6 [algo="p.ml"]
+ p7 [algo="p.ml"]
 
  p1 -- p2 -- p3 -- p4 -- p5 -- p6 -- p7 -- p1 
 }
diff --git a/test/toy-example-sum/state.ml b/test/toy-example-sum/state.ml
index 522a32ef8bdc70a0105f0bfbc3db52aad36a07fa..d889696e15f111e7bdb41dbe642c548ed17b6a23 100644
--- a/test/toy-example-sum/state.ml
+++ b/test/toy-example-sum/state.ml
@@ -12,6 +12,11 @@ let (to_string: (t -> string)) =
   fun s ->
     Printf.sprintf "input=%d sub=%d res=%d"  s.input s.sub s.res
 
+let (to_string: (t -> string)) =
+  fun s ->
+    Printf.sprintf "{pid=%s ; input=%d}" s.pid  s.input
+
+
 let of_string: (string -> t) option =
   Some (fun s ->
         Scanf.sscanf s "{pid=%s ; input=%d}"