diff --git a/test/rsp_tree/Makefile b/test/rsp_tree/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0210a79a0d95b9f462938e956062af9d42f42952 --- /dev/null +++ b/test/rsp_tree/Makefile @@ -0,0 +1,27 @@ +TOPOLOGY ?= tree4 +DOT2LUSFLAGS ?= +SASA_ALGOS := p.ml root.ml +DECO_PATTERN="0:root.ml 1-:p.ml" + + +include ../Makefile.inc +-include ../Makefile.dot + +clean: genclean + rm -f + +## Some examples of use of ../Makefile.inc + + +# run a simulation with luciole +simu: $(TOPOLOGY).simu + +# Compare the ocaml version with the lustre one +compare: $(TOPOLOGY).lurette + cat rsp_tree.rif + +# make diring4.simu +kind2: $(TOPOLOGY).kind2 + +## do not work because there is a modulo in p.lus, which is not (yet) implemented in ../../bit-blast/*.lus +lesar: $(TOPOLOGY).lesar diff --git a/test/rsp_tree/config.ml b/test/rsp_tree/config.ml new file mode 100644 index 0000000000000000000000000000000000000000..494fdf2e9e9ea8cda840c0bfa9dcfbe65b216ad7 --- /dev/null +++ b/test/rsp_tree/config.ml @@ -0,0 +1,9 @@ +(* Automatically generated by /home/emile/.opam/4.12.0/bin/sasa version "v4.6.1" ("c3dfe95")*) +(* on PC-Travail the 20/6/2022 at 14:52:03*) +(*sasa -reg tree4.dot*) + + +let potential = None (* None => only -sd, -cd, -lcd, -dd, or -custd are possible *) +let legitimate = None (* None => only silent configuration are legitimate *) +let fault = None (* None => the simulation stop once a legitimate configuration is reached *) +let init_search_utils = None (* To provide to use --init-search *) diff --git a/test/rsp_tree/p.lus b/test/rsp_tree/p.lus new file mode 100644 index 0000000000000000000000000000000000000000..660bcc314f82df2cba44aeb9063c6d9128d8a08d --- /dev/null +++ b/test/rsp_tree/p.lus @@ -0,0 +1,147 @@ +----------------------------------------------------------------- +--Get parent function: +function parent<<const n:int; const count:int>>(this : state; neighbors : state^n) +returns (res : state); +let + res = if (n<=this.par) then neighbors[n-1] + else with (count = n ) then neighbors[n-1] + else if (count = this.par) then neighbors[count] else parent<<n,(count+1)>>(this,neighbors); +tel; + +------------------------------------------------------------------ +--Reply function: +function reply<<const n:int>>(v:state; neighbors: state^n; reply_l:int^n) +returns (res : int); +let + res = with (n=1) then reply_l[0] else + if (v = neighbors[0]) then reply_l[0] else reply<<n-1>>(v,neighbors[1..n-1],reply_l[1..n-1]); +tel; + +------------------------------------------------------------------ +--Predicates: +function children<<const n:int>>(u:state; neighbors:state^n; reply_l:int^n) +returns ( res : bool^n ); +var v:state; +let + v = neighbors[0]; + res = with (n=1) then [ ((u.st <> I) and + (v.st <> I) and + (reply<<n>>(v,neighbors,reply_l) = v.par) and + (v.d >= u.d + 1) and + ((v.st = u.st) or (u.st = EB))) ] + else [ ((u.st <> I) and + (v.st <> I) and + (reply<<n>>(v,neighbors,reply_l) = v.par) and + (v.d >= u.d + 1) and + ((v.st = u.st) or (u.st = EB))) ] | children<<n-1>>(u,neighbors[1..n-1],reply_l[1..n-1]); +tel; + +function abRoot<<const n:int>>(this : state; neighbors : state^n) +returns(res : bool); +var par_u: state; +let + par_u= parent<<n,0>>(this, neighbors); + res = (this.st <> I) and ( (this.par > n) or + (par_u.st = I) or + (this.d < (par_u.d + (1))) or + (this.st <> par_u.st and par_u.st <> EB)); +tel; + +function p_reset<<const n:int>>(this : state; neighbors: state^n) +returns (res : bool); +let + res = ( (this.st = EF) and (abRoot<<n>>(this,neighbors)) ); +tel; + +function condition(elem:state; this:state) returns(res : bool); +let + res = (elem.st = C) and (elem.d + 1 < this.d); +tel; + +function p_correction<<const n:int>>(this : state; neighbors : state^n) +returns(res : bool); +let + res = n_or<<n>>(map<<condition,n>>(neighbors,(this^n))); +tel; + +--------------------------------------------------------------------- +--Macro: +function argmin<<const n:int; const count:int; const indice:int>>(min:state; nl : state^n) +returns(res : int); +let + res = with ( n = 1) then (if nl[0].st = C and min.st = C then + if (nl[0].d + 1) <= (min.d + 1) then count else indice + else if nl[0].st = C then count else indice) + else (if nl[0].st = C and min.st = C then + if (nl[0].d + 1) <= (min.d + 1) then argmin<<n-1,count+1,count>>(nl[0],nl[1..n-1]) + else argmin<<n-1,count+1,indice>>(min,nl[1..n-1]) + else + argmin<<n-1,count+1,count>>(nl[0],nl[1..n-1]) + ); +tel; + +function computePath<<const n:int>>(this : state ; neighbors : state^n) +returns(res : state); +var par_u:state; +let + par_u = parent<<n,0>>(this,neighbors); + res = state { st = C; + par = argmin<<n,0,-1>>((state { st=EB; par=-1; d=-1 }), neighbors); + d = (par_u.d + 1); }; +tel; + +--------------------------------------------------------------------- +--Enable Macro function: +function for_all<<const n:int>>(neigh_list: state^n; bool_list: bool^n) +returns (res : bool); +let + res = with (n = 1) then (if bool_list[0] = true + then neigh_list[0].st = EF + else true) + else (if bool_list[0] = true + then (neigh_list[0].st = EF) and (for_all<<n-1>>(neigh_list[1 .. n-1], bool_list[1 .. n-1])) + else (for_all<<n-1>>(neigh_list[1 .. n-1], bool_list[1 .. n-1]))); +tel; + +function not_equal_c (elem:state) +returns (res : bool); +let + res = (elem.st<>C); +tel; + +function equal_c (elem:state) +returns (res : bool); +let + res = (elem.st=C); +tel; +-------------------------------------------------------------------- +--Step and Enable functions: +function p_enable<<const degree:int>>(this : state; neighbors : state^degree; reply_l: int^degree) +returns (enabled : bool^actions_number); +var + par_u:state; + bool_list:bool^degree; +let + par_u = parent<<degree,0>>(this, neighbors); + bool_list = children<<degree>>(this, neighbors, reply_l); + enabled = [ ((this.st = C) and p_correction<<degree>>(this,neighbors)), + ((this.st = C) and (not (p_correction<<degree>>(this,neighbors))) and ((abRoot<<degree>>(this,neighbors)) or (par_u.st = EB))), + ((this.st = EB) and (for_all<<degree>>(neighbors, bool_list))), + ((p_reset<<degree>>(this, neighbors)) and boolred<<degree,degree,degree>>(map<< not_equal_c , degree>>(neighbors))), + (((p_reset<<degree>>(this,neighbors)) or this.st = I) and (boolred<<1,degree,degree>>(map<< equal_c , degree>>(neighbors)))) + ]; +tel; + +function p_step<<const degree:int>>( + this : state; + neighbors : state^degree; + action : action) +returns (new : state); +let + new = if (action = Rc) then computePath<<degree>>(this, neighbors) + else if (action = Reb) then state { st = EB; par = this.par; d = this.d } + else if (action = Ref) then state { st = EF; par = this.par; d = this.d } + else if (action = Ri) then state { st = I; par = this.par; d = this.d } + else if (action = Rr) then computePath<<degree>>(this, neighbors) + else this; +tel; diff --git a/test/rsp_tree/p.ml b/test/rsp_tree/p.ml new file mode 120000 index 0000000000000000000000000000000000000000..e13d0969a16d449d2c52597c117fe513d173090e --- /dev/null +++ b/test/rsp_tree/p.ml @@ -0,0 +1 @@ +../../../test/rsp-tree/p.ml \ No newline at end of file diff --git a/test/rsp_tree/root.lus b/test/rsp_tree/root.lus new file mode 100644 index 0000000000000000000000000000000000000000..cfece2221e7496b34ceb13dd0be0161c342f8827 --- /dev/null +++ b/test/rsp_tree/root.lus @@ -0,0 +1,33 @@ +------------------------------------------------------- +--Settings: +type status = enum { I, C, EB, EF }; +type state = struct { st:status; par:int; d:int }; + +type action = enum { Rc,Reb,Ref,Ri,Rr }; +const actions_number = 5; + +function action_of_int(i : int ) returns (a : action); +let + a = if i = 0 then Rc + else if i = 1 then Reb + else if i = 2 then Ref + else if i = 3 then Ri + else Rr; +tel; + +------------------------------------------------------- +--Step and Enable functions(for root): +function root_enable<<const degree:int>>(this : state; neighbors : state^degree) +returns (enabled : bool^actions_number); +let + enabled = [ false, false, false, false, false ] ; +tel; + +function root_step<<const degree:int>>( + this : state; + neighbors : state^degree; + action : action) +returns (new : state); +let + new = state { st=C; par=-1; d=0 }; +tel; \ No newline at end of file diff --git a/test/rsp_tree/root.ml b/test/rsp_tree/root.ml new file mode 120000 index 0000000000000000000000000000000000000000..086c6666a388c7aa7ba8e824a16e6e6367017bbf --- /dev/null +++ b/test/rsp_tree/root.ml @@ -0,0 +1 @@ +../../../test/rsp-tree/root.ml \ No newline at end of file diff --git a/test/rsp_tree/rsp_tree_oracle.lus b/test/rsp_tree/rsp_tree_oracle.lus new file mode 100644 index 0000000000000000000000000000000000000000..7033662016cee16998e8e9885a4de1e3fa4d5964 --- /dev/null +++ b/test/rsp_tree/rsp_tree_oracle.lus @@ -0,0 +1,25 @@ + +-- Here, we use the Lustre version of the algorithm as an oracle for the ocaml version + +include "../../lib/utils.lus" + +node rsp_tree_oracle( + legitimate : bool; + ocaml_enabled : bool^actions_number^card; + active : bool^actions_number^card; + ocaml_config : state^card; +) +returns (ok : bool; lustre_config : state^card; + lustre_enabled : bool^actions_number^card;); +-- var + +let + lustre_config, lustre_enabled = + topology(active -> pre active, -- ignored at the first step + ocaml_config -- used at the first step only + ); + ok = lustre_enabled = ocaml_enabled + -- compare the sasa dot interpretation and the salut dot to lustre compilation + and lustre_config = ocaml_config; + -- compare the lustre and the ocaml version of the processes +tel diff --git a/test/rsp_tree/state.ml b/test/rsp_tree/state.ml new file mode 120000 index 0000000000000000000000000000000000000000..ac63100f73e5f8bcf1a59ba9a370819938e57871 --- /dev/null +++ b/test/rsp_tree/state.ml @@ -0,0 +1 @@ +../../../test/rsp-tree/state.ml \ No newline at end of file diff --git a/test/rsp_tree/tree4.lus b/test/rsp_tree/tree4.lus new file mode 100644 index 0000000000000000000000000000000000000000..cee55d5150e7f4594fa41aa2f324b822f0f49aaa --- /dev/null +++ b/test/rsp_tree/tree4.lus @@ -0,0 +1,77 @@ +-- 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/test/rsp_tree/tree4_oracle.lus b/test/rsp_tree/tree4_oracle.lus new file mode 100644 index 0000000000000000000000000000000000000000..deb6b80e61dc3a1f1cb22b8ed13466dd2bd70925 --- /dev/null +++ b/test/rsp_tree/tree4_oracle.lus @@ -0,0 +1,51 @@ +-- Automatically generated by /home/emile/.opam/4.12.0/bin/sasa version "v4.6.1" ("c3dfe95") +-- on PC-Travail the 20/6/2022 at 14:52:03 +--sasa -glos tree4.dot + +include "rsp_tree_oracle.lus" +const an=5; -- actions number +const pn=4; -- processes number +const degree=2; +const min_degree=1; +const mean_degree=1.500000; +const diameter=3; +const card=4; +const links_number=3; +const is_cyclic=false; +const is_connected=true; +const is_a_tree=true; +const f=false; +const t=true; +const adjacency=[ + [f,t,t,f], + [t,f,f,t], + [t,f,f,f], + [f,t,f,f]]; +const mean_deg=1.5; +const max_deg=2; +const is_tree=true; +const is_rooted=false; +const min_deg=1; + +node oracle(legitimate:bool; + Root_d:int;Root_par:int;Root_st:status;p1_d:int;p1_par:int;p1_st:status;p2_d:int;p2_par:int;p2_st:status;p3_d:int;p3_par:int;p3_st:status; + Enab_Root_Rcu,Enab_Root_Rebu,Enab_Root_Refu,Enab_Root_Riu,Enab_Root_Rru,Enab_p1_Rcu,Enab_p1_Rebu,Enab_p1_Refu,Enab_p1_Riu,Enab_p1_Rru,Enab_p2_Rcu,Enab_p2_Rebu,Enab_p2_Refu,Enab_p2_Riu,Enab_p2_Rru,Enab_p3_Rcu,Enab_p3_Rebu,Enab_p3_Refu,Enab_p3_Riu,Enab_p3_Rru:bool; + Root_Rcu,Root_Rebu,Root_Refu,Root_Riu,Root_Rru,p1_Rcu,p1_Rebu,p1_Refu,p1_Riu,p1_Rru,p2_Rcu,p2_Rebu,p2_Refu,p2_Riu,p2_Rru,p3_Rcu,p3_Rebu,p3_Refu,p3_Riu,p3_Rru:bool) +returns (ok:bool; lustre_config:state^4; lustre_enab:bool^an^pn); +var + Acti:bool^an^pn; + Enab:bool^an^pn; + Config:state^4; + a,b,c,d:state; +let + Acti = [[Root_Rcu,Root_Rebu,Root_Refu,Root_Riu,Root_Rru],[p1_Rcu,p1_Rebu,p1_Refu,p1_Riu,p1_Rru],[p2_Rcu,p2_Rebu,p2_Refu,p2_Riu,p2_Rru],[p3_Rcu,p3_Rebu,p3_Refu,p3_Riu,p3_Rru]]; + Enab = [[Enab_Root_Rcu,Enab_Root_Rebu,Enab_Root_Refu,Enab_Root_Riu,Enab_Root_Rru],[Enab_p1_Rcu,Enab_p1_Rebu,Enab_p1_Refu,Enab_p1_Riu,Enab_p1_Rru],[Enab_p2_Rcu,Enab_p2_Rebu,Enab_p2_Refu,Enab_p2_Riu,Enab_p2_Rru],[Enab_p3_Rcu,Enab_p3_Rebu,Enab_p3_Refu,Enab_p3_Riu,Enab_p3_Rru]]; + a=state { d=Root_d; par=Root_par; st=Root_st }; + b=state { d=p1_d; par=p1_par; st=p1_st }; + c=state { d=p2_d; par=p2_par; st=p2_st }; + d=state { d=p3_d; par=p3_par; st=p3_st }; + Config = [a,b,c,d]; + + ok,lustre_config, lustre_enab = rsp_tree_oracle(legitimate, Enab, Acti, Config); +tel +node to_state(int,int,int) returns (res:status); \ No newline at end of file diff --git a/test/rsp_tree/verify.lus b/test/rsp_tree/verify.lus new file mode 100644 index 0000000000000000000000000000000000000000..afb12854e8a17ff37d6e281120bc2e6b6762ec7b --- /dev/null +++ b/test/rsp_tree/verify.lus @@ -0,0 +1,50 @@ +include "../../lib/sas.lus" + +node verify(activations : bool^actions_number^card; inits : state^card) returns (ok : bool); +var + config : state^card; + enables : bool^actions_number^card; + legitimate, closure, Round : bool; + RoundNb : int; +let +-- assert(true -> daemon_is_locally_central<<actions_number,card>>(activations, pre enables, adjacency)); + assert(true -> daemon_is_central<<actions_number,card>>(activations, pre enables)); + assert(rangei<<0,card>>(inits)); + + config, enables = topology(activations, inits); + + legitimate = silent<<actions_number,card>>(enables); + closure = true -> (pre(legitimate) => legitimate); + Round = round <<actions_number,card>>(enables,activations); + RoundNb = round_count(Round, legitimate); + + -- verify that the execution terminates after at most |N|−1 moves: + ok = closure + and ( not(legitimate) and is_connected => (RoundNb < 3*card+diameter) ) +; +tel; + +---------------------------------------------------------------------------- +function lower_or_egal(x:state; y:state) +returns(res : bool); +let + res = (x.d <= y.d) and (x.par <= y.d); +tel; + +function lower(x:state; y:state) +returns(res : bool); +let + res = (x.d < y.d) and (x.par < y.d); +tel; + +-- all states are initially in [0; card|[ +node rangei<<const low:int; const card:int>>(c:state^card) returns (res:bool); +var + ranges_min, ranges_max : bool^card; +const low_state = state { d = low; par = low; st = I}; +const card_state = state { d = card; par = card; st = EF }; +let + ranges_min = map<< lower_or_egal , card>>(low_state^card, c); + ranges_max = map<< lower , card>>(c, card_state^card); + res = boolall<<card>>(ranges_min) and boolall<<card>>(ranges_max); +tel