elevator

40
Modeling & verification of a simple elevator system using Alloy

Upload: mahedi-hasan

Post on 22-Oct-2014

73 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Elevator

Modeling & verification of a simple elevator system using Alloy

Page 2: Elevator

• To describe formally the components of a system and relationships between them

• Check properties about the model• Exclude ill-formed examples of Models.• Two kind of problems might arise

– bugs in the model itself. We will discuss the problems of overconstraining and underconstraining your model, and how to find and eliminate such bugs.

– errors in the subject you are modeling. These are what you are after, and what modeling is all about. We will show you how to make and check assertions about your system, and how to track down why a given assertion failed to hold.

Page 3: Elevator

Why Alloy• Conceptual simplicity and minimalism

– easy to learn– WYSIWYG: no special semantics

• high-level notation– Constraints -- can build up incrementally– Relations flexible and powerful– Much more briefly and clearly expressed than most model checking

notations

Page 4: Elevator

Properties of Alloy• finite scope check - once you go to actually analyze the model, you must specify a

scope (size) for your model. The analysis is sound (it never returns false positives) but incomplete (since it only checks things up to a certain scope). However, it is complete up to scope; it never misses a counterexample which is smaller than the specified scope. Small scope checks are still extremely valuable for finding errors.

• infinite model - The models you write in Alloy do not reflect the fact that the analysis is finite. That is, you describe the compontents of a system and how they interact, but do not specify how many components there can be (as is done in traditional "model checking").

• declarative - a declarative modeler answers the question "how would I recognize that X has happened", as opposed to an "operational" or "imperative" modeler who asks "how can I accomplish X".

• automatic analysis - unlike some other declarative specification languages, Alloy can be automatically analyzed. You can automatically generate examples of your system and counterexamples to claims made about that system.

Page 5: Elevator

Alloy model structures• Structures are expressed as a set of tuples

– individual elements are treated as singleton sets

• The Alloy universe consists of atoms and relations, although everything that you can get your hands on and describe in the language is a relation. Atoms only exist behind the scenes.

• An atom is a primary entity which is – indivisible: it cannot be broken down into smaller parts, – immutable: it's properties don't change over time, and

• A relation is a structure which relates atoms. Each relation is a set of ordered tuples (vectors of atoms). Each tuple indicates that those atoms are related in a certain way (as dictated by the relation itself). The "arity" of the relation is the number of atoms in each tuple.

Page 6: Elevator

Alloy declarations• First line module declaration

– module chapter4/filesystem• sig Object {}

– Defines a set named Object represents all objects– abstract sig Object{} abstract sig has no elements

except those belonging to its extensions. • sig File extends Object {}

– A set can be introduced as a subset of another set

Page 7: Elevator

• sig A {}• sig B extends A {}• sig C extends A {}

• Means– B in A– C in A– no B & C

Page 8: Elevator

Signatures

• abstract sig A {}• sig B extends A {}• sig C extends A {}• B in A• C in A• no B & C • A = (B + C)

Page 9: Elevator

Declaring relations

• Relations are declared as fields of signatures• sig Object{}

sig Dir extends Object {entries: set Object,parent: lone Dir

}

Page 10: Elevator

Set Multiplicities

• set : any number.• one: exactly one.• lone: zero or one.• some: one or more.

– sig Man extends Person { Wife: lone Woman}– sig Woman extends Person {Husband: lone Man}– sig Object{}

sig Dir extends Object {entries: set Object,parent: lone Dir}

Page 11: Elevator

Facts and Assertions• fact:

– Constraints that are assumed always to hold (used to restrict space of possible counterexamples)

– A Model can have any number of factssig A {}fact { all z: A | F }

• assert:– Constraints that are intended to follow from the

facts of the model– Can be checked using the check command

Page 12: Elevator

assert, check

• fact F {…}• assert A {…}• check A• means

– fact: assume constraint F holds– assert: believe that A follows from F– check: find an instance that satisfies F and not A

Page 13: Elevator

Quantifiers• all x: e | F• some x: e | F• no x: e | F• lone x: e | F• one x: e | F

– fact EntriesSameName {all e1, e2 : entries | e1.name = e2.name => e1 = e2}

– fact nametoaddress { all n:Name| lone d: Address| d in n.address}– fact {no p: Person | p in p.^(mother + father) }– fact FourPassengersPerCar { all c:Car | #{c.contents } <= 4 }– fact OneVehiclePerPassenger { all p:Passenger | one v:Vehicle | p in

v.contents }

Page 14: Elevator

Constants and Operators

• The language of relations has its own constants and operators

• Constants– none = empty set– univ = universal set– iden = identity

Page 15: Elevator

Constants and Operators• Name = {(N0), (N1)}

Addr = {(D0), (D1)}• none={}

univ = {(N0), (N1), (D0), (D1)} iden = {(N0,N0), (N1,N1), (D0,D0), (D1,D1)}

• Operators fall into Two Categories– Set– Relational

Page 16: Elevator

Set Operators

• + : union– sig Vehicle {} {Vehicle = Car + Truck}

• & : intersection– fact DisjSubtrees { all t1, t2:Tree | (t1.^children) & (t2.^children) = none }

• - : difference– fact dirinothers { all d: Directory - Root | some contents.d }

• in : subset– Sibling = (brother + sister)– sister in sibling

• = : equality

Page 17: Elevator

Relational operators• . : dot (Join)

– {(N0), (A0)} . {(A0), (D0)} = {(N0), (D0)}

• -> : arrow (product)– s -> t is their cartesian product– r: s -> t says r maps atoms in s to atoms in t

• ^ : transitive closure– fact DisjSubtrees { all t1, t2:Tree | (t1.^children) & (t2.^children) = none }– fact {no p: Person | p in p.^(mother + father) }

• * : reflexive-transitive closure– fact {Object in Root.*contents}

• ~ : transpose– Takes its mirror image s.~r = r.s (image of s navigating backwards through rel r)

Page 18: Elevator

Relational Operators• ~ : transpose (continued)

– fact dirinothers{ all d: Directory - Root | some d.~contents }– fact dirinothers { all d: Directory - Root | some contents.d }

• [] : box (join)– Semantically identical to join, takes arguments in different order. Expressions:

e1[e2] = e2.e1

• <: :domain restriction– Contains those tuples of r that start with an element in s.

• :> : range restriction– Contains the tuples of r that end with an element in s

• ++: Override– Override p ++ q (just like union), except that tuples of q can replace tuples of p

rather than augmenting them.

Page 19: Elevator

Relational Operators• Alias = {(N0), (N1)}• Addr = {(A0)}• address = {(N0, N1), (N1, N2), (N2, A0)}

• Domain restriction• Alias <: address = {(N0, N1), (N1, N2)}

• Range restriction:• address :> Addr = {(N2, A0)}

• workAddress = {(N0, N1), (N1, A0)}• address ++ workAddress = {(N0, N1), (N1, A0), (N2, A0)}

Page 20: Elevator

Logical operators

• ! : negation• && : conjunction (and)• || : disjunction (OR)• => : implication• else : alternative• <=> : bi-implication (IFF)

Page 21: Elevator

Logic Cardinalities

• = equals• < less than• > greater than• =< less than or equal to• >= greater than or equal

to

• #r number of tuples in r• 0,1,... integer literal• + plus• - minus

•all b: Bag | #b.marbles =< 3 all bags have 3 or less marbles• fact FourPassengersPerCar { all c:Car | #{c.contents} <= 4 }

Page 22: Elevator

Functions and Predicates

• A function is a named expression• Zero or more declarations for arguments• fun grandpas [p: Person]: set Person {

p.(mother + father).father}

• fun colorSequence: Color -> Color { Color <: iden + Red->Green + Green->Yellow + Yellow->Red}

Page 23: Elevator

Predicates and functions

• A predicate is a named constraint• Zero or more declarations for arguments• Can be used to represent an operation• Only holds when invoked (unlike fact)

– sig Name, Addr {}sig Book { addr: Name -> Addr }pred add (b, b': Book, n: Name, a: Addr) {

b'.addr = b.addr + n->a}

– pred Above(m, n: Man) {m.floor = n.ceiling}Man m is “above” Man n if m's floor is n's ceiling

Page 24: Elevator

pred, run

• fact F {…}• pred P () {…}• run P• means

– fact: assume constraint F holds– pred: define constraint P– run: find an instance that satisfies P and F

Page 25: Elevator

elevator policy

challenge› specify a policy for scheduling a lift› all requests eventually served› don’t skip request from inside lift› no fixed configuration of floors, lifts, buttons

Page 26: Elevator

A State is described by• Giving number of floors• Listing details of each floor states• The lift itself

Page 27: Elevator

A floor has• One door (open or shut)• Up call button • Down call button

– On/off• Down button on the ground floor is always off• Up button on the top floor is always off

Page 28: Elevator

• The lift itself has– Current floor– Destination button for each floor

Page 29: Elevator

enum Button { On, Off }enum Door { Open, Shut }

sig Floor { door: one Door, up: one Button, down: one Button

}

one sig Lift { current: Int, buttons: seq Button

}

Page 30: Elevator

enum keyword to declare singleton subsigs.For example, enum X { A, B, C }means abstract sig X { } one sig A, B, C extends X { }

Page 31: Elevator

"seq" is new it is used for declaring a field as a sequence of atoms.

In the following example, for each person p, "p.books" is a sequence of Book: sig Book { } sig Person { books: seq Book }

The actual type of a sequence of Book is "Int->Book".So if s is a sequence of Book, then the first element is s[0] and you can get the set of all elements by writing "univ.s" You can also use "seq" in quantifications, like this: some s: seq Book | FORMULAYou can also use "seq" in function argument declaration, like this: fun getAllElements [s: seq Book] : set Book { univ.s }

Page 32: Elevator

sig State { numFloors: Int, floors: seq Floor, lift: Lift } {#floors = numFloorsfloors[0].down = Offfloors[numFloors-1].up = Off0 <= lift.current && lift.current < numFloorsall i: floors.univ - lift.current | floors[i].door = Shut

}

Initially, the buttons are all off, and the lift is on the ground floor (floor 0) with its door shut

Page 33: Elevator

enum Button { On, Off }

enum Door { Open, Shut }

sig Floor { door: one Door, up: one Button, down: one Button }

one sig Lift { current: Int, buttons: seq Button }

sig State { numFloors: Int, floors: seq Floor, lift: Lift } {#floors = numFloorsfloors[0].down = Offfloors[numFloors-1].up = Off0 <= lift.current && lift.current < numFloorsall i: floors.univ - lift.current | floors[i].door = Shut

}

Page 34: Elevator

pred InitialButton[b: Button] {b = Off

}

pred InitialDoor[d: Door] {d = Shut

}

pred InitialFloor[f: Floor] {InitialDoor[f.door]InitialButton[f.up]InitialButton[f.down]

}

pred InitialLift[l: Lift] {l.current = 0all i: l.buttons.univ |InitialButton[l.buttons[i]]

}

pred InitialState[s: State] {InitialLift[s.lift]all i: s.floors.univ |InitialFloor[s.floors[i]]

}

Initial state

Page 35: Elevator

Test initial states

InitialButtonExists:run {some b: Button | InitialButton[b]}

InitialDoorExists:run {some d: Door | InitialDoor[d]}

InitialFloorExists:run {some f: Floor | InitialFloor[f]}

InitialLiftExists:run {some l: Lift | InitialLift[l]}

InitialStateExists:run {some s: State | s.numFloors = 3 && InitialState[s]}

Page 36: Elevator

PressUp & PressDownpred PressUp[f, f': Floor] {

f'.door = f.door && f'.up = On && f'.down = f.down}pred PressUp[i: Int,s, s': State] {

i in s.floors.univall j: s.floors.univ-i | s'.floors[j] = s.floors[j]PressUp[s'.floors[i], s.floors[i]]

}

TestPressUp:run { some s, s': State | PressUp[0,s,s']}

pred PressDown[f, f': Floor] {f'.door = f.door && f'.up = f.up && f'.down = On

}pred PressDown[i: Int,s, s': State] {

i in s.floors.univall j: s.floors.univ-i | s'.floors[j] = s.floors[j]PressDown[s'.floors[i], s.floors[i]]

}

TestPressDown:run { some s, s': State | PressDown[1,s,s']}

Page 37: Elevator

PressDestButtonpred PressDestButton[i: Int, l, l': Lift] {

i in l.buttons.univl'.current = l.currentall j: l.buttons.univ-i | l'.buttons[j] = l.buttons[j]i != l.current => l'.buttons[i] = On else l'.buttons[i] = l.buttons[i]

}pred PressDestButton[i: Int,s, s': State] {

i in s.floors.univ(all j: s.floors.univ-i |s'.floors[j].up = s.floors[j].up && s'.floors[j].down = s.floors[j].down)PressDestButton[i, s.lift, s'.lift]

}

TestPressDestButton:run { some i: Int, s, s': State | PressDestButton[i,s,s'] }

Page 38: Elevator

openDoor & closeDoorpred OpenDoor[f, f': Floor] {

f'.door = Open && f'.up = f.up && f'.down = f.down}pred OpenDoor[i: Int, s, s': State] {

i in s.floors.univ(all j: s.floors.univ |s'.floors[j].up = s.floors[j].up && s'.floors[j].down = s.floors[j].down)OpenDoor[s.floors[i], s'.floors[i]]

}TestOpenDoor:run { some i: Int, s, s': State | OpenDoor[i,s,s'] }

pred CloseDoor[f, f': Floor] {f'.door = Shut && f'.up = f.up && f'.down = f.down

}pred CloseDoor[i: Int, s, s': State] {

i in s.floors.univ(all j: s.floors.univ |s'.floors[j].up = s.floors[j].up && s'.floors[j].down = s.floors[j].down)CloseDoor[s.floors[i], s'.floors[i]]

}TestCloseDoor:run { some i: Int, s, s': State | CloseDoor[i,s,s'] }

Page 39: Elevator

Move uppred moveLiftUp[s, s': State] {

s.floors[s.lift.current].door = Shut(some i: s.floors.univ | i > s.lift.current &&(s.lift.buttons[i] = On || s.floors[i].up = On || s.floors[i].down = On))s'.floors = s.floorss'.lift.current = s'.lift.current+1

}

TestMoveLiftUp:run { some s, s': State | moveLiftUp[s, s'] }

Page 40: Elevator

Move Lift Downpred moveLiftDown[s, s': State] {

s.floors[s.lift.current].door = Shut(some i: s.floors.univ | i < s.lift.current &&(s.lift.buttons[i] = On || s.floors[i].up = On || s.floors[i].down = On))s'.floors = s.floorss'.lift.current = s'.lift.current-1

}TestMoveLiftDown:run { some s, s': State | moveLiftDown[s, s'] }