diff --git a/coloring/bitset.lus b/bitset.lus
similarity index 92%
rename from coloring/bitset.lus
rename to bitset.lus
index aa08e13a5c9590df6ea3f08abb023f58ce0e8ba1..36b6a029a5e89e73fcf5b075ee71b9950af4f018 100644
--- a/coloring/bitset.lus
+++ b/bitset.lus
@@ -8,7 +8,8 @@ include "utils.lus"
 function one_hot<<const N:int>>(x : int) returns (s : bool^N);
 let
 	assert(x >= 0 and x < N);
-	s = map<<=,N>>(x^N, range<<N>>(true));
+	s = map<<=,N>>(x^N, range<<N>>());
+	assert(boolred<<1,1,N>>(s));
 tel;
 
 -- Returns the complement of a given bitset.
@@ -24,9 +25,9 @@ let
 tel;
 
 -- Tests whether a bitset is empty or not.
-function none<<const N:int>>(s : bool^N) returns (y : bool);
+function is_empty<<const N:int>>(s : bool^N) returns (y : bool);
 let
-	y = pop_count<<N>>(s) = 0;
+	y = boolred<<0,0,N>>(s);
 tel;
 
 -- Bitset union.
@@ -66,7 +67,7 @@ tel;
 -- Test if two bitsets are disjoint.
 function disjoint<<const N:int>>(a, b : bool^N) returns (y : bool);
 let
-	y = none<<N>>(inter<<N>>(a, b));
+	y = is_empty<<N>>(inter<<N>>(a, b));
 tel;
 
 -- Tests whether the bitset s1 is a subset of the bitset s2.
@@ -79,7 +80,8 @@ tel;
 	Builds bitset of size N from a list of M elements, where each element in the
 	list is treated as a bit position to be set to true in the resulting bitset.
 */
-function bitset_of_list<<const N:int; const M:int>>(list : int^M) returns (set : bool^N);
+function bitset_of_list<<const N:int; const M:int>>(list : int^M)
+returns (set : bool^N);
 let
 	set = red<<set<<N>>,M>>(false^N, list);
 tel;
diff --git a/coloring/dice5_oracle.lus b/coloring/dice5_oracle.lus
index 81a79b9df93e0051be7243dcf7582899ca18137b..dbce57dfd075d670b533adbb736b6ade0ebbeb14 100644
--- a/coloring/dice5_oracle.lus
+++ b/coloring/dice5_oracle.lus
@@ -7,8 +7,8 @@ const pn = card;
 
 node oracle(
 	p0_color:int;p1_color:int;p2_color:int;p3_color:int;p4_color:int;
-	Enab_p0_recolor,Enab_p0_noop,Enab_p1_recolor,Enab_p1_noop,Enab_p2_recolor,Enab_p2_noop,Enab_p3_recolor,Enab_p3_noop,Enab_p4_recolor,Enab_p4_noop:bool;
-	p0_recolor,p0_noop,p1_recolor,p1_noop,p2_recolor,p2_noop,p3_recolor,p3_noop,p4_recolor,p4_noop:bool)
+	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;
@@ -17,8 +17,8 @@ var
 	nodes : state^pn;
 	enables : bool^an^pn;
 let
-	Acti = [[p0_recolor,p0_noop],[p1_recolor,p1_noop],[p2_recolor,p2_noop],[p3_recolor,p3_noop],[p4_recolor,p4_noop]];
-	Enab = [[Enab_p0_recolor,Enab_p0_noop],[Enab_p1_recolor,Enab_p1_noop],[Enab_p2_recolor,Enab_p2_noop],[Enab_p3_recolor,Enab_p3_noop],[Enab_p4_recolor,Enab_p4_noop]];
+	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);
diff --git a/coloring/p.lus b/coloring/p.lus
index 7b69e1d2b728e5e64730029c81dab31bd85e718c..398e2852bd18576118d446c5a2dd5dda9af6fb59 100644
--- a/coloring/p.lus
+++ b/coloring/p.lus
@@ -1,14 +1,14 @@
-include "bitset.lus"
+include "../bitset.lus"
 
 type state = int;
 
-type action = enum { recolor, noop };
-const actions_number = 2;
+type action = enum { recolor };
+const actions_number = 1;
 
 function action_of_int(i : int) returns (a : action);
 let
 	assert(i >= 0);
-	a = if i = 0 then recolor else noop;
+	a = recolor;
 tel;
 
 const K = max_degree + 1;
@@ -18,13 +18,13 @@ returns (enabled : bool^actions_number);
 	var conflict : bool;
 let
 	conflict = subset<<K>>(one_hot<<K>>(this), bitset_of_list<<K,degree>>(neighbors));
-	enabled = [ conflict, not conflict ];
+	enabled = [ conflict ];
 tel;
 
 function p_step<<const degree:int>>(this : state; neighbors : state^degree; action : action)
 returns (new : state);
 let
-	new = if action = noop then this
-	      else first_set<<K>>(diff<<K>>(true^K, bitset_of_list<<K,degree>>(neighbors)));
+	assert(action = recolor);
+	new = first_set<<K>>(diff<<K>>(true^K, bitset_of_list<<K,degree>>(neighbors)));
 	assert(new >= 0);
 tel;
diff --git a/coloring/p.ml b/coloring/p.ml
index 869d9bf302851b08242b9ce702a04c298eec13a9..99f279cf999ede6245b4fb547ed53dcbd4ae8005 100644
--- a/coloring/p.ml
+++ b/coloring/p.ml
@@ -3,11 +3,11 @@ module ColorSet = Set.Make (Int)
 type node = { color : State.t; neighbors : State.t list }
 
 let color_count = Algo.max_degree() + 1
-let colors = List.init color_count (fun x -> x) |> ColorSet.of_list
+let all_colors = List.init color_count (fun x -> x) |> ColorSet.of_list
 
 let conflict p = p.neighbors |> List.exists (fun qc -> qc = p.color)
 let used p = ColorSet.of_list p.neighbors
-let free p = ColorSet.diff colors (used p)
+let free p = ColorSet.diff all_colors (used p)
 let color p = ColorSet.min_elt (free p)
 
 let init_state : State.t Algo.state_init_fun = fun n _ -> Random.int n
@@ -15,10 +15,9 @@ let init_state : State.t Algo.state_init_fun = fun n _ -> Random.int n
 let enable_f : State.t Algo.enable_fun = fun state neighbors ->
 	if conflict { color = state; neighbors = List.map Algo.state neighbors }
 	then [ "recolor" ]
-	else [ "noop" ]
+	else [ ]
 
 let step_f : State.t Algo.step_fun = fun state neighbors action ->
 	match action with
 	| "recolor" -> color { color = state; neighbors = List.map Algo.state neighbors }
-	| "noop" -> state
 	| _ -> failwith "Invalid action"
diff --git a/coloring/state.ml b/coloring/state.ml
index 42413aa1133a07b72e54a2ce59abfd2ff7fcb74a..df321ce1563da4cb5510ce4cbb81d150acc950c9 100644
--- a/coloring/state.ml
+++ b/coloring/state.ml
@@ -2,4 +2,4 @@ type t = int
 let to_string = Printf.sprintf "color=%i"
 let of_string = None
 let copy x = x
-let actions = [ "recolor"; "noop" ]
+let actions = [ "recolor" ]
diff --git a/coloring/utils.lus b/coloring/utils.lus
deleted file mode 100644
index ded8d3ceb5a5d85ac841cf644fec21bb90e61026..0000000000000000000000000000000000000000
--- a/coloring/utils.lus
+++ /dev/null
@@ -1,14 +0,0 @@
--- Generates an array of indexes: [0, 1, ..., N-1]
-function range<<const N:int>>(_ : bool) returns (r : int^N);
-let
-	r = with (N = 1) then [ 0 ] else range<<N-1>>(true) | [ N-1 ];
-tel;
-
--- "First-class" if statement, since we don't have lambdas.
-function choice_of_bool<<type T; const t:T; const f:T>>(b : bool) returns (y : T);
-let
-	y = if b then t else f;
-tel;
-
--- |> true -> 1 | false -> 0
-function int_of_bool = choice_of_bool<<int, 1, 0>>;
diff --git a/coloring/verify.lus b/coloring/verify.lus
index c655de56e1c839deaa13d1d87ba3bbf41c4f86fc..c9e6a67d9dae21ef3b590c92024910dd069e258d 100644
--- a/coloring/verify.lus
+++ b/coloring/verify.lus
@@ -1,33 +1,23 @@
-include "../../test/lustre/oracle_utils.lus"
-
--- Any activation Ai implies Ei was previously enabled and
--- and |A| != 0 for all non-silent states (ie. it is distributed).
-node is_proper_distributed<<const an : int; const pn: int>>(acti, enab : bool^an^pn)
-returns (res : bool);
-let
-	res = all_true<<an,pn>>(map<<implies_list<<an>>,pn>>(acti, pre(enab))) and
-	      is_distributed<<an,pn>>(acti, enab);
-tel;
+include "../sas.lus"
 
 node verify(activations : bool^actions_number^card; inits : state^card) returns (ok : bool);
 var
 	nodes : state^card;
 	enables : bool^actions_number^card;
-
+	legitimate, closure : bool;
 	moves : int;
 let
-	-- we assume the daemon is proper and locally central (no two neighbors active at once)
-	assert(is_proper_distributed<<actions_number,card>>(activations, enables));
-	assert(activations[0][0] => not activations[1][0] and not activations[2][0] and not activations[3][0] and not activations[4][0]);
-	assert(activations[1][0] => not activations[0][0] and not activations[2][0] and not activations[4][0]);
-	assert(activations[2][0] => not activations[0][0] and not activations[1][0] and not activations[3][0]);
-	assert(activations[3][0] => not activations[0][0] and not activations[2][0] and not activations[4][0]);
-	assert(activations[4][0] => not activations[0][0] and not activations[1][0] and not activations[3][0]);
+	assert(daemon_is_proper<<actions_number,card>>(activations, enables));
+	assert(daemon_is_locally_central<<actions_number,card>>(adjacency, activations));
 
 	nodes, enables = topology(activations, inits);
 
-	moves = move_count<<actions_number,card>>(activations);
+	-- we assume the algo is implemented correctly and stabilizes silently
+	legitimate = silent<<actions_number,card>>(enables);
+	closure = true -> (pre(legitimate) => legitimate);
 
 	-- the execution terminates after at most |N|−1 moves
-	ok = moves = card - 1 => silent<<actions_number,card>>(enables);
+	moves = move_count<<actions_number,card>>(activations);
+	ok = closure and
+	     ((moves >= card - 1) => legitimate);
 tel;
diff --git a/sas.lus b/sas.lus
new file mode 100644
index 0000000000000000000000000000000000000000..79bffb098e66d5f6486ee7f7ac18763987d78713
--- /dev/null
+++ b/sas.lus
@@ -0,0 +1,70 @@
+include "utils.lus"
+include "bitset.lus"
+
+-- No nodes enabled.
+function silent<<const an:int; const pn:int>>(enab: bool^an^pn)
+returns (y : bool);
+let
+	y = none<<pn>>(map<<any<<an>>, pn>>(enab));
+tel;
+
+node node_is_proper<<const an:int>>(acti, enab : bool^an) returns (y : bool);
+let
+	y = true -> all<<an>>(map<<=>,an>>(acti, pre(enab)));
+tel;
+
+-- Any activation Ai implies Ei was previously enabled.
+node daemon_is_proper<<const an:int; const pn:int>>(acti, enab : bool^an^pn)
+returns (y : bool);
+let
+	y = all<<pn>>(map<<node_is_proper,pn>>(acti, enab));
+tel;
+
+-- |A| >= 1 for non-silent states.
+function daemon_is_distributed<<const an:int; const pn:int>>(acti, enab : bool^an^pn)
+returns (y : bool);
+let
+	y = silent<<an,pn>>(enab) or
+	    boolred<<1,pn,pn>>(map<<any<<an>>, pn>>(acti));
+tel;
+
+-- No two neighboring nodes are active at once.
+function daemon_is_locally_central<<const an:int; const pn:int>>(
+	adjacency : bool^pn^pn;
+	acti : bool^an^pn
+) returns (y : bool);
+var
+	active : bool ^ pn;
+	active_adjacencies : bool ^ pn ^ pn;
+	no_active_adjacencies : bool ^ pn;
+	locally_central : bool ^ pn;
+let
+	active = map<<any<<an>>, pn>>(acti);
+	active_adjacencies = map<<inter,pn>>(active^pn, adjacency);
+	no_active_adjacencies = map<<none<<pn>>, pn>>(active_adjacencies);
+	locally_central = map<<=>,pn>>(active, no_active_adjacencies);
+	y = all<<pn>>(locally_central);
+tel;
+
+-- |A| = 1 for non-silent states.
+function daemon_is_central<<const an:int; const pn:int>>(acti : bool^an^pn)
+returns (y : bool);
+let
+	y = silent<<an,pn>>(enab) or
+	    boolred<<1,1,pn>>(map<<any<<an>>, pn>>(acti));
+tel;
+
+-- |A| = n for non-silent states.
+function daemon_is_synchronous<<const an:int; const pn:int>>(acti, enab : bool^an^pn)
+returns (y:bool);
+let
+	y = silent<<an,pn>>(enab) or
+	    boolred<<pn,pn,pn>>(map<<any<<an>>, pn>>(acti));
+tel;
+
+-- Measures time complexity in moves.
+node move_count<<const an:int; const pn:int>>(acti : bool^an^pn)
+returns (count:int);
+let
+  count = (0 -> pre(count)) + pop_count<<pn>>(map<<any<<an>>, pn>>(acti));
+tel;
diff --git a/token/verify.lus b/token/verify.lus
index 6a134fc5975a364507204c464146176db8c4fec0..49ec2000f273d78dbf661b305260ead271e419cb 100644
--- a/token/verify.lus
+++ b/token/verify.lus
@@ -1,41 +1,28 @@
-include "../../test/lustre/oracle_utils.lus"
-
--- Any activation Ai implies Ei was previously enabled and
--- and |A| != 0 for all non-silent states (ie. it is distributed).
-node is_proper_distributed<<const an : int; const pn: int>>(acti, enab : bool^an^pn)
-returns (res : bool);
-let
-	res = all_true<<an,pn>>(map<<implies_list<<an>>,pn>>(acti, pre(enab))) and
-	      is_distributed<<an,pn>>(acti, enab);
-tel;
+include "../sas.lus"
+include "../utils.lus"
 
 node verify(activations : bool^actions_number^card; inits : state^card) returns (ok : bool);
 var
 	nodes : state^card;
 	enables : bool^actions_number^card;
-
+	legitimate, closure : bool;
 	tokens : int;
-	legitimate : bool;
-	closure : bool;
-
 	steps : int;
 let
-	-- we assume the daemon is proper and put no other limitation to activations
-	assert(is_proper_distributed<<actions_number,card>>(activations, enables));
+	assert(daemon_is_proper<<actions_number,card>>(activations, enables));
+	assert(daemon_is_distributed<<actions_number,card>>(activations, enables));
 
 	nodes, enables = topology(activations, inits);
 
 	-- a node "has the token" when it is enabled
-	tokens = red<<count_true_acc<<actions_number>>, card>>(0, activations);
+	tokens = pop_count<<card>>(map<<any<<actions_number>>, card>>(enables));
 
 	-- stability in this algo means mutual exclusion: 1 node enabled at a time
 	legitimate = tokens = 1;
+	closure = true -> (pre(legitimate) => legitimate);
 
-	-- once in a legitimate state, the network remains in a legitimate state
-	closure = true -> pre(legitimate) => legitimate;
-
-	steps = count(true);
+	steps = (-1 -> pre(steps)) + 1;
 	ok = (closure) and
 	     (tokens >= 1) and -- there always exists at least one token holder
-	     (steps >= 8 => legitimate); -- worst-case stabilization
+	     ((steps >= card*(card-1) + ((card-4)*(card+1)/2) + 1) => legitimate); -- worst-case stabilization
 tel;
diff --git a/utils.lus b/utils.lus
new file mode 100644
index 0000000000000000000000000000000000000000..289a88773eebfcbaf9845083ff1e241008d27d1a
--- /dev/null
+++ b/utils.lus
@@ -0,0 +1,42 @@
+-- Generates an array of indexes: [0, 1, ..., N-1]
+function range<<const N:int>>() returns (r : int^N);
+let
+	r = with (N = 1) then [ 0 ] else range<<N-1>>() | [ N-1 ];
+tel;
+
+-- "First-class" if statement, since we don't have lambdas.
+function choice_of_bool<<type T; const t:T; const f:T>>(b : bool) returns (y : T);
+let
+	y = if b then t else f;
+tel;
+
+-- |> true -> 1 | false -> 0
+function int_of_bool = choice_of_bool<<int, 1, 0>>;
+
+function none<<const N:int>>(s : bool^N) returns (y : bool);
+let
+	y = boolred<<0,0,N>>(s);
+tel;
+
+function any<<const N:int>>(s : bool^N) returns (y : bool);
+let
+	y = boolred<<1,N,N>>(s);
+tel;
+
+function all<<const N:int>>(s : bool^N) returns (y : bool);
+let
+	y = boolred<<N,N,N>>(s);
+tel;
+
+-- Whether an element is contained within an array.
+function member<<type T; const N:int>>(x : T; arr : T^N) returns (y : bool);
+let
+	y = any<<N>>(map<<=,N>>(x^N, arr));
+tel;
+
+function all_different<<type T; const N:int>>(A : T^N) returns (y : bool);
+let
+	y = with (N <= 1) then true
+	    else (not member<<T,N-1>>(A[0], A[1 .. N-1])) and
+	         all_different<<T,N-1>>(A[1 .. N-1]);
+tel;