-- All metro units with metro line associations must be associated with existing metro lines. invforall u insetrng units &
u.GetLine() <> nil => u.GetLine() insetrng lines;
-- All tracks must accommodate all metro units. If any track exceeds its capacity, it is overloaded and metro units may collide. inv TracksAccommodateAllMetroUnits();
functions -- // Metro lines and tracks // privatestatic AllTracks: setof MetroLine -> setof Track
AllTracks(allLines) == dunion { elems line.tracks | line inset allLines };
publicstaticReverse: seqof Track -> seqof Track Reverse(tracks) == if tracks = [ ] then
[ ] else Reverse(tl tracks) ^ [ hd tracks ] measure Length;
privatestatic Length: seqof Track -> nat
Length(tracks) == len tracks;
-- // Units // privatestatic UnitSetToSequence: setof MetroUnit -> seqof MetroUnit
UnitSetToSequence(unitSet) == if unitSet = { } then
[ ] else let unit inset unitSet in
[ unit ] ^ UnitSetToSequence(unitSet \ { unit }) measureCard;
operations public AddUnit: MetroUnit ==> ()
AddUnit(unit) == units := units munion { unit.GetId() |-> unit } pre unit.GetId() notinsetdom units and
(unit.GetLine() <> nil => unit.GetLine() insetrng lines) and
(unit.GetLocation() <> nil => RemainingCapacityOf(unit.GetLocation()) > 0);
public RemoveUnit: MetroUnit`MetroUnitId ==> ()
RemoveUnit(unitId) == units := { unitId } <-: units;
public AddLine: MetroLine ==> ()
AddLine(line) == lines := lines munion { line.name |-> line } pre line.name notinsetdom lines;
pure public IsAnyUnitStuck: () ==> bool
IsAnyUnitStuck() == returnexists u insetrng units &
u.IsStuck();
public FindStuckUnit: () ==> MetroUnit
FindStuckUnit() == let u insetrng units best u.IsStuck() in return u pre IsAnyUnitStuck();
public Tick: () ==> ()
Tick() == def unitsAllowedToRun: setof MetroUnit = UnitsAllowedToRun() in
( forall u insetrng units \ unitsAllowedToRun do
u.Stop();
forall u inset unitsAllowedToRun do
u.Run();
) postforall track inset AllTracks(rng lines) &
NumberOfEnteringUnitsOn(track) <= RemainingCapacityOf(track);
pure private RemainingCapacityOf: Track ==> int
RemainingCapacityOf(track) == def numberOfUnitsOnTrack: nat = card { unit | unit insetrng units & unit.GetLocation() = track } in return track.capacity - numberOfUnitsOnTrack;
pure private NumberOfEnteringUnitsOn: Track ==> int
NumberOfEnteringUnitsOn(track) == returncard { unit | unit insetrng units & unit.GetNextLocation() = track and unit.GetState() = <Running> };
-- // Interlocking mechanism // private UnitsAllowedToRun: () ==> setof MetroUnit
UnitsAllowedToRun() ==
( dcl capacities: CapacityMap := RemainingCapacities(),
unitsAllowedToRun: setof MetroUnit := { }; def prioritisedUnits: seqof MetroUnit = PrioritiseUnits(rng units, trackPriorities) in
( for unit in prioritisedUnits do
( if MayRun(capacities, unit) then
(
capacities := Occupied(capacities, unit);
unitsAllowedToRun := unitsAllowedToRun union { unit };
);
);
return unitsAllowedToRun;
);
);
public PrioritiseUnits: setof MetroUnit * seqof TrackKind ==> seqof MetroUnit
PrioritiseUnits(unitsToPrioritise, priorities) == if priorities = [ ] then return [ ] else def nextUnits = UnitsOn(unitsToPrioritise, hd priorities);
pendingUnits = unitsToPrioritise \ nextUnits in return UnitSetToSequence(nextUnits) ^ PrioritiseUnits(pendingUnits, tl priorities) postforall unit insetelemsRESULT &
unit.GetNextLocation() inset AllTracks(rng lines);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.