
// 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;
init q1;
accept q2, q3, q4, q5;
trans
q1 -> q1 {},
q1 -> q2 { guard (waiting[0] == 1) && not (P_0.CS); },
q1 -> q3 { guard (waiting[1] == 1) && not (P_1.CS); },
q1 -> q4 { guard (waiting[2] == 1) && not (P_2.CS); },
q2 -> q2 { guard not (P_0.CS); },
q2 -> q5 { guard not (P_0.CS) && not (waiting[0] == 1); },
q3 -> q3 { guard not (P_1.CS); },
q3 -> q5 { guard not (P_1.CS) && not (waiting[1] == 1); },
q4 -> q4 { guard not (P_2.CS); },
q4 -> q5 { guard not (P_2.CS) && not (waiting[2] == 1); },
q5 -> q5 {};
}

system async property LTL_property;
