You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
------------------------------ MODULEElevator ------------------------------
(***************************************************************************)(* This spec describes a simple multi-car elevator system. The actions in *)(* this spec are unsurprising and common to all such systems except for *)(* DispatchElevator, which contains the logic to determine which elevator *)(* ought to service which call. The algorithm used is very simple and does *)(* not optimize for global throughput or average wait time. The *)(* TemporalInvariant definition ensures this specification provides *)(* capabilities expected of any elevator system, such as people eventually *)(* reaching their destination floor. *)(***************************************************************************)EXTENDSIntegersCONSTANTSPerson,\* The set of all people using the elevator systemElevator,\* The set of all elevatorsFloorCount\* The number of floors serviced by the elevator systemVARIABLESPersonState,\* The state of each personActiveElevatorCalls,\* The set of all active elevator callsElevatorState\* The state of each elevatorVars==\* Tuple of all specification variables<<PersonState,ActiveElevatorCalls,ElevatorState>>Floor==\* The set of all floors1..FloorCountDirection==\* Directions available to this elevator system{"Up","Down"}ElevatorCall==\* The set of all elevator calls[floor:Floor,direction:Direction]ElevatorDirectionState==\* Elevator movement state; it is either moving in a direction or stationaryDirection\cup{"Stationary"}GetDistance[f1,f2\inFloor]==\* The distance between two floorsIFf1>f2THENf1-f2ELSEf2-f1GetDirection[current,destination\inFloor]==\* Direction of travel required to move between current and destination floorsIFdestination>currentTHEN"Up"ELSE"Down"CanServiceCall[e\inElevator,c\inElevatorCall]==\* Whether elevator is in position to immediately service callLETeState==ElevatorState[e]IN/\c.floor=eState.floor/\c.direction=eState.directionPeopleWaiting[f\inFloor,d\inDirection]==\* The set of all people waiting on an elevator call{p\inPerson:/\PersonState[p].location=f/\PersonState[p].waiting/\GetDirection[PersonState[p].location,PersonState[p].destination]=d}TypeInvariant==\* Statements about the variables which we expect to hold in every system state/\PersonState\in[Person->[location:Floor\cupElevator,destination:Floor,waiting:BOOLEAN]]/\ActiveElevatorCalls\subseteqElevatorCall/\ElevatorState\in[Elevator->[floor:Floor,direction:ElevatorDirectionState,doorsOpen:BOOLEAN,buttonsPressed:SUBSETFloor]]SafetyInvariant==\* Some more comprehensive checks beyond the type invariant/\\Ae\inElevator:\* An elevator has a floor button pressed only if a person in that elevator is going to that floor/\\Af\inElevatorState[e].buttonsPressed:/\\Ep\inPerson:/\PersonState[p].location=e/\PersonState[p].destination=f/\\Ap\inPerson:\* A person is in an elevator only if the elevator is moving toward their destination floor/\\Ae\inElevator:/\(PersonState[p].location=e/\ElevatorState[e].floor/=PersonState[p].destination)=>/\ElevatorState[e].direction=GetDirection[ElevatorState[e].floor,PersonState[p].destination]/\\Ac\inActiveElevatorCalls:PeopleWaiting[c.floor,c.direction]/={}\* No ghost callsTemporalInvariant==\* Expectations about elevator system capabilities/\\Ac\inElevatorCall:\* Every call is eventually serviced by an elevator/\c\inActiveElevatorCalls~>\Ee\inElevator:CanServiceCall[e,c]/\\Ap\inPerson:\* If a person waits for their elevator, they'll eventually arrive at their floor/\PersonState[p].waiting~>PersonState[p].location=PersonState[p].destinationPickNewDestination(p)==\* Person decides they need to go to a different floorLETpState==PersonState[p]IN/\~pState.waiting/\pState.location\inFloor/\\Ef\inFloor:/\f/=pState.location/\PersonState'=[PersonStateEXCEPT![p] = [@EXCEPT!.destination = f]]/\UNCHANGED<<ActiveElevatorCalls,ElevatorState>>CallElevator(p)==\* Person calls the elevator to go in a certain direction from their floorLETpState==PersonState[p]INLETcall==[floor|->pState.location,direction|->GetDirection[pState.location,pState.destination]]IN/\~pState.waiting/\pState.location/=pState.destination/\ActiveElevatorCalls'=IF\Ee\inElevator:/\CanServiceCall[e,call]/\ElevatorState[e].doorsOpenTHENActiveElevatorCallsELSEActiveElevatorCalls\cup{call}/\PersonState'=[PersonStateEXCEPT![p] = [@EXCEPT!.waiting = TRUE]]/\UNCHANGED<<ElevatorState>>OpenElevatorDoors(e)==\* Open the elevator doors if there is a call on this floor or the button for this floor was pressed.LETeState==ElevatorState[e]IN/\~eState.doorsOpen/\\/\Ecall\inActiveElevatorCalls:CanServiceCall[e,call]\/eState.floor\ineState.buttonsPressed/\ElevatorState'=[ElevatorStateEXCEPT![e] = [@EXCEPT!.doorsOpen = TRUE,!.buttonsPressed = @\{eState.floor}]]/\ActiveElevatorCalls'=ActiveElevatorCalls\{[floor|->eState.floor,direction|->eState.direction]}/\UNCHANGED<<PersonState>>EnterElevator(e)==\* All people on this floor who are waiting for the elevator and travelling the same direction enter the elevator.LETeState==ElevatorState[e]INLETgettingOn==PeopleWaiting[eState.floor,eState.direction]INLETdestinations=={PersonState[p].destination:p\ingettingOn}IN/\eState.doorsOpen/\eState.direction/="Stationary"/\gettingOn/={}/\PersonState'=[p\inPerson|->IFp\ingettingOnTHEN[PersonState[p]EXCEPT!.location = e]ELSEPersonState[p]]/\ElevatorState'=[ElevatorStateEXCEPT![e] = [@EXCEPT!.buttonsPressed = @\cupdestinations]]/\UNCHANGED<<ActiveElevatorCalls>>ExitElevator(e)==\* All people whose destination is this floor exit the elevator.LETeState==ElevatorState[e]INLETgettingOff=={p\inPerson:PersonState[p].location=e/\PersonState[p].destination=eState.floor}IN/\eState.doorsOpen/\gettingOff/={}/\PersonState'=[p\inPerson|->IFp\ingettingOffTHEN[PersonState[p]EXCEPT!.location = eState.floor,!.waiting = FALSE]ELSEPersonState[p]]/\UNCHANGED<<ActiveElevatorCalls,ElevatorState>>CloseElevatorDoors(e)==\* Close the elevator doors once all people have entered and exited the elevator on this floor.LETeState==ElevatorState[e]IN/\~ENABLEDEnterElevator(e)/\~ENABLEDExitElevator(e)/\eState.doorsOpen/\ElevatorState'=[ElevatorStateEXCEPT![e] = [@EXCEPT!.doorsOpen = FALSE]]/\UNCHANGED<<PersonState,ActiveElevatorCalls>>MoveElevator(e)==\* Move the elevator to the next floor unless we have to open the doors here.LETeState==ElevatorState[e]INLETnextFloor==IFeState.direction="Up"THENeState.floor+1ELSEeState.floor-1IN/\eState.direction/="Stationary"/\~eState.doorsOpen/\eState.floor\notineState.buttonsPressed/\\Acall\inActiveElevatorCalls:\* Can move only if other elevator servicing call/\CanServiceCall[e,call]=>/\\Ee2\inElevator:/\e/=e2/\CanServiceCall[e2,call]/\nextFloor\inFloor/\ElevatorState'=[ElevatorStateEXCEPT![e] = [@EXCEPT!.floor = nextFloor]]/\UNCHANGED<<PersonState,ActiveElevatorCalls>>StopElevator(e)==\* Stops the elevator if it's moved as far as it can in one directionLETeState==ElevatorState[e]INLETnextFloor==IFeState.direction="Up"THENeState.floor+1ELSEeState.floor-1IN/\~ENABLEDOpenElevatorDoors(e)/\~eState.doorsOpen/\nextFloor\notinFloor/\ElevatorState'=[ElevatorStateEXCEPT![e] = [@EXCEPT!.direction = "Stationary"]]/\UNCHANGED<<PersonState,ActiveElevatorCalls>>(***************************************************************************)(* This action chooses an elevator to service the call. The simple *)(* algorithm picks the closest elevator which is either stationary or *)(* already moving toward the call floor in the same direction as the call. *)(* The system keeps no record of assigning an elevator to service a call. *)(* It is possible no elevator is able to service a call, but we are *)(* guaranteed an elevator will eventually become available. *)(***************************************************************************)DispatchElevator(c)==LETstationary=={e\inElevator:ElevatorState[e].direction="Stationary"}INLETapproaching=={e\inElevator:/\ElevatorState[e].direction=c.direction/\\/ElevatorState[e].floor=c.floor\/GetDirection[ElevatorState[e].floor,c.floor]=c.direction}IN/\c\inActiveElevatorCalls/\stationary\cupapproaching/={}/\ElevatorState'=LETclosest==CHOOSEe\instationary\cupapproaching:/\\Ae2\instationary\cupapproaching:/\GetDistance[ElevatorState[e].floor,c.floor]<=GetDistance[ElevatorState[e2].floor,c.floor]INIFclosest\instationaryTHEN[ElevatorStateEXCEPT![closest] = [@EXCEPT!.floor = c.floor,!.direction = c.direction]]ELSEElevatorState/\UNCHANGED<<PersonState,ActiveElevatorCalls>>Init==\* Initializes people and elevators to arbitrary floors/\PersonState\in[Person->[location:Floor,destination:Floor,waiting:{FALSE}]]/\ActiveElevatorCalls={}/\ElevatorState\in[Elevator->[floor:Floor,direction:{"Stationary"},doorsOpen:{FALSE},buttonsPressed:{{}}]]Next==\* The next-state relation\/\Ep\inPerson:PickNewDestination(p)\/\Ep\inPerson:CallElevator(p)\/\Ee\inElevator:OpenElevatorDoors(e)\/\Ee\inElevator:EnterElevator(e)\/\Ee\inElevator:ExitElevator(e)\/\Ee\inElevator:CloseElevatorDoors(e)\/\Ee\inElevator:MoveElevator(e)\/\Ee\inElevator:StopElevator(e)\/\Ec\inElevatorCall:DispatchElevator(c)TemporalAssumptions==\* Assumptions about how elevators and people will behave/\\Ap\inPerson:WF_Vars(CallElevator(p))/\\Ae\inElevator:WF_Vars(OpenElevatorDoors(e))/\\Ae\inElevator:WF_Vars(EnterElevator(e))/\\Ae\inElevator:WF_Vars(ExitElevator(e))/\\Ae\inElevator:SF_Vars(CloseElevatorDoors(e))/\\Ae\inElevator:SF_Vars(MoveElevator(e))/\\Ae\inElevator:WF_Vars(StopElevator(e))/\\Ac\inElevatorCall:SF_Vars(DispatchElevator(c))Spec==\* Initialize state with Init and transition with Next, subject to TemporalAssumptions/\Init/\[][Next]_Vars/\TemporalAssumptionsTHEOREMSpec=>[](TypeInvariant/\SafetyInvariant/\TemporalInvariant)
=============================================================================
The text was updated successfully, but these errors were encountered:
Found on Wikipedia as an example:
The text was updated successfully, but these errors were encountered: