Skip to content
Snippets Groups Projects
Commit ad01fdff authored by Nathan Rébiscoul's avatar Nathan Rébiscoul
Browse files

Merge branch 'master' of...

Merge branch 'master' of https://gricad-gitlab.univ-grenoble-alpes.fr/verimag/synchrone/sasa into 11-add-lustre-oracles-to-all-examples-of-the-test-directory
parents a34d6243 a0ab40d3
No related branches found
No related tags found
1 merge request!8WIP: Resolve "Add Lustre oracles to all examples of the test directory"
Pipeline #26624 failed
(* Time-stamp: <modified the 03/07/2019 (at 10:17) by Erwan Jahier> *) (* Time-stamp: <modified the 04/07/2019 (at 10:36) by Erwan Jahier> *)
open Sasacore open Sasacore
...@@ -31,6 +31,7 @@ type 's to_register = { ...@@ -31,6 +31,7 @@ type 's to_register = {
copy_state: 's -> 's; copy_state: 's -> 's;
} }
type node_id = string (* cf topology.mli *)
let (to_reg_neigbor : 's Register.neighbor -> 's neighbor) = let (to_reg_neigbor : 's Register.neighbor -> 's neighbor) =
fun n -> fun n ->
...@@ -76,5 +77,13 @@ let (register : 's to_register -> unit) = ...@@ -76,5 +77,13 @@ let (register : 's to_register -> unit) =
let card = Register.card let card = Register.card
let get_graph_attribute = Register.get_graph_attribute let get_graph_attribute = Register.get_graph_attribute
let min_degree = Register.min_degree
let mean_degree = Register.mean_degree
let max_degree = Register.max_degree
let is_cyclic = Register.is_cyclic
let is_connected = Register.is_connected
let is_tree = Register.is_tree
let height = Register.height
let links_number = Register.links_number
let diameter = Register.diameter
(* Time-stamp: <modified the 03/07/2019 (at 10:17) by Erwan Jahier> *) (* Time-stamp: <modified the 04/07/2019 (at 10:36) by Erwan Jahier> *)
(** Process programmer API *) (** Process programmer API *)
type 's neighbor = { type 's neighbor = {
...@@ -41,13 +41,23 @@ type 's to_register = { ...@@ -41,13 +41,23 @@ type 's to_register = {
If one prepend a value with "some_id=", some_id will we used in If one prepend a value with "some_id=", some_id will we used in
the simulation outputs. Otherwise, an id will be invented *) the simulation outputs. Otherwise, an id will be invented *)
type node_id = string (* cf topology.mli *)
(** To be called once *) (** To be called once *)
val register : 's to_register -> unit val register : 's to_register -> unit
val get_graph_attribute : string -> string
(** Topological infos *) (** Topological infos *)
val card : unit -> int val card : unit -> int
(* val degree : unit -> int *) val min_degree : unit -> int
(* val diameter : unit -> int *) val mean_degree : unit -> float
val max_degree : unit -> int
val is_cyclic : unit -> bool
val is_connected : unit -> bool
val is_tree : unit -> bool
val height : unit -> (node_id -> int) option
val links_number : unit -> int
val diameter : unit -> int
val get_graph_attribute : string -> string
(* Time-stamp: <modified the 19/06/2019 (at 10:48) by Erwan Jahier> *) (* Time-stamp: <modified the 03/07/2019 (at 17:22) by Erwan Jahier> *)
type t = type t =
| Synchronous (* select all actions *) | Synchronous (* select all actions *)
...@@ -7,30 +7,67 @@ type t = ...@@ -7,30 +7,67 @@ type t =
| Distributed (* select at least one action *) | Distributed (* select at least one action *)
| Custom | Custom
type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action
let (random_list : 'a list -> 'a) = fun l -> let (random_list : 'a list -> 'a) = fun l ->
assert (l <> []); assert (l <> []);
List.nth l (Random.int (List.length l)) List.nth l (Random.int (List.length l))
let (random1: 'a list list -> 'a list) = (* returns a random element of a list as well as the rest of the list *)
let (random_list2 : 'a list -> 'a * 'a list) = fun l ->
assert (l <> []);
let rec split acc i = function
| [] -> assert false (* sno *)
| x::l ->
if i=0 then x, List.rev_append acc l else split (x::acc) (i-1) l
in
let i = Random.int (List.length l) in
split [] i l
let (central: 'a list list -> 'a list) =
fun all -> fun all ->
if all = [] then [] else if all = [] then [] else
let al = List.map random_list all in let al = List.map random_list all in
let a = random_list al in let a = random_list al in
[a] [a]
let rec (random: 'a list list -> 'a list) = let rec (distributed: 'a list list -> 'a list) =
fun all -> fun all ->
if all = [] then [] else if all = [] then [] else
(* assert (all <> []); *) (* assert (all <> []); *)
let al = List.map random_list all in let al = List.map random_list all in
let al = List.filter (fun _ -> Random.bool ()) al in let al = List.filter (fun _ -> Random.bool ()) al in
if al = [] then random all else al if al = [] then distributed all else al
let (synchrone: 'a list list -> 'a list) = fun all -> let (synchrone: 'a list list -> 'a list) = fun all ->
if all = [] then [] else if all = [] then [] else
let al = List.map random_list all in let al = List.map random_list all in
al al
(* LC= 2 neighbors cannot be activated at the same step
XXX this demon is not fair: it is biased by the degree of nodes.
*)
let (locally_central: 'v pna list list -> 'v pna list) =
fun all ->
let remove_one_conflict al =
let _a, al = random_list2 al in
al
in
let rec remove_conflicts al =
let activated_pids = List.map (fun (p,_,_) -> p.Process.pid) al in
let conflicts, ok = List.partition (fun (_p,nl,_a) ->
List.exists (fun n -> List.mem (n.Register.pid ()) activated_pids) nl
) al
in
if conflicts = [] then ok else
let conflicts = remove_one_conflict conflicts in
ok @ (remove_conflicts conflicts)
in
if all = [] then [] else
let al = distributed all in
remove_conflicts al
let rec map3 f l1 l2 l3 = let rec map3 f l1 l2 l3 =
match (l1, l2, l3) with match (l1, l2, l3) with
([], [], []) -> [] ([], [], []) -> []
...@@ -39,7 +76,6 @@ let rec map3 f l1 l2 l3 = ...@@ -39,7 +76,6 @@ let rec map3 f l1 l2 l3 =
| (_, [], _) -> invalid_arg "map3 (2nd arg too short)" | (_, [], _) -> invalid_arg "map3 (2nd arg too short)"
| (_, _, []) -> invalid_arg "map3 (3rd arg too short)" | (_, _, []) -> invalid_arg "map3 (3rd arg too short)"
type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action
let (custom: 'v pna list list -> 'v Process.t list -> bool list list -> let (custom: 'v pna list list -> 'v Process.t list -> bool list list ->
(string -> string -> bool) -> bool list list * 'v pna list) = (string -> string -> bool) -> bool list list * 'v pna list) =
...@@ -87,10 +123,12 @@ let (f: bool -> bool -> t -> 'v Process.t list -> 'v pna list list -> bool list ...@@ -87,10 +123,12 @@ let (f: bool -> bool -> t -> 'v Process.t list -> 'v pna list list -> bool list
let al = synchrone (remove_empty_list all) in let al = synchrone (remove_empty_list all) in
get_activate_val al pl, al get_activate_val al pl, al
| Central -> | Central ->
let al = random1 (remove_empty_list all) in let al = central (remove_empty_list all) in
get_activate_val al pl, al
| LocallyCentral ->
let al = locally_central (remove_empty_list all) in
get_activate_val al pl, al get_activate_val al pl, al
| LocallyCentral -> assert false
| Distributed -> | Distributed ->
let al = random (remove_empty_list all) in let al = distributed (remove_empty_list all) in
get_activate_val al pl, al get_activate_val al pl, al
| Custom -> custom all pl enab get_action_value | Custom -> custom all pl enab get_action_value
(* Time-stamp: <modified the 19/06/2019 (at 10:50) by Erwan Jahier> *) (* Time-stamp: <modified the 03/07/2019 (at 17:25) by Erwan Jahier> *)
type t = type t =
| Synchronous (* select all actions *) | Synchronous (* select all actions *)
| Central (* select 1 action *) | Central (* select 1 action *)
| LocallyCentral (* never activates two neighbors actions in the same step *) | LocallyCentral (* never activates two neighbors actions in the same step [1] *)
| Distributed (* select at least one action *) | Distributed (* select at least one action *)
| Custom (* enable/actions are communicated via stdin/stdout in RIF *) | Custom (* enable/actions are communicated via stdin/stdout in RIF *)
(* [1] nb: the current implementation of locally central demon is
biased by the degree of nodes. *)
type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action type 'v pna = 'v Process.t * 'v Register.neighbor list * Register.action
......
(* take a string and the list of all node and returns the position of the node in the list *)
let (pos:string -> Topology.node list -> int) =
fun nid lid ->
fst (List.fold_left (fun (found_i,i) lid -> if (nid=lid.Topology.id) then (i,i+1) else (found_i,i+1) ) (-1, 0) lid)
(* take a graph t and returns the Adjacency matrix of t *)
let (graph_to_adjency: Topology.t -> int array array) =
fun t->
let taille = List.length t.nodes in
let mat = Array.make_matrix (taille) (taille) 0 in
List.iter (fun n -> (List.iter (fun (_,m) -> mat.(pos n.Topology.id t.nodes).(pos m t.nodes) <- 1 )
(t.succ n.Topology.id) ) ) (t.nodes);
mat
(* Initialize the Adjacency matrix for Floyd Warshall algorithm *)
let (initFW: int array array -> int array array) =
fun m ->
let n = (Array.length m.(0)) in
for i=0 to (n - 1) do
for j=0 to (n - 1) do
if (i<>j) then
(if (m.(i).(j)=1) then m.(i).(j) <- 1 else m.(i).(j) <- n+1)
else m.(i).(j) <- 0
done;
done;
m
(* Apply Floyd Warshall algorithm which gives the matrix of all pairs shortest path *)
let (floydwarshall:int array array -> int array array) =
fun m ->
let w = initFW m in
let n = (Array.length m.(0)) in
for k=0 to (n - 1) do
for i=0 to (n - 1) do
for j=0 to (n - 1) do
w.(i).(j) <- (min (w.(i).(j)) (w.(i).(k) + w.(k).(j)))
done;
done;
done;
w
(* returns the greatest int of a matrix *)
let (max_mat: int array array -> int) =
fun mat ->
let n = (Array.length mat) and m = (Array.length mat.(0)) in
let maxi = ref (-1) in
for i=0 to (n - 1) do
for j=0 to (m - 1) do
maxi := max !maxi mat.(i).(j)
done;
done;
!maxi
(* takes a graph t in argument and returns the diameter *)
let (get: Topology.t -> int ) =
fun t ->
(max_mat(floydwarshall (graph_to_adjency t)))
\ No newline at end of file
val get : Topology.t -> int
(* Time-stamp: <modified the 19/06/2019 (at 10:49) by Erwan Jahier> *) (* Time-stamp: <modified the 03/07/2019 (at 15:53) by Erwan Jahier> *)
type 'v t = { type 'v t = {
pid : string; pid : string;
...@@ -25,7 +25,8 @@ let (make: bool -> Topology.node -> 'v -> 'v t) = ...@@ -25,7 +25,8 @@ let (make: bool -> Topology.node -> 'v -> 'v t) =
try Register.get_actions id try Register.get_actions id
with _ -> with _ ->
if custom_mode then if custom_mode then
failwith "Registering actions is mandatory in algorithms when using custom demon!" failwith
"Registering actions is mandatory in algorithms when using custom demon!"
else ["a"] else ["a"]
in in
let process = { let process = {
......
(* Time-stamp: <modified the 03/07/2019 (at 10:17) by Erwan Jahier> *) (* Time-stamp: <modified the 04/07/2019 (at 10:35) by Erwan Jahier> *)
type 's neighbor = { type 's neighbor = {
state: 's ; state: 's ;
...@@ -22,9 +22,29 @@ type 's internal_tables = { ...@@ -22,9 +22,29 @@ type 's internal_tables = {
value_of_string : (string, Obj.t) Hashtbl.t; value_of_string : (string, Obj.t) Hashtbl.t;
copy_value : (string, Obj.t) Hashtbl.t; copy_value : (string, Obj.t) Hashtbl.t;
graph_attributes : (string, string) Hashtbl.t; graph_attributes : (string, string) Hashtbl.t;
mutable card : int mutable card : int ;
mutable min_deg : int;
mutable mean_deg : float;
mutable max_deg : int;
mutable is_cyclic : bool option;
mutable is_connected : bool option;
mutable is_tree : bool option;
mutable height : (string -> int);
mutable links_number : int;
mutable diameter : int;
}
type properties_functions = {
mutable card : unit -> int;
mutable min_max : unit -> int*int;
mutable mean_deg : unit -> float;
mutable is_connected_cyclic : unit -> bool*bool;
mutable links_number : unit -> int;
mutable diameter : unit -> int
} }
type node_id = string (* cf topology.mli *)
let (tbls:'s internal_tables) = { let (tbls:'s internal_tables) = {
init_state = Hashtbl.create 1; init_state = Hashtbl.create 1;
enable = Hashtbl.create 1; enable = Hashtbl.create 1;
...@@ -34,7 +54,25 @@ let (tbls:'s internal_tables) = { ...@@ -34,7 +54,25 @@ let (tbls:'s internal_tables) = {
value_of_string = Hashtbl.create 1; value_of_string = Hashtbl.create 1;
copy_value = Hashtbl.create 1; copy_value = Hashtbl.create 1;
graph_attributes = Hashtbl.create 1; graph_attributes = Hashtbl.create 1;
card = (-1) card = (-1);
min_deg = (-1);
mean_deg = (-1.);
max_deg = (-1);
is_cyclic = None;
is_connected = None;
is_tree = None;
height = (fun _ -> -1);
links_number = (-1);
diameter = (-1)
}
let (prop_funs:properties_functions) = {
card = (fun () -> -1);
min_max = (fun () -> (-1,-1));
mean_deg = (fun () -> -1.);
is_connected_cyclic = (fun () -> (false,false));
links_number = (fun () -> -1);
diameter = (fun () -> -1)
} }
let verbose_level = ref 0 let verbose_level = ref 0
...@@ -127,12 +165,103 @@ let (get_copy_value : unit -> ('s -> 's)) = fun () -> ...@@ -127,12 +165,103 @@ let (get_copy_value : unit -> ('s -> 's)) = fun () ->
raise (Unregistred ("copy_value", "_global")) raise (Unregistred ("copy_value", "_global"))
let set_min_max : (unit -> unit) =
fun () ->
let (x,y) = prop_funs.min_max () in
tbls.min_deg <- x;
tbls.max_deg <- y
let set_connec_cycl : (unit -> unit) =
fun () ->
let (x,y) = prop_funs.is_connected_cyclic () in
tbls.is_connected <- Some x;
tbls.is_cyclic <- Some y
let (card : unit -> int) = let (card : unit -> int) =
fun () -> tbls.card fun () -> match tbls.card with
| -1 -> (let c = prop_funs.card () in tbls.card <- c; c)
let (set_card : int -> unit) = | c -> c
fun i ->
tbls.card <- i let (min_degree : unit -> int) =
fun () -> match tbls.min_deg with
| -1 -> (set_min_max (); tbls.min_deg)
| m -> m
let (mean_degree : unit -> float) =
fun () -> match tbls.mean_deg with
| -1. -> (let m = prop_funs.mean_deg () in tbls.mean_deg <- m; m)
| m -> m
let (max_degree : unit -> int) =
fun () -> match tbls.max_deg with
| -1 -> (set_min_max (); tbls.max_deg)
| m -> m
let (is_cyclic : unit -> bool) =
fun () -> match tbls.is_cyclic with
| None -> (set_connec_cycl ();
match tbls.is_cyclic with
| Some b -> b
| _ -> assert false)
| Some b -> b
let (is_connected : unit -> bool) =
fun () -> match tbls.is_connected with
| None -> (set_connec_cycl ();
match tbls.is_connected with
| Some b -> b
| _ -> assert false)
| Some b -> b
let (is_tree : unit -> bool) =
fun () -> match tbls.is_tree with
| None -> (let b = (not (is_cyclic ()) && (is_connected ())) in tbls.is_tree <- Some b; b)
| Some b -> b
(* Caution : this option is not the same as the option in the type tbls.height.
* If height () = None, then the graph doesn't have a height (because it isn't a tree)*)
let height : (unit -> (string -> int) option) =
fun () ->
if is_tree () then
Some tbls.height
else None
let (links_number : unit -> int) =
fun () -> match tbls.links_number with
| -1 -> (let n = prop_funs.links_number () in tbls.links_number <- n; n)
| n -> n
let (diameter : unit -> int) =
fun () ->
match tbls.diameter with
| -1 -> (let d = (prop_funs.diameter ()) in tbls.diameter <- d; d)
| d -> d
let set_card : ((unit -> int) -> unit) =
fun f -> prop_funs.card <- f
let set_degrees : ((unit -> int*int) -> unit) =
fun f -> prop_funs.min_max <- f
let set_mean_deg : ((unit -> float) -> unit) =
fun f -> prop_funs.mean_deg <- f
let set_is_connected_cyclic : ((unit -> bool*bool) -> unit) =
fun f -> prop_funs.is_connected_cyclic <- f
let set_height : ((node_id -> int) -> unit) =
fun f -> tbls.height <- f
let set_links_number : ((unit -> int) -> unit) =
fun f -> prop_funs.links_number <- f
let set_diameter : ((unit -> int) -> unit) =
fun f -> prop_funs.diameter <- f
let (to_string : 's -> string) = let (to_string : 's -> string) =
fun v -> fun v ->
......
(* Time-stamp: <modified the 03/07/2019 (at 10:18) by Erwan Jahier> *) (* Time-stamp: <modified the 04/07/2019 (at 10:34) by Erwan Jahier> *)
type 's neighbor = { type 's neighbor = {
state: 's ; state: 's ;
...@@ -13,6 +13,7 @@ type action = string ...@@ -13,6 +13,7 @@ type action = string
type 's enable_fun = 's neighbor list -> 's -> action list type 's enable_fun = 's neighbor list -> 's -> action list
type 's step_fun = 's neighbor list -> 's -> action -> 's type 's step_fun = 's neighbor list -> 's -> action -> 's
type node_id = string (* cf topology.mli *)
val reg_init_state : algo_id -> (int -> 's) -> unit val reg_init_state : algo_id -> (int -> 's) -> unit
val reg_enable : algo_id -> 's enable_fun -> unit val reg_enable : algo_id -> 's enable_fun -> unit
...@@ -31,15 +32,31 @@ val get_value_to_string : unit -> 's -> string ...@@ -31,15 +32,31 @@ val get_value_to_string : unit -> 's -> string
val get_value_of_string : unit -> (string -> 's) option val get_value_of_string : unit -> (string -> 's) option
val get_copy_value : unit -> ('s -> 's) val get_copy_value : unit -> ('s -> 's)
val to_string : 's -> string val to_string : 's -> string
val set_card : int -> unit
(* val set_degree : int -> unit *)
(* val set_diameter : int -> unit *)
val card : unit -> int
(* val degree : unit -> int *) val set_card : (unit -> int) -> unit
(* val diameter : unit -> int *) val set_degrees : (unit -> int*int) -> unit
val set_mean_deg : (unit -> float) -> unit
val set_is_connected_cyclic : (unit -> bool*bool) -> unit
val set_height : (node_id -> int) -> unit
val set_links_number : (unit -> int) -> unit
val set_diameter : (unit -> int) -> unit
val get_graph_attribute : string -> string val get_graph_attribute : string -> string
val set_graph_attribute : string -> string -> unit val set_graph_attribute : string -> string -> unit
val card : unit -> int
val min_degree : unit -> int
val mean_degree : unit -> float
val max_degree : unit -> int
val is_cyclic : unit -> bool
val is_connected : unit -> bool
val is_tree : unit -> bool
(** If height () = None, then the graph doesn't have a height (because it isn't a tree)
Otherwise, height () = Some h.*)
val height : unit -> (string -> int) option
val links_number : unit -> int
val diameter : unit -> int
val verbose_level: int ref val verbose_level: int ref
...@@ -146,7 +146,66 @@ let (env_rif_decl: SasArg.t -> 'v Process.t list -> string) = ...@@ -146,7 +146,66 @@ let (env_rif_decl: SasArg.t -> 'v Process.t list -> string) =
let ssl = get_outputs_rif_decl args pl in let ssl = get_outputs_rif_decl args pl in
String.concat " " String.concat " "
(List.map (fun (base, tstr) -> Printf.sprintf "\"%s\":%s" base tstr) ssl) (List.map (fun (base, tstr) -> Printf.sprintf "\"%s\":%s" base tstr) ssl)
let (get_degree:Topology.t -> int*int) =
fun t -> if t.nodes = [] then 0,0
else
let node_deg n = List.length (t.succ (n.Topology.id)) in
let d_start = node_deg ((List.hd t.nodes)) in
List.fold_left (fun (d_min,d_max) n -> (min (node_deg n) d_min, max (node_deg n) d_max)
) (d_start,d_start) (List.tl t.nodes)
(* take a graph t and a boolean is_oriented and return the number of link in the graph *)
let (get_nb_link: Topology.t -> bool -> int) =
fun t is_oriented ->
if not is_oriented then (List.fold_left (fun acc n -> ((List.length (t.succ n.Topology.id))) + acc) (0) (t.nodes)) / 2
else (List.fold_left (fun acc n -> ((List.length (t.succ n.Topology.id))) + acc) (0) (t.nodes))
let (get_mean_degree : Topology.t -> float) =
fun t ->
(float_of_int (get_nb_link t true)) /. (float_of_int (List.length t.nodes))
let bfs : (Topology.t -> string -> bool * string list) =
fun t n ->
let q = Queue.create () in
let discovered = ref [n] and parent = ref (function _ -> "") in
let cyclic = ref false in
Queue.add n q;
while not (Queue.is_empty q) do
let node = Queue.take q in
parent := List.fold_left (fun parents (_,suc) ->
if List.for_all (fun disc -> disc <> suc) !discovered
then (
Queue.add suc q;
discovered := (suc)::!discovered;
function a -> if a = suc then node else parents a
) else ((
if suc <> (parents node)
then
cyclic := true);
parents
)
) !parent (t.succ node)
done;
(!cyclic, !discovered)
let is_connected_and_cyclic : Topology.t -> bool*bool =
fun t -> match t.nodes with
| [] -> (false,false)
| hd::_ -> let (cyclic,bfs_nodes) = (bfs t hd.Topology.id) in ((List.compare_lengths t.nodes bfs_nodes) = 0, cyclic)
let rec height : string list -> Topology.t -> string -> int =
fun parents t n ->
(List.fold_left (fun h (_,succ) ->
if List.mem succ parents then h else max h (height (n::parents) t succ)) (-1) (t.succ n)) + 1
let get_height : Topology.t -> string -> int =
fun t ->
height ([]) t
let (make : bool -> string array -> 'v t) = let (make : bool -> string array -> 'v t) =
fun dynlink argv -> fun dynlink argv ->
let args = let args =
...@@ -167,7 +226,14 @@ let (make : bool -> string array -> 'v t) = ...@@ -167,7 +226,14 @@ let (make : bool -> string array -> 'v t) =
let nl = g.nodes in let nl = g.nodes in
let nidl = List.map (fun n -> n.Topology.id) nl in let nidl = List.map (fun n -> n.Topology.id) nl in
let nstr = String.concat "," nidl in let nstr = String.concat "," nidl in
Register.set_card (List.length nl); Register.set_card (fun () -> List.length nl);
Register.set_degrees (fun () -> get_degree g);
Register.set_mean_deg (fun () -> get_mean_degree g);
Register.set_is_connected_cyclic (fun () -> is_connected_and_cyclic g);
Register.set_height (get_height g);
Register.set_links_number (fun () -> get_nb_link g false);
Register.set_diameter (fun () -> Diameter.get g);
Register.verbose_level := args.verbose; Register.verbose_level := args.verbose;
Random.init args.seed; Random.init args.seed;
if !Register.verbose_level > 0 then Printf.eprintf "nodes: %s\nedges:\n" nstr; if !Register.verbose_level > 0 then Printf.eprintf "nodes: %s\nedges:\n" nstr;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment