------------------------------- MODULE Lift2 ------------------------------- (* The behvior of a lift with buttons. Both the movement of the lift and pressing buttons can be seen The lift can be thought of as stopping at loction L when goto[L] changes from TRUE to FALSE Prop0 lift can travel from any floor to any floor Prop1 any floor can request the lift by pushing a button Prop2 The lift only moves to a requested floor Prop3 (With Fairness) having requested the lift it will eventualy arrive Prop4 Lift only changes direction when there is no need to proceed *) EXTENDS Naturals, Integers, TLC, Sequences, Bags, FiniteSets CONSTANT NoOfFloors VARIABLES location, goto, direction, ghostLoc vars == <> floors == 0..NoOfFloors NoneBelow(loc) == \A x\in 0..loc : goto[x]=FALSE NoneAbove(loc) == \A x\in loc..NoOfFloors : goto[x]=FALSE Init == /\ location = 0 /\ goto = [x \in floors |-> FALSE] /\ direction = "" /\ ghostLoc = 0 \* first button press sets direction - all button presses recorded button(pressed) == /\ location /= pressed /\ pressed \in floors /\ goto[pressed] = FALSE /\ goto' = [goto EXCEPT ![pressed] = TRUE] /\ direction' = IF direction = "" /\ location > pressed THEN "down" ELSE IF direction = "" /\ location < pressed THEN "up" ELSE direction /\ UNCHANGED <> \* move one floor in direction unset button on floor you leave \* change direction only if no more floors calling lift in curent direction move == \* /\ to \in floors /\ direction /= "" /\ ghostLoc' = IF goto[location] = TRUE THEN location ELSE ghostLoc /\ goto' = [goto EXCEPT ![location] = FALSE] /\ location' = IF (direction = "up" /\ ~ NoneAbove(location+1)) THEN location +1 ELSE IF (direction = "down" /\ ~ NoneBelow(location-1)) THEN location - 1 ELSE location /\ direction' = IF direction = "up" /\ NoneAbove(location+1) THEN IF NoneBelow(location-1) THEN "" ELSE "down" ELSE IF direction = "down" /\ NoneBelow(location-1) THEN IF NoneAbove(location+1) THEN "" ELSE "up" ELSE direction Next == (\E x \in floors : button(x)) \/move Spec == Init /\ [][Next]_vars FairSpec == Spec /\ SF_vars(move) TypeInvar == location \in floors /\ direction \in {"","up","down"} Inv4up == ((direction="up"/\direction'/="up") => NoneAbove(location+1)) \* an invariant is a state predicate can not have primed variables \* I think a ghost variable, set on change, would be needed Inv4down == ((direction="down"/\direction'/="down") => NoneBelow(location-1)) Lft1 == INSTANCE Lift1 WITH location1 <- ghostLoc THEOREM Spec => Lft1!Spec ============================================================================= \* Modification History \* Last modified Thu May 21 16:50:39 NZST 2020 by dstr \* Created Wed May 20 14:20:09 NZST 2020 by dstr