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}"