From c779951d807a10c5c1baa0a67f81d379bfecdf5a Mon Sep 17 00:00:00 2001
From: Erwan Jahier <erwan.jahier@univ-grenoble-alpes.fr>
Date: Mon, 27 Feb 2023 15:18:40 +0100
Subject: [PATCH] feat: add 2 options for exaustive searches: --es-dfs and
 --es-continue-when-best-sol-found

---
 lib/sasacore/exhaustSearch.ml | 50 +++++++++++++++++++++--------------
 lib/sasacore/sasArg.ml        | 15 +++++++++--
 lib/sasacore/sasArg.mli       |  4 ++-
 3 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/lib/sasacore/exhaustSearch.ml b/lib/sasacore/exhaustSearch.ml
index 050fbfbc..db1918f7 100644
--- a/lib/sasacore/exhaustSearch.ml
+++ b/lib/sasacore/exhaustSearch.ml
@@ -1,13 +1,13 @@
-(* Time-stamp: <modified the 08/02/2023 (at 14:57) by Erwan Jahier> *)
+(* Time-stamp: <modified the 16/02/2023 (at 09:23) by Erwan Jahier> *)
 
 open LocalSearch
 
 type 'v ss = 'v SimuState.t
-let pot = SimuState.compute_potentiel
+let pot st = if SimuState.legitimate st then 0.0 else SimuState.compute_potentiel st
 
 type node = {
   d : int;
-  cost : float;
+  cost : float; (* pot+depth *)
   pot : float;
   cpt : int;  (* => no sharing between config *)
   path : (bool list list * bool list list * bool * float * string) list;
@@ -23,11 +23,13 @@ let delta = 1.0 (* the potential decreases of at least delta at each step *)
 let best = ref None
 let pot_init = ref max_float
 
+let dfs = ref false
+
 let priority n =
   let d = float_of_int n.d in
-  match !best with
-  | None -> if n.pot <= 0.0 then d else d -. (1.0 /. (n.pot/.delta))
-  | Some b ->  d +. n.pot *. (b /. !pot_init)
+  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)
 
 let _priority n =
   let d = float_of_int n.d in
@@ -73,6 +75,7 @@ open SimuState
 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;
   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*)
@@ -90,7 +93,8 @@ let (bnb : out_channel -> bool -> 'v ss ->
         (fun al ->
            incr cpt;
            if !cpt mod (st0.sasarg.length / 100) = 0 && not st0.sasarg.quiet then
-             Printf.printf "%d%% of steps have been tryied so far...\r%!" (!cpt / (st0.sasarg.length / 100));
+             Printf.printf "%d%% of steps have been tryied so far...\r%!"
+               (!cpt / (st0.sasarg.length / 100));
            let nst = Step.f al st in
            let pot_nst = pot nst in
            let nst_str = marshall_ss nst in
@@ -125,7 +129,7 @@ let (bnb : out_channel -> bool -> 'v ss ->
       visiting, visited
     else
       visiting,
-        (*         (fun _ v -> v), (fun _ _ -> false) *)
+      (*         (fun _ v -> v), (fun _ _ -> false) *)
       (fun n v -> if not (StrMap.mem n.st v) then incr visited_config_cpt; false)
   in
   let pot0 = pot st0 in
@@ -139,18 +143,19 @@ let (bnb : out_channel -> bool -> 'v ss ->
   in
   let pb =
     {
-      init = { st=marshall_ss st0; d=0; pot=pot0 ; cpt=0; path=[]; cost=pot0 }, Q.empty, StrMap.empty;
+      init = { st=marshall_ss st0; d=0; pot=pot0 ; cpt=0; path=[]; cost=pot0 },
+             Q.empty, StrMap.empty;
       succ = successors;
       stop = (fun _ _node ->
           if !cpt >= max_step then (
-            pf log "Max number of step reached (%d). Queue size=%d; visited confirations=%d\n%!"
+            pf log "W: Max number of step reached (%d). |Q|=%d; visited config=%d\n%!"
               !cpt !qsize !visited_config_cpt;
-            pf stdout "Max number of step reached (%d); use -l to change it\n%!" !cpt ;
+            pf stdout "W: Max number of step reached (%d); use -l to change it\n%!" !cpt;
             true
           ) else if not_progressing st0.sasarg.es_stop_if_no_progress then (
-            pf log "The exhaustive search did not progress for a long time (%d steps): Abort.\n%!"
+            pf log "W: The search is stuck for a long time (%d steps): Abort.\n%!"
               (!cpt - !cpt_of_last_improvement);
-            pf stdout "The exhaustive search did not progress for a long time (%d steps): Abort.\n%!"
+            pf stdout "W: The search is stuck for a long time (%d steps): Abort.\n%!"
               (!cpt - !cpt_of_last_improvement);
             true
           ) else (
@@ -161,7 +166,7 @@ let (bnb : out_channel -> bool -> 'v ss ->
       push = (fun tv n ->
           qsize := Q.size tv;
           if do_log args then
-            pf log " ==> Pushing a node (#%d) of cost %.1f (pot=%.1f ; d=%d ; queue size=%d ; priority=%.3f)\n%!"
+            pf log " ==> Pushing a node (#%d) of cost %.1f (pot=%.1f; d=%d; |Q|=%d; priority=%.3f)\n%!"
               n.cpt n.cost n.pot n.d  !qsize (priority n);
           Q.add n.cpt n tv);
       pop = (fun tv ->
@@ -185,7 +190,8 @@ let (bnb : out_channel -> bool -> 'v ss ->
   let format sol =
     let msg = Printf.sprintf "  - the worst path is of length %d
   - %f seconds have been spent in the priority queue
-  - %d configurations have been (re-)visited\n%!" sol.d !cumulated_Q_time !visited_config_cpt
+  - %d configurations have been (re-)visited
+  - %d steps have been performed\n%!" sol.d !cumulated_Q_time !visited_config_cpt !cpt
     in
     print_string msg;
     output_string log msg;
@@ -202,8 +208,9 @@ let (bnb : out_channel -> bool -> 'v ss ->
       (List.rev path)
   in
   let rec run_more psol more =
-    if psol.d = int_of_float !pot_init then (
-      pf log "The length of this solution is equal to the initial potential (%.1f). %s\n" !pot_init
+    if psol.d = int_of_float !pot_init && not args.es_continue_after_best then (
+      pf log "The length of this solution is equal to the initial potential (%.1f). %s\n"
+        !pot_init
         "\n\tIt is therefore the best we can find. \n\tStop the search.\n%!";
       pf stdout "The length of this solution is equal to the initial potential (%.1f). %s\n" !pot_init
         "\n\tIt is therefore the best we can find. \n\tStop the search.\n%!";
@@ -214,9 +221,10 @@ let (bnb : out_channel -> bool -> 'v ss ->
       match more_sol with
       | LocalSearch.Stopped
       | LocalSearch.NoMore ->
+        pf log "longuest_path: %d %d %s\n" (psol.d) !cpt (if !dfs then "dfs" else "promising");
         if more_sol = LocalSearch.Stopped then (
-          pf log "The search stopped before the end\n";
-          pf stdout "The search stopped before the end\n"
+          pf log "W: The search stopped before the end\n";
+          pf stdout "W: The search stopped before the end\n"
         )
         else (
           pf log "All possible paths have been explored!\n";
@@ -227,7 +235,8 @@ let (bnb : out_channel -> bool -> 'v ss ->
         if nsol.cost > psol.cost then (
           pf stdout "==> [New longuest path] I've found a path of length %d! (after #%d steps)\n%!" (nsol.d) !cpt;
           update_Q_now := true;
-          pf log "==> [New longuest path] I've found a path of length %d! (after #%d steps)\n%!"    (nsol.d) !cpt;
+          pf log    "==> [New longuest path] I've found a path of length %d! (after #%d steps)\n%!" (nsol.d) !cpt;
+          pf log    "longuest_path: %d %d %s\n"  (nsol.d) !cpt (if !dfs then "dfs" else "promising");
           best := Some (float_of_int nsol.d);
           cpt_of_last_improvement := nsol.cpt;
           run_more nsol more
@@ -244,6 +253,7 @@ let (bnb : out_channel -> bool -> 'v ss ->
   | LocalSearch.NoMore-> failwith "There is no solution!"
   | LocalSearch.Sol (sol, more) ->
     pf log "==> The first solution has a path of length %d (step #%d)\n%!" sol.d !cpt;
+    pf log    "longuest_path: %d %d %s\n" (sol.d) !cpt (if !dfs then "dfs" else "promising");
     pf stdout "==> The first solution has a path of length %d (step #%d)\n%!" sol.d !cpt;
     update_Q_now := true;
     best := Some (float_of_int sol.d);
diff --git a/lib/sasacore/sasArg.ml b/lib/sasacore/sasArg.ml
index 542f422a..72a818ad 100644
--- a/lib/sasacore/sasArg.ml
+++ b/lib/sasacore/sasArg.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 08/02/2023 (at 15:19) by Erwan Jahier> *)
+(* Time-stamp: <modified the 09/02/2023 (at 09:46) by Erwan Jahier> *)
 
 type init_search =
    No_init_search | Local of int | Global of int  | Annealing of int
@@ -12,8 +12,9 @@ type t = {
 
   (* for exhaustive daemon only *)
   mutable es_stop_if_no_progress: int option;
+  mutable es_dfs: bool;
   mutable es_tabu_mode: bool;
-
+  mutable es_continue_after_best: bool;
   mutable rif: bool;
   mutable output_file_name: string option;
   mutable no_data_file: bool;
@@ -50,7 +51,9 @@ let (make_args : unit -> t) =
       verbose = 0;
       daemon = DaemonType.Distributed;
       es_stop_if_no_progress = None;
+      es_dfs = false;
       es_tabu_mode = true;
+      es_continue_after_best = false;
       rif = false;
       output_file_name = None;
       no_data_file = false;
@@ -162,10 +165,18 @@ let (mkoptab : string array -> t -> unit) =
       (Arg.Int(fun i -> args.es_stop_if_no_progress <- Some i))
       ["Abort the exhaustive search if not progressing (i.e., when #step>step(last sol)x<int>)." ] ~arg:" <int>";
 
+    mkopt args  ["--es-dfs"]
+      (Arg.Unit(fun () -> args.es_dfs <- true))
+      ["Use a depth first search to 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  ~hide:true ["--es-continue-when-best-sol-found"]
+      (Arg.Unit(fun () -> args.es_continue_after_best <- true))
+      ["For experiment purposes: do not stop when |path(sol)|=pot(init)" ];
+
 
     (*     mkopt args  ["--bad-daemon";"-bd"] ~arg:" <int>" *)
     (*       (Arg.Int (fun i -> args.daemon <- DaemonType.Bad i)) *)
diff --git a/lib/sasacore/sasArg.mli b/lib/sasacore/sasArg.mli
index 9c72b14b..97dbd043 100644
--- a/lib/sasacore/sasArg.mli
+++ b/lib/sasacore/sasArg.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 08/02/2023 (at 14:24) by Erwan Jahier> *)
+(* Time-stamp: <modified the 09/02/2023 (at 09:46) by Erwan Jahier> *)
 
 type init_search =
    No_init_search | Local of int | Global of int  | Annealing of int
@@ -10,7 +10,9 @@ type t = {
   mutable verbose: int;
   mutable daemon: DaemonType.t;
   mutable es_stop_if_no_progress: int option;
+  mutable es_dfs: bool;
   mutable es_tabu_mode: bool;
+  mutable es_continue_after_best: bool;
   mutable rif: bool;
   mutable output_file_name: string option;
   mutable no_data_file: bool;
-- 
GitLab