350 likes | 579 Views
Abstract Model Examples in Alloy. Nikunj Mehta Chris Patel Vinay Viswanathan . Alloy Model i ng Notat i on. Semantic object models Set-based representation of objects Based on Z Simple and intuitive semantics Introduces mutability properties Graphical and Textual descriptions
E N D
Abstract Model Examples in Alloy Nikunj Mehta Chris Patel Vinay Viswanathan
Alloy Modeling Notation • Semantic object models • Set-based representation of objects • Based on Z • Simple and intuitive semantics • Introduces mutability properties • Graphical and Textual descriptions • Plain ASCII textual notation • Visualizations generated by tool during simulation • Semantic analysis through tool support • Validates expression consistency • Simulation and Checking • Proof by contradiction • Sound modeling and no false alarms
Alloy Constraint Analyzer IDE environment Editor, debugger and simulation windows Visualization control TextPad Syntax Highlighting Tool Support
Alloy Modeling Structures • Domain • represents indivisible atoms • State • declares state components based on domain • Invariants • describe properties of the state • Definitions • help create shortcuts – usually for convenience • Assertions • redundant constraints that follow from previous paragraphs • Condition • used to simulate, to verify that model is not over-constrained
Cruise Control Model model CruiseControl{domain {Vehicle, fixed Speed, fixed CruiseState} state { // Alloy does not support relational operators, so use a range allowableSpeeds : fixed Speed // Cruise control can be off, disabled, active or suspended partition off, active, suspended, disabled : fixed CruiseState! //A vehicle has an exact speed curSpeed : Vehicle -> Speed! //The cruise speed is set sometimes cruiseSpeed : Vehicle -> Speed? //A vehicle has some notion of cruise state cruise : Vehicle -> CruiseState! // Defining a new cruise state as a combination of different cruise states on: fixed CruiseState }
// A vehicle that is in the on state can be either on or offdef on { all s | s in on <-> s != off } inv CruisingVehicle { // A cruising vehicle cannot be in cruise state if it's speed is outside acceptable limits. all v | (v.cruise = suspended || v.cruise = active) -> v.curSpeed /in allowableSpeeds // When a vehicle is actively cruise controlled, the vehicle's speed is maintained at the set speed. all v | (v.cruise = active || v.cruise = suspended) -> one v.cruiseSpeed // Even when the vehicle goes uphill or downhill, the vehicle will maintain this speed all v | (v.cruise = active) -> (v.curSpeed = v.cruiseSpeed) // A vehicle whose cruise control is not being used cannot have a cruise speed. all v | v.cruise = off -> no v.cruiseSpeed // A car cannot cruise at disallowed speeds all v | v.cruise in on -> v.cruiseSpeed in allowableSpeed }
Model Visualization State paragraph Cruising Vehicle AlwaysCruiseAfterAccelerate
op startCruise(v : Vehicle!) // Start cruising the vehicle { // The precondition is that the vehicle was not in cruise state already and is within acceptable // speed limits v.cruise = off v.curSpeed in allowableSpeeds // The result is that vehicle's cruise state is on now, but the control is disabled v.cruise' = disabled no v.cruiseSpeed‘ } op endCruise(v : Vehicle!) // Stop cruising the vehicle { // The precondition is that the vehicle was cruising already v.cruise in on // The result is that vehicle's cruise state is off now v.cruise' = off no v.cruiseSpeed }
op setSpeed(v : Vehicle!) { // The precondition is that the vehicle's cruise was turned on already, // but the control is disabled or was suspended v.cruise = disabled || v.cruise = suspended // The result is that the vehicle's cruise speed is set as the // vehicle's current speed v.cruiseSpeed' = v.curSpeed }
op pressAcceleratePedal(v : Vehicle!, newSpeed : Speed!){// The vehicle cannot already be running at the new speed v.curSpeed != newSpeed// If the vehicle was cruising already the result is that vehicle's //cruise state is on now, but the control is disabled or suspended //based on the new speed v.cruise = active && newSpeed in allowableSpeeds -> v.cruise' = suspended && v.cruiseSpeed' = v.cruiseSpeed v.cruise = active && newSpeed !in allowableSpeeds -> v.cruise' = disabled && v.cruiseSpeed' = v.cruiseSpeed // And the vehicle's speed changes from the cruising speed to the // new speed v.curSpeed' = newSpeed}
// Release accelerator pedal on a suspended vehicleop releaseAcceleratePedal(v : Vehicle!){// If the vehicle was cruising already, the vehicle's speed changes // from the current speed to the cruise speed// The result is that vehicle's cruise state is active now v.cruise = suspended -> (v.curSpeed' = v.cruiseSpeed && v.cruise' = active && v.cruiseSpeed' = v.cruiseSpeed )} // Apply brakes to decel. vehicle will disable its cruise controlop brake(v : Vehicle!, newSpeed : Speed!){// The vehicle cannot already be running at the new speed v.curSpeed != newSpeed v.curSpeed' = newSpeed// If the vehicle was cruising already// The result is that vehicle's cruise state is on now, but the // control is disabled v.cruise = active && newSpeed in allowableSpeeds -> v.cruise' = disabled v.cruise = active && newSpeed !in allowableSpeeds -> v.cruise' = off}
op resumeCruise(v : Vehicle!){ // The precondition is that the vehicle's cruise was turned on already, but the control is disabled v.cruise = disabled // We also need the vehicle to have a set cruise speed. // However, it is not clear if the speed was set in the setSpeed operation v.cruiseSpeed /in allowableSpeeds // And the vehicle's speed changes from the current speed to the cruise speed v.curSpeed' = v.cruiseSpeed // The result is that the vehicle starts cruising v.cruise' = active}
assert CruisingCar{ all car : Vehicle | setSpeed(car) && resumeCruise(car) -> car.cruiseSpeed' = car.curSpeed && car.curSpeed' = car.curSpeed && car.cruise' = active}assert BrakingCar{ all car : Vehicle | all s : Speed | setSpeed(car) && resumeCruise(car) && brake(car, s) -> car.curSpeed' != car.curSpeed && car.cruiseSpeed' /= car.curSpeed && car.cruise' = disabled}assert A{ all car : Vehicle | some s: Speed | brake(car, s) -> car.curSpeed' = s && car.cruise != active}
assert CruiseAgainAfterAccelerate { all car : Vehicle | all s : allowableSpeeds | car.cruise = active && pressAcceleratePedal(car, s) && releaseAcceleratePedal(car) -> car.cruise' = active && car.curSpeed' = car.curSpeed} assert AlwaysCruiseAfterAccelerate{ all car : Vehicle | all s : Speed | car.cruise = active && s !in allowableSpeeds && pressAcceleratePedal(car, s) && releaseAcceleratePedal(car) -> car.cruise' = active}
cond FastCars{ some car: Vehicle | car.cruise = disabled && car.curSpeed !in allowableSpeeds && car.cruiseSpeed /in allowableSpeeds} assert FullLifeCycle{ all car : Vehicle | endCruise(car) -> setSpeed(car)} }
Gas Station Model // The gas station allows for vehicles to pump gas after selecting a pump and grade and paying the moneymodel GasStation{domain { fixed Number, Vehicle, fixed StnGasTankState, fixed VehicleGasTankState, fixed VehicleState, fixed Tank, fixed Pump, fixed PumpState, fixed AttendantState, GasAmount, Person }
state{ partition Premium, Plus, Regular : fixed Tank! partition n1, n2, n3, n4 : fixed Number! partition Idle, Dispensing, Activated : fixed PumpState! partition Enough, NotEnough, Refilling : fixed StnGasTankState! partition NotFull, Full : fixed VehicleGasTankState! partition Waiting, Filling : fixed VehicleState! disjoint Customer, Employee : Person Attendant : fixed Employee! partition Dormant, Servicing : fixed AttendantState! grade : Pump -> Tank? nozzle : Pump -> PumpState! num : Pump -> static Number! gasToFill : Pump -> GasAmount? // everything between 0 and max sGas : Tank -> StnGasTankState! tankAmount : Tank -> GasAmount? atStation : Vehicle -> VehicleState! pumpNum : Vehicle -> Number? vGas : Vehicle -> VehicleGasTankState? atPump : Vehicle? -> Pump? driver : static Vehicle! -> static Customer! pump : Customer? -> Pump? work : Attendant -> AttendantState!}
// A vehicle is at a pump decided on the basis of the pump numberdef atPump{ all v : Vehicle | all p : Pump | v.atPump = p -> v.pumpNum /= p.num} // The pump at which a customer is located, is the same as the pump at which the //vehicle standsdef pump{ all c : Customer | all p : Pump | c.pump = c.~driver.atPump}
inv PumpingVehicle{ // If a pump is not at a station, the gas station does not need to know about the //vehicle all v : Vehicle | some v.atStation <-> some v.atPump && some v.vGas // If a vehicle is waiting at a gas station, it's gas tank is not full all v : Vehicle | v.atStation = Waiting -> v.vGas = NotFull // If a vehicle is filling at a gas station, the pump from which it is filling has to be //dispensing all v : Vehicle | all p : Pump | v.atPump = p && v.atStation = Filling <-> p.nozzle = Dispensing // If gas is unavailable, vehicles do not go to the gas station all v : Vehicle | all p : Pump | no p.nozzle -> no v.atStation}
assert DontCareVeh{ all v : Vehicle | v.atStation = Waiting -> some v.atPump}inv Threshold{// If there is not enough gas in any one or more tank, no pump can be //activated all t : Tank | all p : Pump | t.sGas = NotEnough -> no p.nozzle}inv UniqueNumbers{// A vehicle can be at most at one pump at any time all n : Number | sole v : Vehicle | v.pumpNum = n// Pump numbers are unique all n : Number | one p : Pump | p.num = n}
inv PumpSetting{// If a vehicle is filling at a gas station, the pump from which it is filling has to be //dispensing all v : Vehicle | all p : Pump | v.atPump = p && v.atStation = Filling <-> p.nozzle = Dispensing// However, the vehicle's tank cannot be full while the nozzle is dispensing gas all v : Vehicle | all p : Pump | v.atPump = p && p.nozzle = Dispensing -> v.vGas /= NotFull // If there is no vehicle at the pump, the nozzle stays idle all v : Vehicle | all p : Pump | no p.~atPump -> p.nozzle = Idle// If the nozzle is idle, there cannot be a grade selection or remaining gas to fill at a pump. all p : Pump | p.nozzle = Idle -> no p.grade && no p.gasToFill}// Check to see there is enough gas in the tanks and issue refilling request otherwiseop checkTank{ // Ideally we would have compared the t.tankAmount w the threshold but for now all t : Tank | t.sGas = NotEnough -> t.sGas' = Refilling// also issue a request to refill that tank.}
// Complete the operation to refilling the gas tanks in the stationop finishRefill{ all t : Tank | t.sGas = Refilling -> t.sGas' = Enough}// Record the payment of money by a customerop payForGas(g : GasAmount!, c : Customer!){ all t : Tank | t.sGas != NotEnough c.pump.nozzle = Idle all a : Attendant | a.work = Dormant c.pump.nozzle' = Activated && c.pump.gasToFill' = g all a : Attendant | a.work' = Servicing// Somewhere we need to reset the t.sGas based on the gas amount to be filled}// The customer that paid for gas is leaving the cashier, so that the cashier can service //another customerop leaveCashier(c : Customer!){ all a : Attendant | c.pump.nozzle = Activated -> a.work' = Dormant && c.~driver.vGas = NotFull}
// Select grade of gas to fill in the tankop selectGrade(c : Customer!, g : Tank!){ c.pump.nozzle = Activated -> c.pump.grade' = g}// Press the nozzle to dispense gasop pressNozzle(c : Customer!){ c.~driver.vGas = NotFull c.pump.nozzle = Activated some c.pump.grade some c.pump.gasToFill c.pump.nozzle' = Dispensing && c.~driver.atStation' = Filling}// Fill gas into the vehicle based on the previous paymentop fillGas(c : Customer!, remainingGas : GasAmount!, tankRemaining : GasAmount!){ some c.pump.gasToFill -> (c.pump.gasToFill' = remainingGas && c.pump.grade.tankAmount' = tankRemaining) no c.pump.gasToFill -> c.pump.nozzle' = Idle}
// The nozzle sensor found that a vehicle's gas tank is fullop tankFull(v : Vehicle!){ v.atPump.nozzle = Dispensing && some v.atPump.gasToFill && v.vGas = Full -> v.atPump.nozzle' = Idle && no v.atStation'}// Release the nozzle while pumping gas either before or after the tank is fullop releaseNozzle(c : Customer!){ c.pump.nozzle = Dispensing some c.pump.gasToFill -> c.pump.nozzle' = Activated no c.pump.gasToFill -> c.pump.nozzle' = Idle && no c.~driver.atStation'}
// Retrieve change from the cashier for the remaning gasop RetrieveChange(c : Customer!){ (c.pump.nozzle = Idle || c.pump.nozzle = Activated) some c.pump.gasToFill no c.pump.gasToFill' && c.pump.nozzle' = Idle}// Leave the gas stationop leaveStation(v : Vehicle!){ no v.atStation'}assert TwoSimultaneousCustomers{ all c1, c2 : Customer | all g1, g2 : GasAmount | payForGas(g1, c1) && leaveCashier(c1) -> payForGas(g2, c2)} }
Modeling Experience • Tool support gives the ability to experiment with a model, generate samples, check properties • Visualization allows errors to be caught easily • Good syntax : Notation is easy to read and write • Tedious to work around around the lack of integers and relational operators • A single large model makes maintenance difficult • Large scopes take a long time to analyze
Alloy Limitations • Declarative specifications • Over and under constrained models • Lack of reuse among model elements • All paragraphs are defined in a single model • Kernel is undecidable • Impossible to automatically validate a formula • Lacks scalars and relational operators • Frame conditions and no change semantics • Missing integers and relational operators • Sequence components and sequencing of operations missing
Conclusions • General modeling uses • Simple notation and quick turn-around time for modeling • IDE environment for ease of modeling • Relevance to formalizing architectures • Model based specification • describe static and dynamic aspects of a system formally • Model simulation for checking architecture description • Dynamism modeling using mutability properties • Well suited to database-oriented systems (just like Z)