From ff0da0525b179c86486b56f9d4ee8c492e224acc Mon Sep 17 00:00:00 2001 From: Erwan Jahier <erwan.jahier@univ-grenoble-alpes.fr> Date: Wed, 21 Jun 2023 11:26:03 +0200 Subject: [PATCH] new: add the distance matrix (int^n^n) in the salut generated code This is necessary to compute the heigth in a tree and will probably be useful for other purposes --- lib/sasacore/topology.ml | 37 +++++++++++++++- lib/sasacore/topology.mli | 3 +- salut/src/dot2lus.ml | 66 +++++++++++++++------------- salut/test/kclustering/cost.lus | 41 ++++++++---------- salut/test/rsp_tree/tree4.lus | 77 --------------------------------- salut/test/run-kind2.sh | 23 ++++++---- 6 files changed, 103 insertions(+), 144 deletions(-) delete mode 100644 salut/test/rsp_tree/tree4.lus diff --git a/lib/sasacore/topology.ml b/lib/sasacore/topology.ml index 60574d21..47db5f5e 100644 --- a/lib/sasacore/topology.ml +++ b/lib/sasacore/topology.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 30/05/2022 (at 14:49) by Erwan Jahier> *) +(* Time-stamp: <modified the 20/06/2023 (at 22:55) by Erwan Jahier> *) open Graph open Graph.Dot_ast @@ -70,7 +70,7 @@ let (get_init: Dot_ast.attr list -> string) = let compare_alpha_num str1 str2 = (* if str1 and str2 are of the form [^0-9][0-9]+, we use the alphabetic - order for the first part, and the numeric order for the second part. + order for the first part, and the numeric order for the second part. nb : this is the case for node names generated by gg *) try @@ -90,6 +90,27 @@ let rec (get_weight: Dot_ast.attr -> int) = type attrs = (string * string) list +(* compute the distance between 2 nodes in g denoted by their position in g.nodes *) +module StrSet = Set.Make(String) + +let (distance : t -> int -> int -> int) = + fun g i j -> + assert( 0 <= i && i<=j && j < List.length g.nodes); + let ni = List.nth g.nodes i in + let nj = List.nth g.nodes j in + let (get_succ : node_id -> StrSet.t) = + fun n -> g.succ n |> List.to_seq |> StrSet.of_seq + in + let rec aux n succ cpt = + if StrSet.mem n.id succ then cpt else + let succ = + StrSet.fold (fun n acc -> StrSet.union acc (get_succ n)) succ succ + in + aux n succ (cpt+1) + in + aux ni (StrSet.singleton nj.id) 0 + + let (do_graph_attr : attrs -> (Dot_ast.id * Dot_ast.id option) list -> attrs) = fun acc l -> let f acc = function @@ -187,6 +208,18 @@ let (to_adjacency: t -> bool array array) = t.nodes; m +let (to_distance : t -> int array array) = + fun t -> + let n = List.length t.nodes in + let m = Array.make_matrix n n 0 in + for i = 0 to n-1 do + for j = i to n-1 do + m.(i).(j) <- distance t i j; + m.(j).(i) <- m.(i).(j); + done + done; + m + let (get_degree: t -> int*int) = fun t -> match t.nodes with diff --git a/lib/sasacore/topology.mli b/lib/sasacore/topology.mli index 4c711ae0..d1f82887 100644 --- a/lib/sasacore/topology.mli +++ b/lib/sasacore/topology.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 20/09/2021 (at 09:45) by Erwan Jahier> *) +(* Time-stamp: <modified the 20/06/2023 (at 15:07) by Erwan Jahier> *) (** {1 Topology: internal representation of Graphs } *) @@ -25,6 +25,7 @@ val read: string -> t (** {1 Various eponymous util functions } *) val to_adjacency: t -> bool array array +val to_distance: t -> int array array val get_nb_link: t -> int val get_mean_degree : t -> float val is_connected : t -> bool diff --git a/salut/src/dot2lus.ml b/salut/src/dot2lus.ml index 2280ed18..4cee2817 100644 --- a/salut/src/dot2lus.ml +++ b/salut/src/dot2lus.ml @@ -13,32 +13,30 @@ let action_of_int = "action_of_int" let clock = ref false + +let (array_to_string : ('a -> string) -> 'a array -> string) = + fun tostr a -> + let l = Array.fold_right (fun b acc -> (tostr b)::acc) a [] in + "["^(String.concat "," l)^"]" + +let (matrix_to_string : ('a -> string) -> 'a array array -> string) = + fun tostr m -> + let l = Array.fold_right (fun a acc -> (array_to_string tostr a)::acc) m [] in + "[\n\t"^(String.concat ",\n\t" l)^"]" + + let algo_name (node : Topology.node) = Filename.remove_extension node.file (* prints includes, graph constants and helper functions *) let output_prelude lustre_topology lustre_const (graph : Topology.t) = Printf.fprintf lustre_topology "-- automatically generated by salut \n"; Printf.fprintf lustre_const "-- automatically generated by salut \n"; - - (* NOTE: b2s, array_to_string and matrix_to_string copied from genOracle.ml *) - let b2s b = if b then "t" else "f" in - - let (array_to_string : bool array -> string) = - fun a -> - let l = Array.fold_right (fun b acc -> (b2s b)::acc) a [] in - "["^(String.concat "," l)^"]" - in - let (matrix_to_string : bool array array -> string) = - fun m -> - let l = Array.fold_right (fun a acc -> (array_to_string a)::acc) m [] in - "[\n\t"^(String.concat ",\n\t" l)^"]" - in - + (* include Lustre algos *) graph.nodes |> List.map algo_name |> List.sort_uniq String.compare |> List.iter (Printf.fprintf lustre_topology "include \"%s.lus\"\n"); - + (* define graph constants *) output_string lustre_topology "\n"; Printf.fprintf lustre_const "const card = %d;\n" (List.length graph.nodes); @@ -54,7 +52,7 @@ let output_prelude lustre_topology lustre_const (graph : Topology.t) = let neigh_list = graph.nodes |> List.map (fun (n:Topology.node) -> graph.pred n.id) in let nb_neigh_list = neigh_list |> List.map (fun n -> string_of_int (List.length n)) in Printf.fprintf lustre_const "const nb_neighbors = %s;\n" ("["^(String.concat "," (nb_neigh_list))^"]"); - + (* dot attributes *) let already_defined = function | "card" @@ -75,22 +73,28 @@ let output_prelude lustre_topology lustre_const (graph : Topology.t) = if not (already_defined name) then Printf.fprintf lustre_const "const %s = %s;\n" name value) graph.attributes; - + (* adjacency matrix *) output_string lustre_const "const t = true;\n"; output_string lustre_const "const f = false;\n"; + (* NOTE: b2s, array_to_string and matrix_to_string copied from genOracle.ml *) + let b2s b = if b then "t" else "f" in Printf.fprintf lustre_const "const adjacency = %s;\n" - (graph |> Topology.to_adjacency |> matrix_to_string); + (graph |> Topology.to_adjacency |> (matrix_to_string b2s)); + + Printf.fprintf lustre_const + "const distance = %s;\n" + (graph |> Topology.to_distance |> (matrix_to_string string_of_int)); (* State.lus File *) output_string lustre_topology" include \"state.lus\""; - + (* Neighbors type *) output_string lustre_topology " type neigh = struct { state:state; reply:int; weight:int };\n"; - + (* helper functions *) output_string lustre_topology " function dot2lus_first_set<<const N:int>>(s : bool^N) returns (x : int); @@ -121,7 +125,7 @@ let output_topology lustre_topology (graph : Topology.t) name = |> List.map (fun (n : Topology.node) -> n.id) |> List.iteri (fun index node_id -> Hashtbl.add index_map node_id index); Hashtbl.find index_map (* returns the partially applied find *) in - + let sprint_neighbor_list neighbor_ids list : string = match neighbor_ids with | [] -> "[]" @@ -133,28 +137,28 @@ let output_topology lustre_topology (graph : Topology.t) name = Printf.fprintf lustre_topology "\nnode %s(p : bool^%s^card; initials : %s^card)\n" name action_number state_type; - + Printf.fprintf lustre_topology "returns (p_c : %s^card; Enab_p : bool^%s^card; round:bool; round_nb:int);\n" state_type action_number; - + output_string lustre_topology "var"; - + Printf.fprintf lustre_topology "\tprev_p_c : %s^card;\n\n" state_type; graph.nodes |> List.iteri (fun i _ -> Printf.fprintf lustre_topology "\tsel_%d : bool;\n" i); - + output_string lustre_topology "let round = round<<actions_number,card>>(Enab_p, p); round_nb = round_count(round, legitimate<<actions_number,card>>(Enab_p,p_c)); "; - + output_string lustre_topology "\tprev_p_c = initials -> pre(p_c);\n\n"; graph.nodes |> List.iteri (fun i _ -> Printf.fprintf lustre_topology - "\tsel_%d = false -> n_or<<%s>>(p[%d]);\n" i action_number i); - + "\tsel_%d = false -> nary_or<<%s>>(p[%d]);\n" i action_number i); + let index_of_id = make_index graph in graph.nodes (*liste des noms des noeuds *) @@ -176,7 +180,7 @@ let output_topology lustre_topology (graph : Topology.t) name = Printf.fprintf lustre_topology "\tEnab_p[%d] = %s_enable<<%d>>(p_c[%d], %s);\n" i algo deg i nl); - + Printf.fprintf lustre_topology "tel;\nnode topology = %s;\n%!" name (*Generate a new state.lus file*) @@ -226,7 +230,7 @@ let _ = let usage = "salut <dotfile> [-o lusfile] [--clock] [--help]" in let dotfile = ref "" in let lusfile = ref "" in - + let anon_parse arg = match !dotfile with | "" -> dotfile := arg diff --git a/salut/test/kclustering/cost.lus b/salut/test/kclustering/cost.lus index c9d2c121..2d345d81 100644 --- a/salut/test/kclustering/cost.lus +++ b/salut/test/kclustering/cost.lus @@ -1,33 +1,26 @@ include "p.lus" const debug=false; -function parentd<<const card:int;const n:int>>(p:state ; config:state^card) returns (parp:state); +node heigth<<const i:int>>(dummy:bool) returns (res:int); let -parp=with (card=n) then config[card-1] - else if p.par=n then config[n] else parentd<<card,(n+1)>>(p,config); -tel - -node depth<<const card:int>> (p:state; config:state^card) returns (nat:int); -var parp:state; + res = distance[0][i] ; +tel; +node sum_heigth<<const n:int>>(enabled : bool^1^n; config : state^n) +returns (pf:int); let -parp=parentd<<card;0>>(p,config); -nat= with (card=1) then 1 - else if isRoot(p) then 1 else 1+ depth<<card-1>>(parp,config[1..(card-1)]); + pf= with (n=1) then + if enabled[0][0] then + heigth<<0>>(true)+1 + else + 0 + else + if enabled[n-1][0] then + heigth<<n-1>>(true) + 1 + + sum_heigth<<n-1>>(enabled[0..(n-2)],config[0..(n-2)]) + else sum_heigth<<n-1>>(enabled[0..(n-2)],config[0..(n-2)]); tel -node pot<<const card:int>>(p:state;config:state^card) returns (nat:int); +node cost(enabled : bool^1^card; config : state^card) returns (res: int); let -nat= if p_enable<<n>>(p,config)= [true] then depth<<card>>(p,config) else 0; + res=sum_heigth<<card>>(enabled,config); tel - -node sum<<const card:int>>(enabled : bool^actions_number^card; config : state^card) returns (pf:int); -let -pf= with (card=1) then if enabled[0][0]=true then depth<<card>>(config[0],config) else 0 - else if enabled[0][0]=true then depth<<card>>(config[0],config) + sum<<card-1>>(enabled[1..(card-1)],config[1..(card-1)]) - else sum<<card-1>>(enabled[1..(card-1)],config[1..(card-1)]); -tel - -node cost(enabled : bool^actions_number^card; config : state^card) returns (res: int); -let -res=sum<<card>>(enabled,config); -tel \ No newline at end of file diff --git a/salut/test/rsp_tree/tree4.lus b/salut/test/rsp_tree/tree4.lus deleted file mode 100644 index cee55d51..00000000 --- a/salut/test/rsp_tree/tree4.lus +++ /dev/null @@ -1,77 +0,0 @@ --- automatically generated by salut -include "p.lus" -include "root.lus" - - -function dot2lus_first_set<<const N:int>>(s : bool^N) returns (x : int); -var - found : int; -let - found = - with (N = 1) then (if s[0] then 0 else -1) - else dot2lus_first_set<<N-1>>(s[1 .. N-1]); - x = - if s[0] then 0 - else if found < 0 then -1 - else found + 1; -tel; - -function dot2lus_action_of_activation(activation : bool^actions_number) returns (action : action); -let - action = action_of_int(dot2lus_first_set<<actions_number>>(activation)); -tel; - -node tree4(p : bool^actions_number^card; initials : state^card) -returns (p_c : state^card; Enab_p : bool^actions_number^card); -var - prev_p_c : state^card; - - sel_0 : bool; - sel_1 : bool; - sel_2 : bool; - sel_3 : bool; -let - prev_p_c = initials -> pre(p_c); - - sel_0 = false -> boolred<<1,actions_number,actions_number>>(p[0]); - sel_1 = false -> boolred<<1,actions_number,actions_number>>(p[1]); - sel_2 = false -> boolred<<1,actions_number,actions_number>>(p[2]); - sel_3 = false -> boolred<<1,actions_number,actions_number>>(p[3]); - - p_c[0] = - if not sel_0 then prev_p_c[0] - else root_step<<2>>( - prev_p_c[0], - [ prev_p_c[1], prev_p_c[2] ], - dot2lus_action_of_activation(p[0]) - ); - Enab_p[0] = root_enable<<2>>(p_c[0], [ p_c[1], p_c[2] ]); - - p_c[1] = - if not sel_1 then prev_p_c[1] - else p_step<<2>>( - prev_p_c[1], - [ prev_p_c[0], prev_p_c[3] ], - dot2lus_action_of_activation(p[1]) - ); - Enab_p[1] = p_enable<<2>>(p_c[1], [ p_c[0], p_c[3] ], [0,0]); - - p_c[2] = - if not sel_2 then prev_p_c[2] - else p_step<<1>>( - prev_p_c[2], - [ prev_p_c[0] ], - dot2lus_action_of_activation(p[2]) - ); - Enab_p[2] = p_enable<<1>>(p_c[2], [ p_c[0] ],[1]); - - p_c[3] = - if not sel_3 then prev_p_c[3] - else p_step<<1>>( - prev_p_c[3], - [ prev_p_c[1] ], - dot2lus_action_of_activation(p[3]) - ); - Enab_p[3] = p_enable<<1>>(p_c[3], [ p_c[1] ],[1]); -tel; -node topology = tree4; diff --git a/salut/test/run-kind2.sh b/salut/test/run-kind2.sh index aa7ec28e..4543ab4b 100755 --- a/salut/test/run-kind2.sh +++ b/salut/test/run-kind2.sh @@ -1,5 +1,5 @@ #!/bin/bash -#set -x +set -x GITROOT=$(git rev-parse --show-toplevel) LIB_LUS="${GITROOT}/test/lustre/round.lus ${GITROOT}/salut/lib/daemon.lus" @@ -100,7 +100,7 @@ fi kind2_opt="--timeout 36000 -json -v " kind2_opt="--enable BMC --enable IND --timeout 36000 -json -v" kind2_opt="--enable BMC --enable IND --enable IC3 --timeout 36000" -kind2_opt="--smt_solver $solver --enable BMC --enable IND --timeout 36000 $@" +kind2_opt="--smt_solver $solver --enable BMC --enable IND --timeout 10000 $@" # --qe_method {precise|impl|cooper} @@ -116,25 +116,30 @@ cp ${LIB_LUS} ${TMP} cd ${TMP} make $main.dot || [ -f $main.dot ] || (echo "E: is Makefile.dot included from Makefile?"; exit 2) +start0=`date +%s.%N` salut $main.dot # Get rif of the lutre v6 constructs that kind2 does not handle -lv6 -eei ${LIB_LUS} $main.lus verify.lus ${main}_const.lus -n verify --lustre-v4 -en -knc -o $main.verify.lv4 +lv6 -eei ${LIB_LUS} $main.lus verify.lus ${main}_const.lus -n verify --lustre-v4 -en -knpc -o $main.verify.lv4 # set the property to check -sed -i -e "s/tel/--%MAIN ;\n--%PROPERTY $prop;\ntel/" $main.verify.lv4 +cat $main.verify.lv4 | grep -v "\-\-" | sed -e "$ s/\(.*\)tel$/--%MAIN ;\n--%PROPERTY $prop;\ntel/g" > $main.verify.lv4.tmp +mv $main.verify.lv4.tmp $main.verify.lv4 +# sed -i -e "$s/\(.*\)tel/--%MAIN ;\n--%PROPERTY $prop;\ntel/" $main.verify.lv4 + +# using machine integers instead of int: eg, replace 42 by (uint8 42) -# using machine integers instead of int cat $main.verify.lv4 | \ - sed -r "s/[ =](\[)?((-)?[[:digit:]]+)/ \1(${int} \2)/g" | \ - sed -r "s/\(((-)?[[:digit:]]+)\)/(${int} \1)/g" | \ + sed -r "s/([ \t\r\n=([<>\/\*\+]+)((-)?[[:digit:]]+)/ \1(${int} \2)/g" | \ sed -r "s/:int/:${int}/g" \ > $main.verify.${int}.lv4 + start=`date +%s.%N` time kind2 --color true ${kind2_opt} $main.verify.${int}.lv4 end=`time date +%s.%N` +wallclock0=$( echo "$end - $start0" | bc -l ) wallclock=$( echo "$end - $start" | bc -l ) timestamp=`date +"%d/%m/%Y-%H:%M:%S"` @@ -146,7 +151,7 @@ LC_NUMERIC="en_US.UTF-8" # let's keep a track of all runs (it can expensive, it should not be lost) # in a .org file ALL_RESULT="${GITROOT}/salut/test/kind2-result-`uname -n`.org" -printf "| %s | %s | %s | %s | %.2f | %s | %s | %s | %s |\n" $algo ${topology} ${size} \ - $prop $wallclock $int $solver $timestamp `kind2 --version | cut -d ' ' -f2` >> ${ALL_RESULT} +printf "| %s | %s | %s | %s | %.2f-%.2f | %s | %s | %s | %s |\n" $algo ${topology} ${size} \ + $prop $wallclock0 $wallclock $int $solver $timestamp `kind2 --version | cut -d ' ' -f2` >> ${ALL_RESULT} echo "cf ${ALL_RESULT}" \ No newline at end of file -- GitLab