mdp
const int N = 3;
const int MAX = 4;
formula leaders_agree1 = (p1=1 | r1<max(r1,r2,r3)) & (p2=1 | r2<max(r1,r2,r3)) & (p3=1 | r3<max(r1,r2,r3));
formula leaders_agree2 = (p1=2 | r1<max(r1,r2,r3)) & (p2=2 | r2<max(r1,r2,r3)) & (p3=2 | r3<max(r1,r2,r3));
formula decide1 = leaders_agree1 & (p1=1 | r1<max(r1,r2,r3)-1) & (p2=1 | r2<max(r1,r2,r3)-1) & (p3=1 | r3<max(r1,r2,r3)-1);
formula decide2 = leaders_agree2 & (p1=2 | r1<max(r1,r2,r3)-1) & (p2=2 | r2<max(r1,r2,r3)-1) & (p3=2 | r3<max(r1,r2,r3)-1);
module process1
s1 : [0..5];
r1 : [0..MAX];
p1 : [0..2];
[] s1=0 & r1=0 -> (p1'=1) & (r1'=1);
[] s1=0 & r1=0 -> (p1'=2) & (r1'=1);
[] s1=0 & r1>0 & r1<=MAX -> (s1'=1);
[] s1=1 & decide1 -> (s1'=4) & (p1'=1);
[] s1=1 & decide2 -> (s1'=4) & (p1'=2);
[] s1=1 & r1<MAX & leaders_agree1 & !decide1 -> (s1'=0) & (p1'=1) & (r1'=r1+1);
[] s1=1 & r1<MAX & leaders_agree2 & !decide2 -> (s1'=0) & (p1'=2) & (r1'=r1+1);
[] s1=1 & r1<MAX & !(leaders_agree1 | leaders_agree2) -> (s1'=2) & (p1'=0);
[] s1=1 & r1=MAX & !(decide1 | decide2) -> (s1'=5);
[coin1_s1_start] s1=2 & r1=1 -> (s1'=3);
[coin2_s1_start] s1=2 & r1=2 -> (s1'=3);
[coin3_s1_start] s1=2 & r1=3 -> (s1'=3);
[coin1_s1_p1] s1=3 & r1=1 -> (s1'=0) & (p1'=1) & (r1'=r1+1);
[coin1_s1_p2] s1=3 & r1=1 -> (s1'=0) & (p1'=2) & (r1'=r1+1);
[coin2_s1_p1] s1=3 & r1=2 -> (s1'=0) & (p1'=1) & (r1'=r1+1);
[coin2_s1_p2] s1=3 & r1=2 -> (s1'=0) & (p1'=2) & (r1'=r1+1);
[coin3_s1_p1] s1=3 & r1=3 -> (s1'=0) & (p1'=1) & (r1'=r1+1);
[coin3_s1_p2] s1=3 & r1=3 -> (s1'=0) & (p1'=2) & (r1'=r1+1);
[done] s1>=4 -> true;
endmodule
module process2 = process1[ s1=s2,
p1=p2,p2=p3,p3=p1,
r1=r2,r2=r3,r3=r1,
coin1_s1_start=coin1_s2_start,coin2_s1_start=coin2_s2_start,coin3_s1_start=coin3_s2_start,
coin1_s1_p1=coin1_s2_p1,coin2_s1_p1=coin2_s2_p1,coin3_s1_p1=coin3_s2_p1,
coin1_s1_p2=coin1_s2_p2,coin2_s1_p2=coin2_s2_p2,coin3_s1_p2=coin3_s2_p2 ]
endmodule
module process3 = process1[ s1=s3,
p1=p3,p2=p1,p3=p2,
r1=r3,r2=r1,r3=r2,
coin1_s1_start=coin1_s3_start,coin2_s1_start=coin2_s3_start,coin3_s1_start=coin3_s3_start,
coin1_s1_p1=coin1_s3_p1,coin2_s1_p1=coin2_s3_p1,coin3_s1_p1=coin3_s3_p1,
coin1_s1_p2=coin1_s3_p2,coin2_s1_p2=coin2_s3_p2,coin3_s1_p2=coin3_s3_p2 ]
endmodule
module coin1_error
c1 : [0..1];
v1 : [0..2];
[coin1_s1_p1] v1=0 -> (v1'=1);
[coin1_s2_p1] v1=0 -> (v1'=1);
[coin1_s3_p1] v1=0 -> (v1'=1);
[coin1_s1_p2] v1=0 -> (v1'=2);
[coin1_s2_p2] v1=0 -> (v1'=2);
[coin1_s3_p2] v1=0 -> (v1'=2);
[coin1_s1_p1] v1=1 -> true;
[coin1_s2_p1] v1=1 -> true;
[coin1_s3_p1] v1=1 -> true;
[coin1_s1_p2] v1=2 -> true;
[coin1_s2_p2] v1=2 -> true;
[coin1_s3_p2] v1=2 -> true;
[coin1_s1_p1] v1=2 -> (c1'=1);
[coin1_s2_p1] v1=2 -> (c1'=1);
[coin1_s3_p1] v1=2 -> (c1'=1);
[coin1_s1_p2] v1=1 -> (c1'=1);
[coin1_s2_p2] v1=1 -> (c1'=1);
[coin1_s3_p2] v1=1 -> (c1'=1);
endmodule
module coin2_error
c2 : [0..1];
v2 : [0..2];
[coin2_s1_p1] v2=0 -> (v2'=1);
[coin2_s2_p1] v2=0 -> (v2'=1);
[coin2_s3_p1] v2=0 -> (v2'=1);
[coin2_s1_p2] v2=0 -> (v2'=2);
[coin2_s2_p2] v2=0 -> (v2'=2);
[coin2_s3_p2] v2=0 -> (v2'=2);
[coin2_s1_p1] v2=1 -> true;
[coin2_s2_p1] v2=1 -> true;
[coin2_s3_p1] v2=1 -> true;
[coin2_s1_p2] v2=2 -> true;
[coin2_s2_p2] v2=2 -> true;
[coin2_s3_p2] v2=2 -> true;
[coin2_s1_p1] v2=2 -> (c2'=1);
[coin2_s2_p1] v2=2 -> (c2'=1);
[coin2_s3_p1] v2=2 -> (c2'=1);
[coin2_s1_p2] v2=1 -> (c2'=1);
[coin2_s2_p2] v2=1 -> (c2'=1);
[coin2_s3_p2] v2=1 -> (c2'=1);
endmodule
label "one_proc_err" = (s1=5 | s2=5 | s3=5);
label "one_coin_ok" = (c1=0 | c2=0);