
// peterson mutual exclusion protocol for N processes

byte pos[3];
byte step[3];
byte in_critical = 0;

byte active = 0;
byte waiting[3] = {0 ,0 ,0  };

process P_0 {
byte j=0, k=0;
state NCS, CS, wait ,q2,q3;
init NCS;
trans
 
 NCS -> wait { effect j = 1, active = 0, waiting[0] = 1; },
 wait -> q2  { guard j < 3; effect pos[0] = j, active = 0;},
 q2 -> q3 { effect step[j-1] = 0, k = 0, active = 0; },
 q3 -> q3 { guard k < 3 && (k == 0 || pos[k]< j); effect k = k+1,
               active = 0;},
 q3 -> wait { guard step[j-1] != 0 || k == 3; effect j = j+1, active = 0;},
 wait -> CS { guard j == 3; effect in_critical = in_critical+1, active = 0, waiting[0] = 0;},
 CS -> NCS { effect pos[0] = 0, in_critical = in_critical-1, active = 0;};
}
process P_1 {
byte j=0, k=0;
state NCS, CS, wait ,q2,q3;
init NCS;
trans
 
 NCS -> wait { effect j = 1, active = 1, waiting[1] = 1; },
 wait -> q2  { guard j < 3; effect pos[1] = j, active = 1;},
 q2 -> q3 { effect step[j-1] = 1, k = 0, active = 1; },
 q3 -> q3 { guard k < 3 && (k == 1 || pos[k]< j); effect k = k+1,
               active = 1;},
 q3 -> wait { guard step[j-1] != 1 || k == 3; effect j = j+1, active = 1;},
 wait -> CS { guard j == 3; effect in_critical = in_critical+1, active = 1, waiting[1] = 0;},
 CS -> NCS { effect pos[1] = 0, in_critical = in_critical-1, active = 1;};
}
process P_2 {
byte j=0, k=0;
state NCS, CS, wait ,q2,q3;
init NCS;
trans
 
 NCS -> wait { effect j = 1, active = 2, waiting[2] = 1; },
 wait -> q2  { guard j < 3; effect pos[2] = j, active = 2;},
 q2 -> q3 { effect step[j-1] = 2, k = 0, active = 2; },
 q3 -> q3 { guard k < 3 && (k == 2 || pos[k]< j); effect k = k+1,
               active = 2;},
 q3 -> wait { guard step[j-1] != 2 || k == 3; effect j = j+1, active = 2;},
 wait -> CS { guard j == 3; effect in_critical = in_critical+1, active = 2, waiting[2] = 0;},
 CS -> NCS { effect pos[2] = 0, in_critical = in_critical-1, active = 2;};
}

process LTL_property {
state q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27;
init q27;
accept q2, q4, q6;
trans
q1 -> q7 {},
q2 -> q8 { guard not (P_0.CS); },
q3 -> q9 {},
q4 -> q10 { guard not (P_1.CS); },
q5 -> q5 {},
q5 -> q6 { guard not (P_2.CS); },
q6 -> q11 { guard not (P_2.CS); },
q6 -> q12 { guard not (P_2.CS) && (active == 2); },
q7 -> q13 {},
q8 -> q14 { guard not (P_0.CS); },
q9 -> q9 {},
q9 -> q15 { guard not (P_1.CS); },
q10 -> q15 { guard not (P_1.CS); },
q11 -> q11 { guard not (P_2.CS); },
q11 -> q12 { guard not (P_2.CS) && (active == 2); },
q12 -> q16 { guard not (P_2.CS); },
q13 -> q17 {},
q14 -> q18 { guard not (P_0.CS); },
q15 -> q15 { guard not (P_1.CS); },
q15 -> q19 { guard not (P_1.CS) && (active == 1); },
q16 -> q20 { guard not (P_2.CS); },
q17 -> q17 {},
q17 -> q21 { guard not (P_0.CS); },
q18 -> q21 { guard not (P_0.CS); },
q19 -> q22 { guard not (P_1.CS); },
q20 -> q23 { guard not (P_2.CS); },
q21 -> q21 { guard not (P_0.CS); },
q21 -> q24 { guard not (P_0.CS) && (active == 0); },
q22 -> q25 { guard not (P_1.CS); },
q23 -> q26 { guard not (P_2.CS); },
q24 -> q2 { guard not (P_0.CS); },
q25 -> q4 { guard not (P_1.CS); },
q26 -> q6 { guard not (P_2.CS); },
q27 -> q1 {},
q27 -> q3 {},
q27 -> q5 {};
}

system async property LTL_property;
