diff --git a/lib/algo/algo.ml b/lib/algo/algo.ml index 7a1f9a13a011da08a884cee4a1f5057173f88a5a..91d0bed03bf7664114694c28beea997162baa880 100644 --- a/lib/algo/algo.ml +++ b/lib/algo/algo.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 02/09/2020 (at 10:30) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/10/2020 (at 15:55) by Erwan Jahier> *) open Sasacore (* Process programmer API *) @@ -43,9 +43,9 @@ type 's enable_fun = 's -> 's neighbor list -> action list type 's step_fun = 's -> 's neighbor list -> action -> 's type 's state_init_fun = int -> string -> 's type 's fault_fun = int -> string -> 's -> 's -type 's legitimate_fun = pid list -> (pid -> 's * 's neighbor list) -> bool +type 's legitimate_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> bool -type 's potential_fun = pid list -> (pid -> 's * 's neighbor list) -> float +type 's potential_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> float type 's algo_to_register = { algo_id: string; @@ -72,11 +72,11 @@ let (to_reg_neigbor : 's Register.neighbor -> 's neighbor) = spid = n.Register.spid; reply = n.Register.reply; weight = n.Register.weight; - } + } -let (to_reg_info : 's * 's Register.neighbor list -> 's * 's neighbor list) = +let (to_reg_info : 's * ('s Register.neighbor * pid) list -> 's * ('s neighbor *pid) list) = fun (s, nl) -> - s, List.map to_reg_neigbor nl + s, List.map (fun (n,pid) -> to_reg_neigbor n, pid) nl let (to_reg_enable_fun : 's enable_fun -> 's Register.neighbor list -> 's -> action list) = @@ -89,17 +89,17 @@ let (to_reg_step_fun : 's step_fun -> f s (List.map to_reg_neigbor nl) a let (to_reg_potential_fun : - 's potential_fun -> pid list -> (pid -> 's * 's Register.neighbor list) -> float) = + 's potential_fun -> pid list -> (pid -> 's * ('s Register.neighbor * pid) list) -> float) = fun pf pidl f -> let nf pid = to_reg_info (f pid) in pf pidl nf let (to_reg_legitimate_fun : - 's legitimate_fun -> pid list -> (pid -> 's * 's Register.neighbor list) -> bool) = + 's legitimate_fun -> pid list -> (pid -> 's * ('s Register.neighbor * pid) list) -> bool) = fun lf pidl from_pid -> let n_from_pid pid = let s, nl = from_pid pid in - s, List.map to_reg_neigbor nl + s, List.map (fun (n,pid) -> to_reg_neigbor n, pid) nl in lf pidl n_from_pid diff --git a/lib/algo/algo.mli b/lib/algo/algo.mli index 9460dc002a6d1a06060459c49033430850cb0e19..2cc2ca7c0632728dca383835896cb095fc21b9cb 100644 --- a/lib/algo/algo.mli +++ b/lib/algo/algo.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 16/09/2020 (at 15:42) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/10/2020 (at 15:30) by Erwan Jahier> *) (** {1 The Algorithm programming Interface} A SASA process is an instance of an algorithm defined via this @@ -53,12 +53,12 @@ type 's state_init_fun = int -> string -> 's *) type pid = string -type 's potential_fun = pid list -> (pid -> 's * 's neighbor list) -> float +type 's potential_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> float (** {3 Legitimate Configurations} *) -type 's legitimate_fun = pid list -> (pid -> 's * 's neighbor list) -> bool +type 's legitimate_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> bool (** By default, legitimate configurations (i.e., global states) are silent ones. But this is not true for all algorithms. Predicates of this type are used to redefine what's a legitimate configuration diff --git a/lib/sasa/sasaRun.ml b/lib/sasa/sasaRun.ml index ba174a44949996ffe04c8eb904f605ecd4e184f4..627c29961bb83ff48f63f302b8390abf04dc8511 100644 --- a/lib/sasa/sasaRun.ml +++ b/lib/sasa/sasaRun.ml @@ -45,146 +45,151 @@ let (compute_potentiel: ('v Process.t * 'v Register.neighbor list) list -> | Some user_pf -> let pidl = List.map (fun (p,_) -> p.Process.pid) p_nl_l in let get_info pid = + let nl = snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) in Env.get ne pid, - snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) + List.map (fun n -> n, n.Register.pid) nl in let p = (user_pf pidl get_info) in [("potential", Data.F p)] - + +(* The nl local state needs to be updated w.r.t. e *) +let update_p_nl_l e p_nl_l = List.map + (fun (p,nl) -> p, List.map (Sasacore.Main.update_neighbor_env e) nl) + p_nl_l + let (make_do: string array -> SasArg.t -> ('v Process.t * 'v Register.neighbor list) list -> 'v Env.t -> RdbgPlugin.t) = fun argv args p_nl_l e -> - let pl = fst (List.split p_nl_l) in - let prog_id = Printf.sprintf "%s (with sasa Version %s)" - (String.concat " " (Array.to_list argv)) SasaVersion.str - in - let vntl_i = - List.map (fun (vn,vt) -> vn, Data.type_of_string vt) - (Sasacore.Main.get_inputs_rif_decl args pl) - in - let vntl_o = - List.map (fun (vn,vt) -> vn, Data.type_of_string vt) - (Sasacore.Main.get_outputs_rif_decl args pl) - in - let vntl_o = - if Register.get_potential () = None then vntl_o else ("potential", Data.Real)::vntl_o in - let vntl_o = ("silent", Data.Bool)::vntl_o in - let pre_enable_processes_opt = ref None in - let sasa_env = ref e in - let reset () = - pre_enable_processes_opt := None; - sasa_env := e - in - (* Do the same job as SasaMain.simustep *) - let (step: RdbgPlugin.sl -> RdbgPlugin.sl) = - fun sl_in -> - let e = !sasa_env in - match !pre_enable_processes_opt with - | None -> ( (* the first step *) - (* 1: Get enable processes *) - let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in - let sasa_nenv = from_sasa_env p_nl_l e in - let pot_sl = compute_potentiel p_nl_l e in + let pl = fst (List.split p_nl_l) in + let prog_id = Printf.sprintf "%s (with sasa Version %s)" + (String.concat " " (Array.to_list argv)) SasaVersion.str + in + let vntl_i = + List.map (fun (vn,vt) -> vn, Data.type_of_string vt) + (Sasacore.Main.get_inputs_rif_decl args pl) + in + let vntl_o = + List.map (fun (vn,vt) -> vn, Data.type_of_string vt) + (Sasacore.Main.get_outputs_rif_decl args pl) + in + let vntl_o = + if Register.get_potential () = None then vntl_o else ("potential", Data.Real)::vntl_o in + let vntl_o = ("silent", Data.Bool)::vntl_o in + let pre_enable_processes_opt = ref None in + let sasa_env = ref e in + let reset () = + pre_enable_processes_opt := None; + sasa_env := e + in + (* Do the same job as SasaMain.simustep *) + let (step: RdbgPlugin.sl -> RdbgPlugin.sl) = + fun sl_in -> + let e = !sasa_env in + let p_nl_l = update_p_nl_l e p_nl_l in + match !pre_enable_processes_opt with + | None -> ( (* the first step *) + (* 1: Get enable processes *) + let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in + let sasa_nenv = from_sasa_env p_nl_l e in + let pot_sl = compute_potentiel p_nl_l e in + let silent = List.for_all (fun b -> not b) (List.flatten enab_ll) in + pre_enable_processes_opt := Some(pnall, enab_ll); + ("silent", Data.B silent)::pot_sl @ sasa_nenv @ (get_sl_out true pl enab_ll) + ) + | Some (pre_pnall, pre_enab_ll) -> + (* 2: read the actions from the outside process, i.e., from sl_in *) + let _, pnal = Daemon.f args.dummy_input + (args.verbose > 0) args.daemon p_nl_l e pre_pnall pre_enab_ll + (get_action_value sl_in) + in + (* 3: Do the steps *) + let ne = Sasacore.Step.f pnal e in + let new_p_nl_l = update_p_nl_l ne p_nl_l in + let sasa_nenv = from_sasa_env p_nl_l ne in + (* 1': Get enable processes *) + let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l ne in let silent = List.for_all (fun b -> not b) (List.flatten enab_ll) in + let pot_sl = compute_potentiel new_p_nl_l ne in pre_enable_processes_opt := Some(pnall, enab_ll); - ("silent", Data.B silent)::pot_sl @ sasa_nenv @ (get_sl_out true pl enab_ll) - ) - | Some (pre_pnall, pre_enab_ll) -> - (* 2: read the actions from the outside process, i.e., from sl_in *) - let _, pnal = Daemon.f args.dummy_input - (args.verbose > 0) args.daemon p_nl_l e pre_pnall pre_enab_ll - (get_action_value sl_in) - in - (* 3: Do the steps *) - let ne = Sasacore.Step.f pnal e in - let sasa_nenv = from_sasa_env p_nl_l ne in - (* 1': Get enable processes *) - let new_p_nl_l = - List.map (fun (p,nl) -> - p, List.map (Sasacore.Main.update_neighbor_env ne) nl ) p_nl_l - in - let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l ne in + sasa_env := ne; + ("silent", Data.B silent)::pot_sl @ sasa_nenv @ (get_sl_out true pl enab_ll) + in + let (step_internal_daemon: RdbgPlugin.sl -> RdbgPlugin.sl) = + fun sl_in -> + (* in this mode, sasa does not play first *) + let e = !sasa_env in + let p_nl_l = update_p_nl_l e p_nl_l in + (* 1: Get enable processes *) + let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in + let pot_sl = compute_potentiel p_nl_l e in let silent = List.for_all (fun b -> not b) (List.flatten enab_ll) in - let pot_sl = compute_potentiel new_p_nl_l ne in - pre_enable_processes_opt := Some(pnall, enab_ll); - sasa_env := ne; - ("silent", Data.B silent)::pot_sl @ sasa_nenv @ (get_sl_out true pl enab_ll) - in - let (step_internal_daemon: RdbgPlugin.sl -> RdbgPlugin.sl) = - fun sl_in -> - (* in this mode, sasa does not play first *) - let e = !sasa_env in - (* 1: Get enable processes *) - let pnall, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in - let silent = List.for_all (fun b -> not b) (List.flatten enab_ll) in - if silent then ( - ("silent", Data.B true)::(from_sasa_env p_nl_l e) @ (get_sl_out true pl enab_ll) - ) - else - (* 2: read the actions from the outside process, i.e., from sl_in *) - let activate_val, pnal = Daemon.f args.dummy_input - (args.verbose > 0) args.daemon p_nl_l e pnall enab_ll - (get_action_value sl_in) - in - (* 3: Do the steps *) - let ne = Sasacore.Step.f pnal e in - let pot_sl = compute_potentiel p_nl_l ne in - sasa_env := ne; - ("silent", Data.B false)::pot_sl @ - (from_sasa_env p_nl_l e) @ (get_sl_out true pl enab_ll) @ - (get_sl_out false pl activate_val) - in - let step = if args.daemon = Daemon.Custom then step else step_internal_daemon in - let ss_table = Hashtbl.create 10 in - let step_dbg sl_in ctx cont = - let sl_out = step sl_in in - { ctx with - (* RdbgEvent.nb = 0; *) - (* RdbgEvent.step = 0; (* we are actually in the middle of the first step! *) *) - RdbgEvent.depth = ctx.RdbgEvent.depth + 1; - RdbgEvent.kind = RdbgEvent.Exit; - RdbgEvent.lang = "sasa"; - RdbgEvent.sinfo = None; - RdbgEvent.name = "sasa"; - RdbgEvent.inputs = vntl_i; - RdbgEvent.outputs = vntl_o; - RdbgEvent.locals = []; - RdbgEvent.data = sl_in@sl_out; - RdbgEvent.next = ( - fun () -> - let ctx = { ctx with RdbgEvent.nb = 1 + ctx.RdbgEvent.nb } in - cont sl_out ctx ); + if silent then ( + ("silent", Data.B true)::(from_sasa_env p_nl_l e) @ (get_sl_out true pl enab_ll) + ) + else + (* 2: read the actions from the outside process, i.e., from sl_in *) + let activate_val, pnal = Daemon.f args.dummy_input + (args.verbose > 0) args.daemon p_nl_l e pnall enab_ll + (get_action_value sl_in) + in + (* 3: Do the steps *) + let ne = Sasacore.Step.f pnal e in + sasa_env := ne; + ("silent", Data.B false)::pot_sl @ + (from_sasa_env p_nl_l e) @ (get_sl_out true pl enab_ll) @ + (get_sl_out false pl activate_val) + in + let step = if args.daemon = Daemon.Custom then step else step_internal_daemon in + let ss_table = Hashtbl.create 10 in + let step_dbg sl_in ctx cont = + let sl_out = step sl_in in + { ctx with + (* RdbgEvent.nb = 0; *) + (* RdbgEvent.step = 0; (* we are actually in the middle of the first step! *) *) + RdbgEvent.depth = ctx.RdbgEvent.depth + 1; + RdbgEvent.kind = RdbgEvent.Exit; + RdbgEvent.lang = "sasa"; + RdbgEvent.sinfo = None; + RdbgEvent.name = "sasa"; + RdbgEvent.inputs = vntl_i; + RdbgEvent.outputs = vntl_o; + RdbgEvent.locals = []; + RdbgEvent.data = sl_in@sl_out; + RdbgEvent.next = ( + fun () -> + let ctx = { ctx with RdbgEvent.nb = 1 + ctx.RdbgEvent.nb } in + cont sl_out ctx ); + } + in + let (mems_in : Data.subst list) = [] in + let (mems_out : Data.subst list) = [] in + { + id = prog_id; + inputs = vntl_i; + outputs= vntl_o; + reset=(fun () -> reset()); + kill=(fun _ -> flush stdout; flush stderr); + init_inputs=mems_in; + init_outputs=mems_out; + step=step; + step_dbg = step_dbg; + save_state = (fun i -> + let prgs = Random.get_state () in + (* Printf.eprintf "Save state %i from sasa\n%!" i; *) + Hashtbl.replace ss_table i + (prgs, !sasa_env, !pre_enable_processes_opt) + ); + restore_state = (fun i -> + match Hashtbl.find_opt ss_table i with + | Some (prgs, e, pepo) -> + Random.set_state prgs; + (* Printf.eprintf "Restore state %i from sasa\n%!" i; *) + sasa_env := e; pre_enable_processes_opt := pepo + | None -> + Printf.eprintf "Cannot restore state %i from sasa\n" i; + flush stderr + ); } - in - let (mems_in : Data.subst list) = [] in - let (mems_out : Data.subst list) = [] in - { - id = prog_id; - inputs = vntl_i; - outputs= vntl_o; - reset=(fun () -> reset()); - kill=(fun _ -> flush stdout; flush stderr); - init_inputs=mems_in; - init_outputs=mems_out; - step=step; - step_dbg = step_dbg; - save_state = (fun i -> - let prgs = Random.get_state () in - (* Printf.eprintf "Save state %i from sasa\n%!" i; *) - Hashtbl.replace ss_table i - (prgs, !sasa_env, !pre_enable_processes_opt) - ); - restore_state = (fun i -> - match Hashtbl.find_opt ss_table i with - | Some (prgs, e, pepo) -> - Random.set_state prgs; - (* Printf.eprintf "Restore state %i from sasa\n%!" i; *) - sasa_env := e; pre_enable_processes_opt := pepo - | None -> - Printf.eprintf "Cannot restore state %i from sasa\n" i; - flush stderr - ); - } let (make: string array -> RdbgPlugin.t) = diff --git a/lib/sasacore/env.mli b/lib/sasacore/env.mli index 0b4204ce2a09bc87259951014829d702db023dd2..c22d152dfd974b0be63355edb270f245e23dfd73 100644 --- a/lib/sasacore/env.mli +++ b/lib/sasacore/env.mli @@ -3,11 +3,12 @@ type 'v t val init: unit -> 'v t -(** [set env process_id var_name var_value] *) +(** [set env process_id var_value] *) val set: 'v t -> string -> 'v -> 'v t -(** [get env process_id var_name] *) +(** [get env process_id] *) val get: 'v t -> string -> 'v -(** Use registered copy function to returns an (hopefully) fresh copy *) +(** Use registered copy function to returns an hopefully (if the user + provided copy state function is correct) fresh copy *) val get_copy: 'v t -> string -> 'v diff --git a/lib/sasacore/evil.ml b/lib/sasacore/evil.ml index 82de548cf061ed2014452f6788bd66b8835bd938..5aee11602d62f078cbf70eb425efa09de7768ba7 100644 --- a/lib/sasacore/evil.ml +++ b/lib/sasacore/evil.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 28/09/2020 (at 11:31) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/10/2020 (at 16:06) by Erwan Jahier> *) type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action @@ -129,8 +129,9 @@ let (worst: bool -> 'v Env.t -> ('v Process.t * 'v Register.neighbor list) list let pidl = List.map (fun (p,_) -> p.Process.pid) p_nl_l in let ne = Step.f pnal e in let get_info pid = + let nl = snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) in Env.get ne pid, - snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) + List.map (fun n -> n, n.Register.pid) nl in user_pf pidl get_info in @@ -170,8 +171,9 @@ let (worst_central: bool -> 'v Env.t -> ('v Process.t * 'v Register.neighbor lis let pidl = List.map (fun (p,_) -> p.Process.pid) p_nl_l in let ne = Step.f [pna] e in let get_info pid = + let nl = snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) in Env.get ne pid, - snd (List.find (fun (p,_) -> p.Process.pid = pid) p_nl_l) + List.map (fun n -> n, n.Register.pid) nl in user_pf pidl get_info in diff --git a/lib/sasacore/main.ml b/lib/sasacore/main.ml index 22cd51b82c393a2960f8844328536011de3f0252..0f79e98d27cc11fb0222bd48ff454a3c6d5c5a1a 100644 --- a/lib/sasacore/main.ml +++ b/lib/sasacore/main.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 01/09/2020 (at 17:15) by Erwan Jahier> *) +(* Time-stamp: <modified the 15/10/2020 (at 15:53) by Erwan Jahier> *) open Register @@ -274,9 +274,13 @@ let (make : bool -> string array -> 'v t) = Printf.eprintf "==> get input var names...\n%!"; List.iter (fun (vn,vt) -> Printf.printf "\"%s\":%s " vn vt) inputs_decl; Printf.printf "\n%!"; + let pot = match Register.get_potential () with + | None -> "" + | Some _ -> "potential:real" + in if !Register.verbose_level > 0 then Printf.eprintf "==> get output var names...\n%!"; - Printf.printf "#outputs %s\n" (env_rif_decl args pl); + Printf.printf "#outputs %s %s\n" (env_rif_decl args pl) pot; Printf.printf "\n%!"; flush_all() ); diff --git a/lib/sasacore/register.ml b/lib/sasacore/register.ml index 350e829acf2b44d5a4990cd7e501764fd5c40032..2c646c476484fee0808e3b41fcc1dce14e84313a 100644 --- a/lib/sasacore/register.ml +++ b/lib/sasacore/register.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 02/09/2020 (at 10:31) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/10/2020 (at 15:37) by Erwan Jahier> *) type 's neighbor = { state: 's ; @@ -14,9 +14,9 @@ type 's enable_fun = 's neighbor list -> 's -> action list type 's step_fun = 's neighbor list -> 's -> action -> 's type pid = string -type 's potential_fun = pid list -> (pid -> 's * 's neighbor list) -> float +type 's potential_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> float type 's fault_fun = int -> string -> 's -> 's -type 's legitimate_fun = string list -> (string -> 's * 's neighbor list) -> bool +type 's legitimate_fun = string list -> (string -> 's * ('s neighbor * pid) list) -> bool type 's internal_tables = { init_state: (string, Obj.t) Hashtbl.t; diff --git a/lib/sasacore/register.mli b/lib/sasacore/register.mli index 2b93b06b5d586d9f7b44af524fe3dba32e678a3c..e405b94d6cbb8e3020a9760482a03e6ca7446e7f 100644 --- a/lib/sasacore/register.mli +++ b/lib/sasacore/register.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 02/09/2020 (at 10:32) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/10/2020 (at 15:36) by Erwan Jahier> *) (** This module duplicates and extends the Algo module with get_* functions. @@ -23,8 +23,8 @@ type 's step_fun = 's neighbor list -> 's -> action -> 's type 's fault_fun = int -> string -> 's -> 's type pid = string -type 's potential_fun = pid list -> (pid -> 's * 's neighbor list) -> float -type 's legitimate_fun = string list -> (string -> 's * 's neighbor list) -> bool +type 's potential_fun = pid list -> (pid -> 's * ('s neighbor * pid) list) -> float +type 's legitimate_fun = string list -> (string -> 's * ('s neighbor * pid) list) -> bool val reg_init_state : algo_id -> (int -> string -> 's) -> unit val reg_enable : algo_id -> 's enable_fun -> unit diff --git a/lib/sasacore/step.ml b/lib/sasacore/step.ml index 55068b9738ee99cd6d96af8f414180669bab711c..6e62b4bb787f0b3d414eb01c0713321a363dbe41 100644 --- a/lib/sasacore/step.ml +++ b/lib/sasacore/step.ml @@ -3,21 +3,18 @@ open Register open Process -let (update_neighbor_env: 'v Env.t -> 'v Register.neighbor -> 'v Register.neighbor) = - fun e n -> - { n with state = Env.get_copy e n.Register.pid } let (update_env: 'v Env.t -> 'v Process.t * 'v -> 'v Env.t) = fun e (p, st) -> Env.set e p.pid st -let (f : ('v Process.t * 'v Register.neighbor list * action) list -> 'v Env.t - -> 'v Env.t) = +let (f : ('v Process.t * 'v Register.neighbor list * action) list -> 'v Env.t -> 'v Env.t) = fun pnal e -> let lenv_list = List.map (fun (p,nl,a) -> - let nl = List.map (update_neighbor_env e) nl in + (* I perform a copy of the local env to make sure the + configuration update is atomic *) let lenv = Env.get_copy e p.pid in p, p.step nl lenv a) pnal diff --git a/lib/sasacore/step.mli b/lib/sasacore/step.mli index 0ca3da97e26f0a3064692be218c7aaccdbe217f9..436e95e3eeb6dee7300bf30c60bbe2f8f856a1fa 100644 --- a/lib/sasacore/step.mli +++ b/lib/sasacore/step.mli @@ -1,2 +1,5 @@ + +(* [f pnal e] performs a step (according to the actions in pnal) and returns a new env *) + val f : ('v Process.t * 'v Register.neighbor list * Register.action) list -> 'v Env.t -> 'v Env.t diff --git a/src/sasaMain.ml b/src/sasaMain.ml index 2062ab765e5bce0cb0f8cbb84953441b478eeb6d..0a65fcd60f77067e4f3f06fa2e0493afc10b1acd 100644 --- a/src/sasaMain.ml +++ b/src/sasaMain.ml @@ -1,8 +1,8 @@ open Sasacore -let (print_step : int -> int -> SasArg.t -> 'v Env.t -> 'v Process.t list -> string -> - bool list list -> unit) = - fun n i args e pl activate_val enab_ll -> +let (print_step : int -> int -> string -> SasArg.t -> 'v Env.t -> 'v Process.t list -> string -> + bool list list -> unit) = + fun n i pot args e pl activate_val enab_ll -> let enable_val = String.concat " " (List.map (fun b -> if b then "t" else "f") (List.flatten enab_ll)) @@ -13,17 +13,17 @@ let (print_step : int -> int -> SasArg.t -> 'v Env.t -> 'v Process.t list -> str if args.daemon = Daemon.Custom then ( (* in custom mode, to be able to talk with lurette, this should not be printed on stdout - *) + *) Printf.eprintf "\n#step %s\n" (string_of_int (n-i)) ; Printf.eprintf "%s #outs " activate_val; flush stderr; - Printf.printf "%s %s\n" (StringOf.env_rif e pl) enable_val; + Printf.printf "%s %s %s\n" (StringOf.env_rif e pl) enable_val pot; ) else ( (* rif mode, internal daemons *) if args.rif then - Printf.printf " %s %s %s\n%!" (StringOf.env_rif e pl) enable_val activate_val + Printf.printf " %s %s %s %s\n%!" (StringOf.env_rif e pl) enable_val activate_val pot else ( Printf.printf "\n#step %s\n" (string_of_int (n-i)); - Printf.printf "#outs %s %s %s\n%!" (StringOf.env_rif e pl) enable_val activate_val + Printf.printf "#outs %s %s %s %s\n%!" (StringOf.env_rif e pl) enable_val activate_val pot ); ); flush stderr; @@ -62,8 +62,10 @@ let legitimate p_nl_l e = | [] -> assert false (* sno *) | (p,nl)::tail -> if p.Process.pid = pid then + let nl = List.map (Sasacore.Main.update_neighbor_env e) nl in + let nl = List.map (fun n -> n,n.Register.pid) nl in Env.get e pid, - List.map (Sasacore.Main.update_neighbor_env e) nl + nl else from_pid tail pid in @@ -79,12 +81,35 @@ let inject_fault ff p_nl e = List.fold_left update_nodes e p_nl let plur i = if i>1 then "s" else "" - + +let (compute_potentiel: ('v Process.t * 'v Register.neighbor list) list -> + 'v Env.t -> string) = + fun p_nl_l ne -> + match Register.get_potential () with + | None -> "" + | Some user_pf -> + let pidl = List.map (fun (p,_) -> p.Process.pid) p_nl_l in + let get_info pid = + let nl = match List.find_opt (fun (p,_) -> p.Process.pid = pid) p_nl_l with + None -> failwith (Printf.sprintf "no %s found in %s" pid + (String.concat "," (List.map (fun (p,_) -> p.Process.pid) p_nl_l))) + | Some (_,x) -> x + in + Env.get ne pid, + List.map (fun n -> n, n.Register.pid) nl + in + let p = (user_pf pidl get_info) in + string_of_float p + + let (simustep: int -> int -> SasArg.t -> string -> ('v Process.t * 'v Register.neighbor list) list -> 'v Env.t -> 'v Env.t * string) = fun n i args activate_val p_nl_l e -> (* 1: Get enable processes *) + if !Register.verbose_level > 0 then + Printf.eprintf "==> SasaMain.simustep :1: Get enable processes\n%!"; let all, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in + let pot = compute_potentiel p_nl_l e in let pl = fst(List.split p_nl_l) in let e, all, enab_ll = if @@ -92,41 +117,43 @@ let (simustep: int -> int -> SasArg.t -> string -> then ( match Register.get_fault () with | None -> - print_step n i args e pl activate_val enab_ll; - incr rounds; - raise (Silent (n-i)) + print_step n i pot args e pl activate_val enab_ll; + incr rounds; + raise (Silent (n-i)) | Some ff -> - print_step n i args e pl activate_val enab_ll; - let str = if args.rif then "#" else "" in - Printf.eprintf "\n%sThis algo is silent after %i move%s, %i step%s, %i round%s.\n" - str !moves (plur !moves) (n-i) (plur (n-i)) !rounds (plur !rounds); - Printf.eprintf "%s==> Inject a fault\n%!" str; - let e = inject_fault ff p_nl_l e in - let all, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in - e, all, enab_ll + print_step n i pot args e pl activate_val enab_ll; + let str = if args.rif then "#" else "" in + Printf.eprintf "\n%sThis algo is silent after %i move%s, %i step%s, %i round%s.\n" + str !moves (plur !moves) (n-i) (plur (n-i)) !rounds (plur !rounds); + Printf.eprintf "%s==> Inject a fault\n%!" str; + let e = inject_fault ff p_nl_l e in + let all, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in + e, all, enab_ll ) else if legitimate p_nl_l e then ( match Register.get_fault () with | None -> - print_step n i args e pl activate_val enab_ll; - raise (Legitimate (n-i)) + print_step n i pot args e pl activate_val enab_ll; + raise (Legitimate (n-i)) | Some ff -> - print_step n i args e pl activate_val enab_ll; - let str = if args.rif then "#" else "" in - Printf.eprintf - "\n%sThis algo reached a legitimate configuration after %i move%s, %i step%s, %i round%s.\n" - str !moves (plur !moves) (n-i) (plur (n-i)) !rounds (plur !rounds); - Printf.eprintf "%s==> Inject a fault\n%!" str; - let e = inject_fault ff p_nl_l e in - let all, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in - e, all, enab_ll + print_step n i pot args e pl activate_val enab_ll; + let str = if args.rif then "#" else "" in + Printf.eprintf + "\n%sThis algo reached a legitimate configuration after %i move%s, %i step%s, %i round%s.\n" + str !moves (plur !moves) (n-i) (plur (n-i)) !rounds (plur !rounds); + Printf.eprintf "%s==> Inject a fault\n%!" str; + let e = inject_fault ff p_nl_l e in + let all, enab_ll = Sasacore.Main.get_enable_processes p_nl_l e in + e, all, enab_ll ) else e, all, enab_ll in if args.daemon = Daemon.Custom then - print_step n i args e pl activate_val enab_ll; + print_step n i pot args e pl activate_val enab_ll; (* 2: read the actions *) + if !Register.verbose_level > 0 then + Printf.eprintf "==> SasaMain.simustep : 2: read the actions\n%!"; let get_action_value = RifRead.bool (args.verbose > 1) in let next_activate_val, pnal = Daemon.f args.dummy_input (args.verbose >= 1) args.daemon p_nl_l e all enab_ll get_action_value @@ -135,15 +162,22 @@ let (simustep: int -> int -> SasArg.t -> string -> update_round next_activate_val enab_ll; let next_activate_val = bool_ll_to_string next_activate_val in (* 3: Do the steps *) - let ne = Sasacore.Step.f pnal e in + if !Register.verbose_level > 0 then + Printf.eprintf "==> SasaMain.simustep : 3: Do the steps\n%!"; if args.daemon <> Daemon.Custom then - print_step n i args e pl next_activate_val enab_ll; + print_step n i pot args e pl next_activate_val enab_ll; + let ne = Sasacore.Step.f pnal e in ne, next_activate_val let rec (simuloop: int -> int -> SasArg.t -> string -> ('v Process.t * 'v Register.neighbor list) list -> 'v Env.t -> unit) = fun n i args activate_val p_nl_l e -> + if !Register.verbose_level > 0 then Printf.eprintf "==> SasaMain.simuloop %d/%d \n%!" i n; let ne, next_activate_val = simustep n i args activate_val p_nl_l e in + let p_nl_l = List.map + (fun (p,nl) -> p, List.map (Sasacore.Main.update_neighbor_env ne) nl) + p_nl_l + in if i > 0 then simuloop n (i-1) args next_activate_val p_nl_l ne else ( print_string "#q\n"; flush stdout ) diff --git a/test/Makefile.dot b/test/Makefile.dot index e4ff29bace26af01024f247d01dff7d42c58e769..77920060e1406f77dc70dfccfc3bbb3515a434ac 100644 --- a/test/Makefile.dot +++ b/test/Makefile.dot @@ -1,4 +1,4 @@ -# Time-stamp: <modified the 14/04/2020 (at 17:16) by Erwan Jahier> +# Time-stamp: <modified the 14/10/2020 (at 21:46) by Erwan Jahier> # Rules to generate various dot files. @@ -33,6 +33,10 @@ ring%.dot: gg ring -n $* -o $@ gg-deco $(DECO_PATTERN) $@ -o $@ +dtree%.dot: + gg tree -dir -n $* -o $@ + gg-deco $(DECO_PATTERN) $@ -o $@ + cleandot: rm -f ring5* ring30* er30* er100* grid* ba100* udg* qudg* diff --git a/test/coloring/config.ml b/test/coloring/config.ml index 5a3230915315beb71fad5aa3d0e774277f7aa0f8..aa5fd985aaae3bb14c7ed2859797d3d1b58e479b 100644 --- a/test/coloring/config.ml +++ b/test/coloring/config.ml @@ -5,7 +5,7 @@ let clash_number pidl get = let clash = ref 0 in let color pid = fst (get pid) in List.iter (fun pid -> - List.iter (fun n -> if state n = color pid then incr clash) (snd (get pid))) + List.iter (fun (n,_) -> if state n = color pid then incr clash) (snd (get pid))) pidl; float_of_int !clash diff --git a/test/dijkstra-ring/config.ml b/test/dijkstra-ring/config.ml index 762edb25517cc351730c539f0891391fd9e2e8de..661adc58d02bceefdec43c4410e9b8581062be4d 100644 --- a/test/dijkstra-ring/config.ml +++ b/test/dijkstra-ring/config.ml @@ -10,6 +10,7 @@ let (legitimate: t Algo.legitimate_fun) = (* only one node is enabled *) let incr_token i pid = let s, nl = get pid in + let nl = List.map fst nl in let have_token = (if s.root then Root.enable_f s nl else P.enable_f s nl) <> [] in if have_token then i+1 else i in diff --git a/test/k-clustering/Makefile b/test/k-clustering/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cc38fd6c6e9fd7128981df40b89797d9efdafafc --- /dev/null +++ b/test/k-clustering/Makefile @@ -0,0 +1,32 @@ +# Time-stamp: <modified the 15/10/2020 (at 15:36) by Erwan Jahier> + + +test: fig52_kcl.cmxs + sasa -gcd fig52_kcl.dot + +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 + +gnuplot: fig52_kcl.rif + gnuplot-rif $< + +rdbg: fig52_kcl.ml + rdbg -o fig52_kcl.rif -env "sasa fig52_kcl.dot -gcd" + +rdbgcd: fig52_kcl.ml + rdbg -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/config.ml b/test/k-clustering/config.ml new file mode 100644 index 0000000000000000000000000000000000000000..3e8fabff253cbc2d859561c205f07c3aaafe42d4 --- /dev/null +++ b/test/k-clustering/config.ml @@ -0,0 +1,44 @@ + +open Algo +open State +open P + +let debug = false + +let rec (pot : pid -> (pid -> ('a * ('a neighbor*pid) list)) -> int -> int -> int) = + fun pid get level acc -> + (* From a pid and its level, adds to acc the potential of the tree + rooted in pid *) + let s, nl = get pid in + let nl2 = List.map fst nl in + let acc = if P.enable_f s nl2 <> [] then ( + (* if debug then Printf.printf "%s -> acc=%d+%d\n%!" pid acc level ; *) + acc+level + ) + else acc in + List.fold_left (fun acc (_, pid) -> pot pid get (level+1) acc) acc nl + + +(* The potential is defined as the sum of enabled nodes levels (the + level is 1 for root, 2 for its children, and so on *) +let (pf: pid list -> (pid -> ('a * ('a neighbor * pid) list)) -> float) = + fun pidl get -> + let root_pot = pot "root" get 1 0 in + if debug then ( + let enab pid = + let v,nl = get pid in + if P.enable_f v (List.map fst nl) = [] then + "" + else + pid + in + let enab_list = List.map enab pidl in + Printf.printf "=================> potential(%s) = %d\n%!" (String.concat "," enab_list) root_pot + ); + (* (String.concat "," (List.map (fun pid -> Printf.sprintf "%s=%b" get pid) pidl) root_pot ; *) + float_of_int root_pot + +let potential = Some pf + +let legitimate = None (* None => only silent configuration are legitimate *) +let fault = None (* None => the simulation stop once a legitimate configuration is reached *) diff --git a/test/k-clustering/fig52_kcl.dot b/test/k-clustering/fig52_kcl.dot new file mode 100644 index 0000000000000000000000000000000000000000..8e94c2cdfaee2a0b609fe64483a27254e63930b7 --- /dev/null +++ b/test/k-clustering/fig52_kcl.dot @@ -0,0 +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 -> p2 -> p3 -> p4 -> p5 -> p6 + p5 -> p7 + } + \ No newline at end of file diff --git a/test/k-clustering/my-rdbg-tuning.ml b/test/k-clustering/my-rdbg-tuning.ml new file mode 100644 index 0000000000000000000000000000000000000000..b12b09cd74c71569488cc5d47df38332619d2edf --- /dev/null +++ b/test/k-clustering/my-rdbg-tuning.ml @@ -0,0 +1,4 @@ + (* *) +#use "rdbg-cmds.ml";; +#use "../sasa-rdbg-cmds.ml";; +dot_view := fd;; diff --git a/test/k-clustering/p.ml b/test/k-clustering/p.ml new file mode 100644 index 0000000000000000000000000000000000000000..bef8df291239231ca0cf811560820fde9ecc3831 --- /dev/null +++ b/test/k-clustering/p.ml @@ -0,0 +1,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 +*) + +open Algo +open State + + +(* State predicates *) + +let isRoot p = p.isRoot + +let (isShort: 'st -> bool) = + fun p -> p.alpha < k + +let (isTall: 'st -> bool) = + fun p -> p.alpha >= k + +(* Actually unused *) +let (kDominator: 'v -> bool) = + fun p -> (p.alpha = k) || ((isShort p) && (isRoot p)) + + +let rec (shortChildren: State.t neighbor list -> State.t list) = + fun nl -> + List.filter isShort (List.map state nl) + +let rec (tallChildren: State.t neighbor list -> 'st list) = + fun nl -> + List.filter isTall (List.map state nl) + +let rec (max: 'st list -> 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: 'st list -> int -> int) = + fun sl cur -> + match sl with + [] -> cur + | s::liste -> if (s.alpha) < cur then min liste (s.alpha) else min liste cur + +let (maxAShort: 'st neighbor list -> int) = + fun nl -> max (shortChildren nl) (-1) + +let (minATall: 'st neighbor list -> int) = + fun nl -> min (tallChildren nl) (2*k+1) + +let (newAlpha: 'st neighbor list -> int) = + fun nl -> + let mas = (maxAShort nl) in + let mit = (minATall nl) in + if (mas + mit) <= (2*k - 2) then (mit + 1) else (mas + 1) + +(*end macros*) + +let (init_state: int -> string -> 'st) = + fun _ pid -> + { + isRoot = pid = "root"; (* ZZZ: The root of the tree should be named "root"! *) + alpha = Random.int (2*k+1) + } + +let (enable_f: 'st -> 'st neighbor list -> action list) = + fun p nl -> if (p.alpha <> (newAlpha nl)) then ["change_alpha"] else [] + +let (step_f : 'st -> 'st neighbor list -> action -> 'st ) = + fun p nl a -> if a = "change_alpha" then {p with alpha = (newAlpha nl)} else assert false diff --git a/test/k-clustering/state.ml b/test/k-clustering/state.ml new file mode 100644 index 0000000000000000000000000000000000000000..8985084259ea5adc24ce690f037f930688b111ed --- /dev/null +++ b/test/k-clustering/state.ml @@ -0,0 +1,23 @@ +open Algo + +let d = max_degree() + +type t = { + isRoot:bool; + alpha:int; +} + +let (to_string: (t -> string)) = + fun s -> + Printf.sprintf "alpha=%d" s.alpha + +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})) + +let (copy : ('v -> 'v)) = fun x -> x +let actions = ["change_alpha"] + +let k = 2 + diff --git a/tools/gg/graphGen.ml b/tools/gg/graphGen.ml index 4e35fd346e77cff914a22d8c0dd412906f10de5a..bab125621dbb6ae9bdafc3d7e8a7d427bef3817f 100644 --- a/tools/gg/graphGen.ml +++ b/tools/gg/graphGen.ml @@ -241,7 +241,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 dir t.n) + | "tree" -> (rand_tree t.tree_edge 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/graphGen_arg.ml b/tools/gg/graphGen_arg.ml index b18a6f3fcb31f4ffa28dd8fd3f53ee6dc238bc44..2b1282be29b72407bc6214b9a60a5d24632246ff 100644 --- a/tools/gg/graphGen_arg.ml +++ b/tools/gg/graphGen_arg.ml @@ -17,6 +17,7 @@ type qudg_arg = { type er_prob = float (*between 0 and 1*) type ba_m = int (*positive*) +type tree_edge = InTree | OutTree | InOutTree type t = { mutable outputFile: string; @@ -25,6 +26,7 @@ type t = { mutable action: action; mutable n : int; + mutable tree_edge : tree_edge; mutable grid : grid_arg; mutable er : er_prob; mutable ba : ba_m; @@ -63,6 +65,7 @@ let (make_args : unit -> t) = dotUDGrad = ""; action = "void"; + tree_edge = InTree; n = -1; grid = { width = 0; @@ -134,7 +137,7 @@ let help args tool = ( ("HC",[(["Generate a hyper-cube graph"],"")]); ("ER",[(["Generate a graph using the Erdos Renyi algo"],"")]); ("BA",[(["Generate a graph using the Barabasi–Albert algo"],"")]); - ("tree",[(["Generate an acyclic graph (tree)"],"")]); + ("tree",[(["Generate a tree"],"")]); ("UDG",[(["Generate a graph using the Unit Disc Graph algo"],"")]); ("QUDG",[(["Generate a graph using the Quasi UDG algo"],"")]); ]; @@ -180,6 +183,24 @@ let (mkoptab : string array -> t -> unit) = [([msg],"clique");([msg],"star");([msg],"ring"); ([msg],"ER");([msg],"BA");([msg],"tree");([msg],"UDG");([msg],"QUDG")]; + mkopt args ["--in-tree"] + (Arg.Unit (fun () -> match args.action with + | "tree" -> args.tree_edge <- InTree; args.directed <- true + | _ -> unexpected "--in-tree")) + [(["Generate directed in-trees (downward edges); Do the same as -dir actually "],"tree")]; + + mkopt args ["--out-tree"] + (Arg.Unit (fun () -> match args.action with + | "tree" -> args.tree_edge <- OutTree; args.directed <- true + | _ -> unexpected "--out-tree")) + [(["Generate directed out-trees (upward edges) "],"tree")]; + + mkopt args ["--in-out-tree"] + (Arg.Unit (fun () -> match args.action with + | "tree" -> args.tree_edge <- InOutTree; args.directed <- true + | _ -> unexpected "--in-out-tree")) + [(["Generate directed in-out-trees (downward+upward edges) "],"tree")]; + mkopt args ["--dimension";"-d"] ~arg:" <int>" (Arg.Int (fun n -> match args.action with | "HC"-> args.n <- n @@ -274,7 +295,7 @@ let (mkoptab : string array -> t -> unit) = mkopt args ["--directed";"-dir"] (Arg.Unit (fun () -> args.directed <- true)) - [(["NOT WORKING! Generate a directed graph."],"void")]; + [(["Generate a directed graph"],"void")]; mkopt args ["--help";"-h"] (Arg.Unit (fun () -> help args ((argv.(0))^(if args.action = "void" then "" diff --git a/tools/gg/graphGen_arg.mli b/tools/gg/graphGen_arg.mli index 5c966acf55010d85c41ed1e88210f9ecc822315b..c57eda5072298a19fcaa5235c7a189cbc8ff306f 100644 --- a/tools/gg/graphGen_arg.mli +++ b/tools/gg/graphGen_arg.mli @@ -15,6 +15,7 @@ type qudg_arg = { type er_prob = float (*between 0 and 1*) type ba_m = int (*positive*) +type tree_edge = InTree | OutTree | InOutTree type t = { mutable outputFile: string; @@ -23,6 +24,7 @@ type t = { mutable action: action; mutable n : int; + mutable tree_edge : tree_edge; mutable grid : grid_arg; mutable er : er_prob; mutable ba : ba_m; diff --git a/tools/gg/randomGraph.ml b/tools/gg/randomGraph.ml index 27af6022a61b943271ab1b2458a7295f7a60fbb0..5b4df62f9e0125bff439de2e2a2a96a25e42de25 100644 --- a/tools/gg/randomGraph.ml +++ b/tools/gg/randomGraph.ml @@ -119,27 +119,37 @@ let gen_BA : (bool -> int -> int -> Topology.t) = attributes = [] } -let pre_rand_tree : (node_succ_t -> node_id list -> (node_id -> (int * node_id) list)) = - fun node_succ -> +let pre_rand_tree : (GraphGen_arg.tree_edge -> node_succ_t -> node_id list -> + (node_id -> (int * node_id) list)) = + fun tree_edge node_succ -> function | [] -> failwith "Tree Error : You need at least one nodes in your tree" | h::t -> ignore (List.fold_left (fun acc elem -> let no = (List.nth acc (Random.int (List.length acc))) in - (Hashtbl.replace node_succ no ((1,elem)::(try Hashtbl.find node_succ no with Not_found -> [])); - Hashtbl.replace node_succ elem ((1,no)::(try Hashtbl.find node_succ elem with Not_found -> [])) - ); - (elem::acc) + (* add an option to control whether to add + - down edges + - up edges + - both + *) + if tree_edge <> GraphGen_arg.OutTree then + (Hashtbl.replace node_succ no + ((1,elem)::(try Hashtbl.find node_succ no with Not_found -> []))); + if tree_edge <> GraphGen_arg.InTree then + Hashtbl.replace node_succ elem + ((1,no)::(try Hashtbl.find node_succ elem with Not_found -> [])); + (elem::acc) ) [h] (t)); (fun n -> try Hashtbl.find node_succ n with Not_found -> []) -let (rand_tree: bool -> int -> Topology.t) = - fun directed nb -> - let (node_succ:node_succ_t) = Hashtbl.create nb and nodes = create_nodes "p" (0,nb) in +let (rand_tree: GraphGen_arg.tree_edge -> bool -> int -> Topology.t) = + fun tree_edge directed nb -> + let (node_succ:node_succ_t) = Hashtbl.create nb + and nodes = "root"::(create_nodes "p" (1,nb-1)) in let nl = id_to_empty_nodes nodes in { nodes = nl; - succ = (pre_rand_tree node_succ nodes); + succ = (pre_rand_tree tree_edge node_succ nodes); of_id = get_of_id nl; directed = directed; attributes = [] diff --git a/tools/gg/randomGraph.mli b/tools/gg/randomGraph.mli index c26f84183a0de2e4a19e2e1077c81693619ac434..63e5009441f23c8568b3fa2e7d1460c8a98a9460 100644 --- a/tools/gg/randomGraph.mli +++ b/tools/gg/randomGraph.mli @@ -16,8 +16,9 @@ val gen_ER : bool -> int -> probability -> Topology.t Barabasi–Albert model is used for the remaining nodes *) val gen_BA : bool -> int -> int -> Topology.t + (** [rand_tree n] generate a random tree of n nodes *) -val rand_tree: bool -> int -> Topology.t +val rand_tree: GraphGen_arg.tree_edge -> 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 area in which the nodes are randomly disposed,