datatype Variables = Variables(p1: bool, p2: bool, p3: bool, p4: bool)
ghost predicate Init(v: Variables) {
ghost predicate NextStep(v: Variables, v': Variables, step: Step)
!v.p1 && v' == v.(p1 := true)
v.p1 && v' == v.(p2 := true)
v.p2 && v' == v.(p3 := true)
v.p3 && v' == v.(p4 := true)
ghost predicate Next(v: Variables, v': Variables)
exists step: Step :: NextStep(v, v', step)
ghost predicate Safety(v: Variables)
ghost predicate Inv(v: Variables)
lemma InvInductive(v: Variables, v': Variables)
requires Inv(v) && Next(v, v')
var step :| NextStep(v, v', step);
assert NextStep(v, v', step); // by definition of :|
case Step1 => { return; }
case Step2 => { return; }
case Step3 => { return; }
lemma InvSafe(v: Variables)
ensures Inv(v) ==> Safety(v)
lemma SafetyHolds(v: Variables, v': Variables)
ensures Init(v) ==> Inv(v)
ensures Inv(v) && Next(v, v') ==> Inv(v')
ensures Inv(v) ==> Safety(v)
if Inv(v) && Next(v, v') {
predicate Inv2(v: Variables) {
lemma Inv2Holds(v: Variables, v': Variables)
ensures Init(v) ==> Inv2(v)
ensures Inv2(v) && Next(v, v') ==> Inv2(v')
assert Init(v) ==> Inv2(v);
if Inv2(v) && Next(v, v') {
var step :| NextStep(v, v', step);
case Step1 => { return; }
case Step2 => { return; }
case Step3 => { return; }
case Step4 => { return; }