From 4aa645f4be744ddfce243d3d232d4e41d88c3da4 Mon Sep 17 00:00:00 2001 From: invite <invite@debian> Date: Fri, 1 Jul 2022 09:47:03 +0200 Subject: [PATCH] add kclustering --- test/coloring/Makefile | 4 +- test/coloring/dice5_oracle.lus | 26 ----- test/kclustering/Makefile | 27 ++++++ test/kclustering/config.ml | 1 + test/kclustering/cost.lus | 33 +++++++ test/kclustering/kclustering_oracle.lus | 31 ++++++ test/kclustering/p.lus | 121 ++++++++++++++++++++++++ test/kclustering/p.ml | 1 + test/kclustering/state.ml | 1 + test/kclustering/verify.lus | 55 +++++++++++ 10 files changed, 272 insertions(+), 28 deletions(-) delete mode 100644 test/coloring/dice5_oracle.lus create mode 100644 test/kclustering/Makefile create mode 120000 test/kclustering/config.ml create mode 100644 test/kclustering/cost.lus create mode 100644 test/kclustering/kclustering_oracle.lus create mode 100644 test/kclustering/p.lus create mode 120000 test/kclustering/p.ml create mode 120000 test/kclustering/state.ml create mode 100644 test/kclustering/verify.lus diff --git a/test/coloring/Makefile b/test/coloring/Makefile index 952d8bca..2fa29b08 100644 --- a/test/coloring/Makefile +++ b/test/coloring/Makefile @@ -26,8 +26,8 @@ simu: clique3.simu # Compare the ocaml version with the lustre one # XXX todo : write a coloring_oracle.lus similar to ../dijkstra-ring/dijkstra_ring_oracle.lus -#compare: clique3.lurette -# cat dijkstra-ring.rif +compare: clique3.lurette + cat coloring.rif kind2: clique3.kind2 diff --git a/test/coloring/dice5_oracle.lus b/test/coloring/dice5_oracle.lus deleted file mode 100644 index dbce57df..00000000 --- a/test/coloring/dice5_oracle.lus +++ /dev/null @@ -1,26 +0,0 @@ -include "dice5.lus" -include "verify.lus" - -node topology = dice5; -const an = actions_number; -const pn = card; - -node oracle( - p0_color:int;p1_color:int;p2_color:int;p3_color:int;p4_color:int; - Enab_p0_recolor,Enab_p1_recolor,Enab_p2_recolor,Enab_p3_recolor,Enab_p4_recolor:bool; - p0_recolor,p1_recolor,p2_recolor,p3_recolor,p4_recolor:bool) -returns (ok:bool); -var - Acti:bool^an^pn; - Enab:bool^an^pn; - Stat : state^pn; - nodes : state^pn; - enables : bool^an^pn; -let - Acti = [[p0_recolor],[p1_recolor],[p2_recolor],[p3_recolor],[p4_recolor]]; - Enab = [[Enab_p0_recolor],[Enab_p1_recolor],[Enab_p2_recolor],[Enab_p3_recolor],[Enab_p4_recolor]]; - Stat = [ p0_color, p1_color, p2_color, p3_color, p4_color ]; - - nodes, enables = topology(pre(Acti), Stat); - ok = enables = Enab and boolred<<pn,pn,pn>>(map<<=,pn>>(nodes, Stat)); -tel; diff --git a/test/kclustering/Makefile b/test/kclustering/Makefile new file mode 100644 index 00000000..19d67dcf --- /dev/null +++ b/test/kclustering/Makefile @@ -0,0 +1,27 @@ +TOPOLOGY ?= tree3 +DOT2LUSFLAGS ?= +SASA_ALGOS := p.ml +DECO_PATTERN="0-:p.ml" + + +include ~/sasa/salut/test/Makefile.inc +-include ~/sasa/salut/test/Makefile.dot + +clean: genclean + rm -f tree*.* + +## Some examples of use of ../Makefile.inc + + +# run a simulation with luciole +simu: tree3.simu + +# Compare the ocaml version with the lustre one +compare: tree3.lurette + cat kclustering.rif + +# make diring4.simu +kind2: tree3.kind2 + +## do not work because there is a modulo in p.lus, which is not (yet) implemented in ../../bit-blast/*.lus +lesar: tree3.lesar diff --git a/test/kclustering/config.ml b/test/kclustering/config.ml new file mode 120000 index 00000000..cd1408a5 --- /dev/null +++ b/test/kclustering/config.ml @@ -0,0 +1 @@ +../../../test/k-clustering/config.ml \ No newline at end of file diff --git a/test/kclustering/cost.lus b/test/kclustering/cost.lus new file mode 100644 index 00000000..c9d2c121 --- /dev/null +++ b/test/kclustering/cost.lus @@ -0,0 +1,33 @@ +include "p.lus" +const debug=false; + +function parentd<<const card:int;const n:int>>(p:state ; config:state^card) returns (parp:state); +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; +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)]); +tel + +node pot<<const card:int>>(p:state;config:state^card) returns (nat:int); +let +nat= if p_enable<<n>>(p,config)= [true] then depth<<card>>(p,config) else 0; +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/test/kclustering/kclustering_oracle.lus b/test/kclustering/kclustering_oracle.lus new file mode 100644 index 00000000..9b623fc2 --- /dev/null +++ b/test/kclustering/kclustering_oracle.lus @@ -0,0 +1,31 @@ +-- Here, we use the Lustre version of the algorithm as an oracle for the ocaml version + +include "../../sasa/salut/lib/utils.lus" +--include "cost.lus" +node kclustering_oracle( + legitimate : bool; + -- ocaml_cost : real; + ocaml_enabled : bool^actions_number^card; + active : bool^actions_number^card; + ocaml_config : state^card; +) +returns (ok : bool) +var + lustre_config : state^card; + lustre_enabled : bool^actions_number^card; +-- lustre_cost:int; +let + lustre_config, lustre_enabled = + topology(active -> pre active, -- ignored at the first step + ocaml_config -- used at the first step only + ); + -- lustre_cost = cost(lustre_enabled, lustre_config); + 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 + -- and Lustre::real2int(ocaml_cost) = lustre_cost; + -- compare the cost functions +tel + + diff --git a/test/kclustering/p.lus b/test/kclustering/p.lus new file mode 100644 index 00000000..3b2f8457 --- /dev/null +++ b/test/kclustering/p.lus @@ -0,0 +1,121 @@ +type state= struct{isRoot:bool; alpha:int ; par:int}; +type action=enum{change_alpha}; +const actions_number=1; +const k= 2 ; +function action_of_int (i:int) returns (a:action); +let +a=change_alpha; +tel + +function isRoot(p:state) returns (b:bool); +let +b=p.isRoot; +tel + +function isShort (p:state) returns (b:bool); +let +b= p.alpha < k; +tel + +function isTall (p:state) returns (b:bool); +let +b= p.alpha >= k; +tel + +function kDominator (p:state) returns (b:bool); +let +b= (p.alpha = k) or (isShort(p) and isRoot(p)); +tel + +function reply<<const n:int>>(p:state;nl:state^n;rl:int^n) returns (r:int); +let +r=with (n=1) then rl[0] + else if p=nl[0] then rl[0] else reply<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]); +tel + +function children<<const n:int>>(p:state; nl:state^n; rl:int^n) returns (cl:bool^n); +let +cl= with (n=1) then [ nl[0].par=reply<<n>>(nl[0],nl,rl) ] + else [nl[0].par=reply<<n>>(nl[0],nl,rl)] | children<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) +; +tel + +function shortChildren<<const n:int>>(p:state; nl:state^n;rl:int^n) returns (sl:bool^n); +var c:bool^n; +let +c=children<<n>>(p,nl,rl); +sl= with (n=1) then [c[0]=true and isShort(nl[0])] + else [(c[0]=true and isShort(nl[0]))] | shortChildren <<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) ; + +tel + +function tallChildren<<const n:int>>(p:state; nl: state^n;rl:int^n) returns (tl:bool^n) ; +var c:bool^n; +let +c=children<<n>>(p,nl,rl); +tl=with (n=1) then [c[0]=true and isTall(nl[0])] + else [c[0]=true and isTall(nl[0])] | tallChildren <<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) ; +tel + +function max<<const n:int>>(p:state;nl:state^n;rl:int^n) returns (m:int); +var scd:bool^n; +let +scd=shortChildren<<n>>(p,nl,rl); +m=with (n=1) then if scd[0]=true then nl[0].alpha else 0 + else if scd[0]=true then if nl[0].alpha > max<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) then nl[0].alpha + else max<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) + else max<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]); +tel + +function min<<const n:int>>(p:state;nl:state^n;rl:int^n) returns (m:int); +var tcd: bool^n; +let +tcd=tallChildren<<n>>(p,nl,rl); +m=with (n=1) then if tcd[0]=true then nl[0].alpha else -1 + else if tcd[0]=true then if min<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)])<>(-1) + + then if nl[0].alpha < min<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) + then nl[0].alpha + else min<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]) + else nl[0].alpha + + else min<<n-1>>(p,nl[1..(n-1)],rl[1..(n-1)]); +tel + +function maxAshort<<const n:int>>(p:state ; nl:state^n;rl:int^n) returns (max:int); +var scd:bool^n; +let +scd=shortChildren<<n>>(p,nl,rl); +max= if boolred<<0,0,n>>(scd) then -1 else max<<n>>(p,nl,rl); +tel + +function minAtall<<const n:int>>(p:state ; nl:state^n; rl:int^n) returns (min:int); +var tcd:bool^n; +let +tcd=tallChildren<<n>>(p,nl,rl); +min= if boolred<<0,0,n>>(tcd) then (2*k + 1)else min<<n>>(p,nl,rl); +tel + +function newAlpha<<const n:int>>(p:state; nl:state^n;rl:int^n) returns (x:int); +var mas,mit:int; +let +mas=maxAshort<<n>>(p,nl,rl); +mit=minAtall<<n>>(p,nl,rl); +x=if (mas + mit) <= ((2*k)-2) + then (mit + 1) + else (mas + 1 ); +tel + +function p_enable<<const n:int>>(p:state ; nl:state^n; rl:int^n) returns +(a:bool^actions_number); +let +a= [p.alpha <> newAlpha<<n>>(p,nl,rl)]; +tel + +function p_step <<const n:int>>(p:state; nl:state^n;rl:int^n; a:action) +returns (pnew:state); +let +pnew = state{isRoot=p.isRoot; alpha=newAlpha<<n>>(p,nl,rl); par=p.par} ; +tel + +--rl=reply list \ No newline at end of file diff --git a/test/kclustering/p.ml b/test/kclustering/p.ml new file mode 120000 index 00000000..24d41e87 --- /dev/null +++ b/test/kclustering/p.ml @@ -0,0 +1 @@ +../../../test/k-clustering/p.ml \ No newline at end of file diff --git a/test/kclustering/state.ml b/test/kclustering/state.ml new file mode 120000 index 00000000..833567ba --- /dev/null +++ b/test/kclustering/state.ml @@ -0,0 +1 @@ +../../../test/k-clustering/state.ml \ No newline at end of file diff --git a/test/kclustering/verify.lus b/test/kclustering/verify.lus new file mode 100644 index 00000000..9a5d06e4 --- /dev/null +++ b/test/kclustering/verify.lus @@ -0,0 +1,55 @@ +include "../../sasa/salut/lib/sas.lus" +include "../../sasa/salut/lib/utils.lus" + +include "cost.lus" +const worst_case=3*card*(card-1)/2 - card - 1; + +node verify( + active : bool^actions_number^card; + init_config : state^card +) +returns (ok : bool); +var + config : state^card; + enabled : bool^actions_number^card; + legitimate, closure : bool; + steps, cost : int; +let + assert(true -> daemon_is_distributed<<actions_number,card>>(active, pre enabled)); +-- assert(true -> daemon_is_synchronous<<actions_number,card>>(active, pre enabled)); + assert(rangei<<0,card>>(init_config)); + + config, enabled = topology(active, init_config); + assert(config = init_config -> true); + + -- stability in this algo means mutual exclusion: exactly 1 node is enabled at a time + legitimate = n_xor<<card>>(map<<n_or<<actions_number>>,card>> (enabled)); + closure = true -> (pre(legitimate) => legitimate); + + cost = cost(enabled, config); + -- converge = (true -> legitimate or pre(cost)>cost); + + steps = 0 -> (pre(steps) + 1); + ok = closure + -- and (steps > worst_case) => legitimate -- the worst-case stabilization + + -- and (steps > worst_case - 1) => legitimate -- is tigth! +; +tel; + +node stVint<<const card:int>>(c:state^card) returns (ca:int^card); +let +ca=with (card=1) then [c[0].alpha] + else [c[0].alpha] | stVint<<card-1>>(c[1..(card-1)]); +tel + +node rangei<<const low:int; const card:int>>(c:state^card) returns (res:bool); +var + ranges_min, ranges_max : bool^card;ca:int^card; +let + ca=stVint<<card>>(c); + ranges_min = map<< <= , card>>(low^card, ca); + ranges_max = map<< < , card>>(ca, card^card); + res = boolall<<card>>(ranges_min) and boolall<<card>>(ranges_max); +tel + -- GitLab