diff --git a/lib/sasacore/exhaustSearch.ml b/lib/sasacore/exhaustSearch.ml
index d56251dd0608967866e9e2adb190d481f0f7484f..f7dd442f2adbe4cf37eef1c652decfaf197b1342 100644
--- a/lib/sasacore/exhaustSearch.ml
+++ b/lib/sasacore/exhaustSearch.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 01/03/2023 (at 15:10) by Erwan Jahier> *)
+(* Time-stamp: <modified the 17/03/2023 (at 22:14) by Erwan Jahier> *)
 
 open LocalSearch
 
@@ -24,12 +24,14 @@ let best = ref None
 let pot_init = ref max_float
 
 let dfs = ref false
+let bfs = ref false
 
 let priority n =
   let d = float_of_int n.d in
-  match !best, !dfs with
-  | None, _ | _, true -> if n.pot <= 0.0 then d else d -. (1.0 /. (n.pot/.delta))
-  | Some b, false ->  d +. n.pot *. (b /. !pot_init)
+  match !best, !dfs, !bfs with
+  | None, _, false | _, true, _ -> if n.pot <= 0.0 then d else d -. (1.0 /. (n.pot/.delta))
+  | Some b, false, false -> d +. n.pot *. (b /. !pot_init)
+  | _,_, true -> -. d
 
 let _priority n =
   let d = float_of_int n.d in
@@ -76,6 +78,7 @@ let (bnb : out_channel -> bool -> 'v ss ->
      (bool list list * bool list list * bool * float * 'v Conf.t) list) =
   fun log central st0 ->
   dfs := st0.sasarg.es_dfs;
+  bfs := st0.sasarg.es_bfs;
   let max_step = st0.sasarg.length in
   let cpt = ref 0 in
   let cpt_of_last_improvement = ref 0 in (* to measure the progress of the search*)
diff --git a/lib/sasacore/sasArg.ml b/lib/sasacore/sasArg.ml
index c4331d13f095e05354adad247a1e231cec565d4c..82120d4e7314e5fa1a82fc0f03a9dd83b81a64e8 100644
--- a/lib/sasacore/sasArg.ml
+++ b/lib/sasacore/sasArg.ml
@@ -1,7 +1,7 @@
-(* Time-stamp: <modified the 15/03/2023 (at 15:59) by Erwan Jahier> *)
+(* Time-stamp: <modified the 24/03/2023 (at 15:40) by Erwan Jahier> *)
 
 type init_search =
-   No_init_search | Local of int | Global of int  | Annealing of int
+   No_init_search | Local of int * int | Global of int  | Annealing of int
 
 type t = {
   mutable topo: string;
@@ -13,7 +13,9 @@ type t = {
   (* for exhaustive daemon only *)
   mutable es_stop_if_no_progress: int option;
   mutable es_dfs: bool;
+  mutable es_bfs: bool;
   mutable es_tabu_mode: bool;
+  mutable is_tabu_mode: bool;
   mutable es_continue_after_best: bool;
   mutable es_dont_cut: bool;
   mutable rif: bool;
@@ -53,7 +55,9 @@ let (make_args : unit -> t) =
       daemon = DaemonType.Distributed;
       es_stop_if_no_progress = None;
       es_dfs = false;
+      es_bfs = false;
       es_tabu_mode = true;
+      is_tabu_mode = true;
       es_continue_after_best = false;
       es_dont_cut= false;
       rif = false;
@@ -173,12 +177,20 @@ let (mkoptab : string array -> t -> unit) =
 
     mkopt args  ["--es-dfs"]
       (Arg.Unit(fun () -> args.es_dfs <- true))
-      ["Use a depth first search to exploration." ];
+      ["Use a depth first search to perform the exploration." ];
+
+    mkopt args  ~hide:true ["--es-bfs"]
+      (Arg.Unit(fun () -> args.es_bfs <- true))
+      ["Use a breadth first search to perform the exploration." ];
 
     mkopt args  ["--es-no-tabu"]
       (Arg.Unit(fun () -> args.es_tabu_mode <- false))
       ["Do not use Tabu list during the exhaustive search." ];
 
+    mkopt args  ["--is-no-tabu"]
+      (Arg.Unit(fun () -> args.is_tabu_mode <- false))
+      ["Do not use Tabu list during the initial configuration search." ];
+
     mkopt args  ~hide:true ["--es-continue-when-best-sol-found"]
       (Arg.Unit(fun () -> args.es_continue_after_best <- true))
       ["Do not stop when |path(sol)|=pot(init): this is necessary when E.x phi'(c)>0 (pseudo pot)" ];
@@ -193,13 +205,19 @@ let (mkoptab : string array -> t -> unit) =
     (*       ["Use a  daemon that tries  to maximize the  potential function, "; *)
     (*         "considering sub-graphs of a given maximal size"]; *)
     mkopt args  ["--local-init-search";"-is"]
-      (Arg.Int(fun i -> args.init_search <- Local i))
+      (Arg.Int(fun i ->
+           match args.init_search with
+           | Global g -> args.init_search <- Local (g,i)
+           | _ ->  args.init_search <- Local (0,i)))
       ["Use local search algorithms to find an initial configuration that pessimize ";
        "the step number. The argument is the maximum number of trials to do the search. ";
        "Require the state_to_nums Algo.to_register field to be defined."]  ~arg:" <int>";
 
     mkopt args  ["--global-init-search";"-gis"]
-      (Arg.Int(fun i -> args.init_search <- Global i))
+      (Arg.Int(fun i ->
+           match args.init_search with
+           | Local (_,l) -> args.init_search <- Local (i,l)
+           | _ ->  args.init_search <- Global i))
       ["Use global (i.e., completely random)  search to find an initial configuration ";
        "that pessimize the step number. The argument is the maximum number of trials";
        " to do the search. "]  ~arg:" <int>";
@@ -271,7 +289,7 @@ let (mkoptab : string array -> t -> unit) =
       ["Display the version ocaml version sasa was compiled with and exit."];
 
     mkopt args  ["--quiet";"-q"]
-      (Arg.Unit (fun () -> args.quiet <- true))   ["Set the quiet mode"];
+      (Arg.Unit (fun () -> args.quiet <- true))   ["Set the quiet mode (for batch)"];
 
     mkopt args  ["--verbose";"-vl"] ~arg:" <int>"
       (Arg.Int (fun i -> args.verbose <- i))   ["Set the verbose level"];
diff --git a/lib/sasacore/sasArg.mli b/lib/sasacore/sasArg.mli
index a134b188dc218d6f269b51e9eaa0e39aa5047b1f..7a53ead9e1263834aeb3d5694476fe75365c091c 100644
--- a/lib/sasacore/sasArg.mli
+++ b/lib/sasacore/sasArg.mli
@@ -1,7 +1,7 @@
-(* Time-stamp: <modified the 01/03/2023 (at 12:20) by Erwan Jahier> *)
+(* Time-stamp: <modified the 24/03/2023 (at 15:16) by Erwan Jahier> *)
 
 type init_search =
-   No_init_search | Local of int | Global of int  | Annealing of int
+   No_init_search | Local of int * int | Global of int  | Annealing of int
 
 type t = {
   mutable topo: string;
@@ -11,7 +11,9 @@ type t = {
   mutable daemon: DaemonType.t;
   mutable es_stop_if_no_progress: int option;
   mutable es_dfs: bool;
+  mutable es_bfs: bool;
   mutable es_tabu_mode: bool;
+  mutable is_tabu_mode: bool;
   mutable es_continue_after_best: bool;
   mutable es_dont_cut: bool;
   mutable rif: bool;
diff --git a/lib/sasacore/worstInit.ml b/lib/sasacore/worstInit.ml
index 17827b399f1af6c2f3331fa10f78268c7dff48ee..8ff9a482d6192a5695218ef34b54e49d157a3018 100644
--- a/lib/sasacore/worstInit.ml
+++ b/lib/sasacore/worstInit.ml
@@ -1,8 +1,8 @@
-(* Time-stamp: <modified the 25/01/2023 (at 15:24) by Erwan Jahier> *)
+(* Time-stamp: <modified the 24/03/2023 (at 23:02) by Erwan Jahier> *)
 
 open Register
 
-type 's node = { st : 's ; d : int ; cost : int ; cpt : int }
+type 's search_node = { st : 's ; d : int ; cost : int ; cpt : int }
 type point = value Array.t
 
 let debug = false
@@ -161,7 +161,7 @@ open LocalSearch
 
 
 module ValueArrayNode = struct
-  type t = value array node
+  type t = value array search_node
   let compare n1 n2 = compare n2.cost n1.cost
 end
 
@@ -179,6 +179,105 @@ let _point2str p =
   Array.fold_right (fun value acc -> (value2str value)::acc)  p []
   |> String.concat ";"
 
+open SimuState
+
+(* mix local and global search, a la simulating annealing, with one round *)
+let _succ_far_and_close dmax log cpt step_cpt percent_done cost ss_init n =
+  let beam_size = max 50 ss_init.sasarg.cores_nb in
+  let percent_close = ((tf !cpt) /. (tf dmax)) ** 2.0 in
+  let percent_far = 1.0 -. percent_close in
+
+  let far_nb = max 1 (ti ((tf beam_size) *. percent_far) / 6) in
+  let close_nb = max 1 (ti ((tf beam_size) *. percent_close) / 6) in
+  incr step_cpt;
+  let pl = (choose far_nb n.st (one_dim_succ Close)) @
+           (choose far_nb n.st (ran_dim_succ Close)) @
+           (choose far_nb n.st (all_dim_succ Close)) @
+           (choose close_nb n.st (one_dim_succ Far)) @
+           (choose close_nb n.st (ran_dim_succ Far)) @
+           (choose close_nb n.st (all_dim_succ Far))
+  in
+  let new_cpt, res =
+    map_local_fold
+      ~f: (fun p -> cost p, p)
+      ~fold:(fun (cpt,nl) (c,p) ->
+          assert(dmax <> 0);
+          let n_percent_done = if dmax < 100 then 1 else cpt / (dmax / 100) in
+          if n_percent_done <> !percent_done  && not (ss_init.sasarg.quiet) then (
+            percent_done := n_percent_done;
+            Printf.printf "%d%% of the %d simulations have been tryied so far...\r%!"
+              n_percent_done dmax
+          );
+          Printf.fprintf log "At depth %d, cost=%d\n%!" (n.d+1) c;
+          cpt+1,{ d=n.d+1; cost=c; st=p ; cpt = cpt}::nl
+        )
+      (!cpt, [])
+      pl
+  in
+  Printf.fprintf log "fchc: cpt=%d->%d cost=[%s]\n%!" !cpt new_cpt
+    (String.concat "," (List.map (fun n -> string_of_int n.cost) res));
+  cpt:=new_cpt;
+  res
+
+(* purely local search *)
+let succ_close dmax log cpt step_cpt percent_done cost ss_init n =
+  let beam_size = max 50 ss_init.sasarg.cores_nb in
+  let close_nb = max 1 (ti ((tf beam_size)) / 3) in
+  incr step_cpt;
+  let pl = (choose close_nb n.st (one_dim_succ Far)) @
+           (choose close_nb n.st (ran_dim_succ Far)) @
+           (choose close_nb n.st (all_dim_succ Far))
+  in
+  let new_cpt, res =
+    map_local_fold
+      ~f: (fun p -> cost p, p)
+      ~fold:(fun (cpt,nl) (c,p) ->
+          assert(dmax <> 0);
+          let n_percent_done = if dmax < 100 then 1 else cpt / (dmax / 100) in
+          if n_percent_done <> !percent_done && not (ss_init.sasarg.quiet) then (
+            percent_done := n_percent_done;
+            Printf.printf "%d%% of the %d simulations have been tryied so far...\r%!"
+              n_percent_done dmax
+          );
+          Printf.fprintf log "At depth %d, cost=%d\n%!" (n.d+1) c;
+          cpt+1,{ d=n.d+1; cost=c; st=p ; cpt = cpt}::nl
+        )
+      (!cpt, [])
+      pl
+  in
+  Printf.fprintf log "fchc: cpt=%d->%d cost=[%s]\n%!" !cpt new_cpt
+    (String.concat "," (List.map (fun n -> string_of_int n.cost) res));
+  cpt:=new_cpt;
+  res
+
+
+(**********************************************************************)
+(* Use hashed configuration + int set to implement Tabu list.
+
+nb 1 : the evaluation of each initial config is (generally) costy, so
+   this set should remain small => no need to drop elements
+
+nb 2 : using a hash function is not safe, but clashes are
+- unlikely (cf nb 1)
+- not critical  : configurations  are created at  random, and  only a
+   very small fraction of the  set of possible configurations will be
+   tried anyway. So if a config is wrongly rejected, it is not a big deal
+ *)
+
+module IntSet = Set.Make(Int)
+let (tabu_add : 's search_node -> IntSet.t -> IntSet.t) =
+  fun n tabu ->
+  IntSet.add (Hashtbl.hash n) tabu
+
+let (tabu_mem : 's search_node -> IntSet.t -> bool) =
+  fun n tabu ->
+  IntSet.mem (Hashtbl.hash n) tabu
+
+let empty_tabu_list = IntSet.empty
+
+(**********************************************************************)
+
+
 (* First Choice Hill Climbing: a  successor is chosen at random (using
    some  heuristics), and  became  the  current state  if  its cost  is
    better.
@@ -187,7 +286,7 @@ let _point2str p =
    heuristics.   The probability  of  each heuristic  evolves, but  is
    never null.  *)
 let (fchc : out_channel -> ('v SimuState.t -> int) -> 'v SimuState.t -> int
-        -> 'v SimuState.t) =
+     -> 'v SimuState.t) =
   fun log run ss_init dmax ->
   let cpt = ref 0 in
   let step_cpt = ref 1 in
@@ -195,54 +294,15 @@ let (fchc : out_channel -> ('v SimuState.t -> int) -> 'v SimuState.t -> int
   let pinit = ss_to_point ss_init in
   let percent_done = ref 0 in
   Functory.Cores.set_number_of_cores ss_init.sasarg.cores_nb;
+  let visiting, visited =
+    match ss_init.sasarg.is_tabu_mode with
+    | false -> (fun _ x -> x), (fun _ _ -> false)
+    | true -> tabu_add, tabu_mem
+  in
   let g =
     {
-      init = ({ st = pinit ; d = 0 ; cost = cost pinit ; cpt = 0 }, Q.empty, ());
-      succ = (fun n ->
-          (* let beam_size = min 50 (max 1 (dmax / 10)) in *)
-          (* let beam_size = min m (max 1 (dmax - !cpt - 2)) in *)
-          (* let beam_size = max 1 (dmax / (10 * !step_cpt)) in (* 10% of the points to simulate. *)
-
-          let beam_size_part0 = beam_size / 6 in
-          let beam_size_part1 = max 1 beam_size_part0 in
-
-             *)
-          let beam_size = max 50 ss_init.sasarg.cores_nb in
-          let percent_close = ((tf !cpt) /. (tf dmax)) ** 2.0 in
-          let percent_far = 1.0 -. percent_close in
-
-          let far_nb = max 1 (ti ((tf beam_size) *. percent_far) / 6) in
-          let close_nb = max 1 (ti ((tf beam_size) *. percent_close) / 6) in
-          incr step_cpt;
-          let pl = (choose far_nb n.st (one_dim_succ Close)) @
-                   (choose far_nb n.st (ran_dim_succ Close)) @
-                   (choose far_nb n.st (all_dim_succ Close)) @
-                   (choose close_nb n.st (one_dim_succ Far)) @
-                   (choose close_nb n.st (ran_dim_succ Far)) @
-                   (choose close_nb n.st (all_dim_succ Far))
-          in
-          let new_cpt, res =
-            map_local_fold
-              ~f: (fun p -> cost p, p)
-              ~fold:(fun (cpt,nl) (c,p) ->
-                  assert(dmax <> 0);
-                  let n_percent_done = if dmax < 100 then 1 else cpt / (dmax / 100) in
-                  if n_percent_done <> !percent_done then (
-                    percent_done := n_percent_done;
-                    Printf.printf "%d%% of the %d simulations have been tryied so far...\r%!"
-                      n_percent_done dmax
-                  );
-                  Printf.fprintf log "At depth %d, cost=%d\n%!" (n.d+1) c;
-                  cpt+1,{ d=n.d+1; cost=c; st=p ; cpt = cpt}::nl
-              )
-              (!cpt, [])
-              pl
-          in
-          Printf.fprintf log "fchc: cpt=%d->%d cost=[%s]\n%!" !cpt new_cpt
-            (String.concat "," (List.map (fun n -> string_of_int n.cost) res));
-          cpt:=new_cpt;
-          res
-      );
+      init = ({ st = pinit ; d = 0 ; cost = cost pinit ; cpt = 0 }, Q.empty, empty_tabu_list);
+      succ = succ_close dmax log cpt step_cpt percent_done cost ss_init ;
       stop = (fun _ _n -> !cpt >= dmax);
       is_goal = (fun _n -> true);
       push = (fun tv n ->
@@ -250,46 +310,57 @@ let (fchc : out_channel -> ('v SimuState.t -> int) -> 'v SimuState.t -> int
             (n.cost) (Q.size tv);
           Q.add n.cpt n tv);
       pop = (fun tv -> match Q.pop tv with None -> None | Some((i,x),t) ->
-             Printf.fprintf log "Poping a point of cost %d (simu #%d)\n%!" x.cost i;
-             Some(x, t));
-      visiting = (fun _ x -> x);
-      visited  = (fun _ _ -> false);
+          Printf.fprintf log "Poping a point of cost %d (simu #%d)\n%!" x.cost i;
+          Some(x, t));
+      visiting;
+      visited;
       cut  = (fun pn n -> if pn.cost > n.cost then (
           Printf.fprintf log "%d: cut a point at depth %d of cost %d < %d\n%!"
             !cpt n.d n.cost pn.cost;
           true
-      )
+        )
           else false
-      );
+        );
     }
   in
+
   let rec run_more psol more =
-      ( match more (Some psol) with
-        | LocalSearch.NoMore ->
-          (* occurs if all successors are cut *)
+    ( match more (Some psol) with
+      | LocalSearch.NoMore ->
+        (* occurs if all successors are cut *)
+        run_more psol more
+      | LocalSearch.Stopped ->
+        Printf.printf "\nThe worst initial configuration costs %d :" psol.cost;
+        point_to_ss psol.st ss_init
+      | LocalSearch.Sol (nsol, more) ->
+        if nsol.cost > psol.cost then (
+          if ss_init.sasarg.quiet then
+            Printf.printf "data: %d %d %d\n%!" nsol.cost nsol.cpt nsol.d
+          else
+            Printf.printf "Hey, I've found a conf of cost %d! (simu #%d, depth %d)\n%!"
+              nsol.cost nsol.cpt nsol.d;
+          run_more nsol more
+        ) else (
           run_more psol more
-        | LocalSearch.Stopped ->
-          Printf.printf "\nThe worst initial configuration costs %d :" psol.cost;
-          point_to_ss psol.st ss_init
-        | LocalSearch.Sol (nsol, more) ->
-            if nsol.cost > psol.cost then (
-              Printf.printf "Hey, I've found a conf of cost %d! (simu #%d, depth %d)\n%!"
-                nsol.cost nsol.cpt nsol.d;
-              run_more nsol more
-            ) else (
-              run_more psol more
-            )
-      )
+        )
+    )
 
   in
   match LocalSearch.run g None with
   | LocalSearch.Stopped -> assert false (* SNO *)
   | LocalSearch.NoMore-> assert false (* SNO *)
-  | LocalSearch.Sol (sol, more) -> run_more sol more
+  | LocalSearch.Sol (sol, more) ->
+    if ss_init.sasarg.quiet then
+      Printf.printf "data: %d %d %d\n%!" sol.cost sol.cpt sol.d
+      else
+        Printf.printf "Hey, I've found a conf of cost %d! (simu #%d, depth %d)\n%!"
+          sol.cost sol.cpt sol.d;
+    run_more sol more
 
 open Topology
 open SimuState
 open Process
+
 (* generate a new random configuration using the user init functions *)
 let reinit_simu g ss =
   let pl = List.map2
@@ -320,18 +391,25 @@ let (global : out_channel -> ('v SimuState.t -> int) -> 'v SimuState.t -> int
       let res = run ss in
       Printf.fprintf log "simu %d, cost=%d\n%!" cpt res;
       if res > worst then (
-        Printf.printf "Hey, I've found a conf of cost %d! (simu #%d)\n%!" res cpt;
+        if ss_init.sasarg.quiet then
+          Printf.printf "data: %d %d\n%!" res cpt
+        else
+          Printf.printf "Hey, I've found a conf of cost %d! (simu #%d)\n%!" res cpt;
         ss, res
       )
       else
         ss_worst, worst
     in
     let n_percent_done = if dmax < 100 then 1 else cpt / (dmax / 100) in
-    if n_percent_done <> !percent_done then (
+    if n_percent_done <> !percent_done && not (ss_init.sasarg.quiet) then (
       percent_done := n_percent_done;
       Printf.printf "%d%% of the %d simulations have been tryied so far...\r%!"
         n_percent_done dmax
     );
-    if cpt > dmax then ss_worst else loop (cpt+1) (ss_worst, worst)
+    if cpt > dmax then (
+      Printf.printf "\nThe worst initial configuration costs %d :" worst;
+      ss_worst
+    )
+    else loop (cpt+1) (ss_worst, worst)
   in
   loop 1 (ss_init, run ss_init)
diff --git a/src/sasaMain.ml b/src/sasaMain.ml
index ea2ee657e45020dda1e01d2af976d25bf5d1a482..46ef799cfdf2833cdbccac3dc860a02f6c39721a 100644
--- a/src/sasaMain.ml
+++ b/src/sasaMain.ml
@@ -204,13 +204,13 @@ let () =
       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 "#")
-         Round.s.moves (plur Round.s.moves) i (plur i) Round.s.cpt (plur Round.s.cpt);
+        Round.s.moves (plur Round.s.moves) i (plur i) Round.s.cpt (plur Round.s.cpt);
 
     | No_init_search, _ ->
       ignore (simuloop stdout n n "" st)
 
     | Annealing _, _ -> assert false (* TODO *)
-    | (Local maxt|Global maxt) , _ ->
+    | (Local _ |Global _) , _ ->
       let log = open_out (st.sasarg.topo ^ ".log") in
       let newdot_fn = (Filename.chop_extension st.sasarg.topo) ^ "_wi.dot" in
       let newdot = open_out newdot_fn in
@@ -224,9 +224,9 @@ let () =
         let res =
           try if st.sasarg.daemon = ExhaustSearch ||
                  st.sasarg.daemon = ExhaustCentralSearch
-          then
+            then
               List.length (ExhaustSearch.f log (st.sasarg.daemon=ExhaustCentralSearch) st)
-          else
+            else
               simuloop log n n "" s
           with error ->
             (* We consider that error here mean that a meaningless configuration
@@ -247,16 +247,19 @@ let () =
           failwith(Printf.sprintf
                      "Maximum simulation length reached. Something went wrong or %d %s"
                      n "is not long enough (use sasa -l to try longer simulation)"
-          )
+                  )
         )
         else
           res
       in
       let st =
-        if search_kind = "local" then
-          WorstInit.fchc log run st maxt
-        else
-          WorstInit.global log  run st maxt
+        match st.sasarg.init_search with
+        | Local (maxg, maxl) ->
+          let st = if maxg=0 then st else WorstInit.global log run st maxg in
+          WorstInit.fchc log run st maxl
+        | Global maxg ->
+          WorstInit.global log  run st maxg
+        | _ -> assert false
       in
       Printf.printf  " (%s)\n%!" (StringOf.env_rif st.config st.network);
       Printf.fprintf newdot "%s\n" (SimuState.to_dot st);
@@ -266,7 +269,7 @@ let () =
       close_out log
   with
   | e ->
-     Printf.printf "%s%s\n%!" (if st.sasarg.rif then "#" else "") (Printexc.to_string e);
-     print_string "\nq\n#quit\n%!";
-     flush_all();
-     exit 2
+    Printf.printf "%s%s\n%!" (if st.sasarg.rif then "#" else "") (Printexc.to_string e);
+    print_string "\nq\n#quit\n%!";
+    flush_all();
+    exit 2