Answers B Method
Answers B Method
This document contains sample solutions to the exercises in the book The
B-Method: an Introduction by Steve Schneider.
Steve Schneider
[email protected]
June 2001
Exercise 1.2
MACHINE Ticket
VARIABLES serve , next
INVARIANT serve N next N serve next next 501
INITIALISATION serve , next := 0 , 0
OPERATIONS
ss - serve next =
b
PRE serve < next
THEN ss , serve := serve + 1 , serve + 1
END
tt - take ticket =
b
PRE next 500
THEN tt , next := next , next + 1
END
END
Exercise 1.3
nn - query =
b
PRE true
THEN nn := next serve
END
Exercise 1.4
MACHINE Ticket14
VARIABLES serve , next , record
INVARIANT serve N next N record N serve next
INITIALISATION serve , next , record := 0 , 0 , 0
OPERATIONS
ss - serve next =
b
PRE serve < next
THEN ss , serve , record := serve + 1 , serve + 1 , 0
END
tt - take ticket =
b
PRE true
THEN tt , next , record := next , next + 1 , record + 1
END
rr - query record =
b
PRE true
THEN rr := record
END
END
Exercise 1.5
MACHINE Ticket
VARIABLES serve , next , lim
INVARIANT serve N next N lim N serve next next lim
INITIALISATION serve , next , lim := 0 , 0 , 500
OPERATIONS
ss - serve next =
b
PRE serve < next
THEN ss , serve := serve + 1 , serve + 1
END
tt - take ticket =
b
PRE next < lim
THEN tt , next := next , next + 1
END
limit ( nn ) =
b
PRE nn N next nn
THEN lim := nn
END
END
Exercise 1.6
No, this operation is not consistent with the invariant of the Ticket machine,
since it may be called in the state in which serve and next are both 0. It can be
made consistent by strengthening the precondition to serve > 0.
Exercise 1.7
MACHINE CarPark
VARIABLES contents
INVARIANT contents N contents 640
INITIALISATION contents := 0
OPERATIONS
enter =
b
PRE contents < 640
THEN contents := contents + 1
END
leave =
b
PRE contents > 0
THEN contents := contents 1
END
nn - query =
b
PRE true
THEN nn := contents
END
END
PPMEMBER.
Exercise 2.2
{} {home, work} = {}. S T = T S if S = {} or T = {} or S = T .
Exercise 2.3
This is the set of cubes of size less than 100, which is { 0, 1, 8, 27, 64 }
Exercise 2.4
1. always true
2. not always true
3. always true
4. always true
5. not always true
6. always true
7. always true
Exercise 3.1
0, {}
0, {olly}
0, {pat }
0, {olly, pat }
1, {}
1, {olly}
1, {pat }
1, {olly, pat }
2, {olly, pat }
2, {olly}
2, {pat }
2, {}
0, {}
0, {}
0, {olly}
0, {olly}
0, {pat }
0, {pat }
0, {olly, pat }
1, {}
0, {olly, pat }
1, {}
1, {olly}
1, {olly}
1, {pat }
1, {pat }
1, {olly, pat }
1, {olly, pat }
2, {olly, pat }
2, {olly, pat }
2, {olly}
2, {olly}
2, {pat }
2, {pat }
2, {}
2, {}
Exercise 3.2
0, 0
0, 0
0, 1
0, 1
0, 2
0, 2
1, 0
1, 0
1, 1
1, 1
1, 2
1, 2
2, 0
2, 0
2, 1
2, 1
2, 2
2, 2
The states which reach a state in which x+y = 2 are (0, 2), (2, 2), (1, 2), (2, 1), (2, 0).
By calculation, we obtain:
[ IF x < y THEN y := y x ELSE x := x y END ](x + y = 2)
=
(x
=
=
=
max(x, y) = 2
which yields the same states as obtained directly from the relation.
Exercise 3.3
IF E1 THEN S1
ELSIF E 2 THEN S2
ELSIF ...
P
ELSIF En THEN Sn
ELSE Sn+1
END
E1 [S1 ]P
(E1 E2 ) [S2 ]P
=
...
(E1 ... En1 En ) [Sn ]P
(E1 E2 ... En ) [Sn+1 ]P
Exercise 3.4
6 next
2. serve + new 6 next + 1
1. serve + new
6 60) hh papers
[papers := papers {hh} || magazines := magazines {hh}]
(papers 1..163 magazines papers card(papers) 6 60)
6 60) hh papers
6 60)
remove ( hh ) =
b
PRE hh 1 . . 163
card ( magazines { hh } ) card ( papers { hh } ) / 2
10
THEN
END
Exercise 4.4
The operation board is consistent with the invariant of Bus. The other two
operations, buy and double are not consistent.
The machine can be amended by strengthening the invariant so that tickets
passengers is a clause; and by altering the precondition of buy to ensure the
(new) invariant is met, resulting in the following machine:
MACHINE Bus
VARIABLES tickets , passengers
INVARIANT tickets N passengers N tickets passengers
INITIALISATION tickets , passengers := 0 , 0
OPERATIONS
buy ( mm ) =
b
PRE mm N tickets + mm passengers
THEN tickets := tickets + mm
END
board ( nn ) =
b
PRE nn N
THEN passengers := passengers + nn
END
double =
b
PRE true
THEN tickets , passengers := 2 tickets , 2 passengers
END
END
6 tickets + 45
6 tickets + 22
11
Exercise 5.2
>
12
ian
eggs
jim
cheese
ken
salad
lisa
pizza
eats
4. eats
Exercise 6.2
1. eats[{ian, lisa}] = {eggs, cheese, pizza, salad}
2. eats 1 = { eggs ian, cheese ian, pizza ian,
eggs jim, salad jim, pizza ken,
cheese lisa, salad lisa, pizza lisa}
3. eats 1[{cheese, eggs}] = {ian, jim, lisa}
4. eats ; cost = { ian cheap, ian expensive, jim cheap,
7. eats <+ {lisa steak} = { ian eggs, ian cheese, ian pizza,
jim eggs, jim salad, ken pizza, lisa steak}
13
Exercise 6.3
The invariant becomes
access USER PRINTER uu . (uu USER card(access[{uu}])
6 6)
Two operations are no longer consistent with this strengthened invariant: add,
and unify.
In order to regain consistency of the machine, the precondition of add can
be strengthened to
uu USER pp PRINTER card(access[{uu}]) < 6
and the precondition of unify can be strengthened to
u1 USER u2 USER card(access[{u1}]) + card(access[{u2}])
66
.
Exercise 6.4
exchange ( u1 , u2 ) =
b
PRE u1 USER u2 USER
THEN access := access <+ ( { u1 } access [ { u2 } ] { u2 } access [ { u1 } ] )
END
Exercise 6.5
maintenance ( pp , alt ) =
b
PRE pp PRINTER alt PRINTER
THEN access := access { pp } access
END
[ { pp } ] { alt }
Exercise 6.6
The variable barred and associated conditions and operations are incorporated
into the machine below. The operations which require strengthened preconditions are again add and unify. all other operations are consistent with the next
invariant and remain unchanged from their description in the original Access
machine.
MACHINE Access
SETS USER ; PRINTER ; OPTION ; PERMISSION = { ok , noaccess }
CONSTANTS options
PROPERTIES options PRINTER OPTION
14
[ { oo } ]
removebar ( uu , oo ) =
b
PRE uu USER oo OPTION uu oo barred
THEN barred := barred { uu oo }
END
add ( uu , pp ) =
b
PRE uu USER pp PRINTER options [ { pp } ] barred [ { uu } ] = {}
THEN access := access { uu pp }
END
unify ( u1 , u2 ) =
b
PRE u1 USER u2 USER access ; options [ { u1 , u2 } ] barred [ { u1 , u2 } ] = {}
THEN access := access { u1 } access [ { u2 } ] { u2 } access [ { u1 } ]
END
END
15
END
start ( rr , cc ) =
b
PRE rr READER cc copies copyof ( cc ) 6 hasread [ { rr } ]
rr 6 dom ( reading ) cc 6 ran ( reading )
THEN reading := reading { rr cc }
END
finished ( rr , cc ) =
b
PRE rr READER cc copies cc = reading ( rr )
THEN hasread := hasread { rr copyof ( cc ) }
k reading := { rr } reading
END
resp - precurrentquery ( rr ) =
b
PRE rr READER
THEN
IF rr dom ( reading )
THEN resp := yes
ELSE resp := no
END
END
bb - currentquery ( rr ) =
b
PRE rr READER rr dom ( reading )
THEN bb := copyof ( reading ( rr ) )
END
resp - hasreadquery ( rr , bb ) =
b
PRE rr READER bb BOOK
16
THEN
IF bb hasread [ { rr } ]
THEN resp := yes
ELSE resp := no
END
END
END
Exercise 7.2
pp - position ( rr ) =
b
PRE rr ran ( finish )
THEN pp := finish 1 ( rr )
END
remove ( rr ) =
b
PRE rr ran ( finish )
THEN
pp
BE pp = finish
LET
IN
( rr )
finish := finish pp 1
END
END
a ( finish pp )
17
i =j i =k
i = j i k a(k) = 5
i j i = k a(j ) = 5
i j i k a(j ) = a(k)
Exercise 8.2
a := x . (x dom(a) | 2 x)
Exercise 8.3
betterswap ( rr , ss ) =
b
PRE
rr ROOM ss ROOM
( rr small numbers ( ss ) 4 )
( ss small numbers ( rr ) 4 )
THEN numbers := numbers <+ { rr numbers ( ss ) , ss numbers ( rr ) }
END
Exercise 8.4
step =
b
guests := xx . ( xx
N xx + 1 ROOM
| guests ( xx + 1 ) )
Exercise 8.5
MACHINE Hotelguests ( sze )
CONSTRAINTS sze N1
SETS NAME ; REPORT = { present , notpresent }
CONSTANTS empty , ROOM
PROPERTIES card ( ROOM ) = sze empty NAME ROOM
VARIABLES pguests
INVARIANT pguests ROOM
7 NAME
INITIALISATION pguests := {}
OPERATIONS
guestcheckin ( rr , nn ) =
b
18
rr ROOM nn NAME
THEN pguests ( rr ) := nn
PRE
END
guestcheckout ( rr ) =
b
PRE rr ROOM
THEN pguests := { rr } pguests
END
nn - guestquery ( rr ) =
b
PRE rr ROOM
THEN IF rr dom ( pguests )
THEN nn := pguests ( rr )
ELSE nn := empty
END
END
rr - presentquery ( nn ) =
b
PRE nn NAME
THEN IF nn ran ( pguests )
THEN rr := present
ELSE rr := notpresent
END
END
guestswap ( rr , ss ) =
b
PRE rr ROOM ss ROOM
THEN
IF rr dom ( pguests )
ss dom ( pguests )
THEN pguests := pguests <+ { rr pguests ( ss ) , ss pguests ( rr ) }
ELSE pguests := { rr } pguests { ss pguests ( rr ) }
THEN IF
END
END
END
END
step =
b
pguests := xx . ( xx
END
N xx + 1 dom ( pguests )
| pguests ( xx + 1 ) )
19
WHERE nn : N
THEN square := nn nn
END
Exercise 9.2
This operation adds some arbitrary value between 1 and 5 to total.
[ ANY a WHERE a N1 a
=
a . (a N1 a
a . (a N1
total
>8
Exercise 9.3
This statement picks an arbitrary set of up to three numbers between 1 and N .
[ ANY s WHERE s 1..N card(s)
=
=
=
The statement is guaranteed to achieve the postcondition provided the numbers comprising the set are all no greater than 14.
Exercise 9.4
ANY nn WHERE nn 1..49 card(nn) = 6 THEN ticket := nn END
Exercise 9.5
ANY d WHERE d : order [{p}] THEN delivery := d END
20
Exercise 9.6
CHOICE salary := salary 1.03 OR salary := salary + 400 END
[ CHOICE salary := salary 1.03 OR salary := salary + 400 END ](salary > 14000)
=
[salary := salary 1.03](salary > 14000) [salary := salary + 400](salary > 14000]
Exercise 9.7
1.
(hh = clarissa)
2.
(hh albsert )
21
albert 6 here
3.
(hh fido)
Exercise 9.8
MACHINE Deliveries
SETS ITEM ; ADDRESS
VARIABLES van , nogo
INVARIANT van ADDRESS ITEM nogo ADDRESS
INITIALISATION van := {} k nogo : P ( ADDRESS )
OPERATIONS
load ( aa , ii ) =
b
PRE aa ADDRESS ii ITEM
THEN van := van { aa ii }
END
aa , ii - drop =
b
PRE van {}
THEN
ad , it
ad ADDRESS it ITEM ad it van
THEN aa := ad k ii := it
ANY
WHERE
END
END
warning ( aa ) =
b
PRE aa ADDRESS
THEN IF aa nogo
22
van := { aa } van
OR nogo := nogo { aa }
THEN CHOICE
END
END
23
;
The new operation for Safes is
quickcloseandlock ( dd ) =
b
PRE dd DOOR position ( dd ) = open
THEN quickclose ( dd ) k removekey ( unlocks
END
( dd ) )
Exercise 10.2
MACHINE Safes
INCLUDES Locks , Keys
PROMOTES opendoor , closedoor , lockdoor
CONSTANTS unlocks
PROPERTIES unlocks KEY DOOR
VARIABLES masterkey
INVARIANT status 1 [ { unlocked } ] unlocks [ keys ]
masterkey DOOR card ( masterkey ) 1
status 1 [ { unlocked } ] masterkey
INITIALISATION masterkey := {}
OPERATIONS
insertmaster ( dd ) =
b
PRE dd DOOR masterkey = {}
THEN masterkey := { dd }
END
removemaster =
b
PRE status [ masterkey ] = { locked }
THEN masterkey := {}
END
insert ( kk , dd ) =
b
PRE kk KEY dd DOOR unlocks ( kk ) = dd
24
insertkey ( kk )
THEN
END
extract ( kk , dd ) =
b
PRE kk KEY dd DOOR unlocks ( kk ) = dd status ( dd ) = locked
THEN removekey ( kk )
END
unlock ( dd ) =
b
PRE dd DOOR unlocks
THEN unlockdoor ( dd )
END
( dd ) keys dd masterkey
quicklock ( dd ) =
b
PRE dd DOOR position ( dd ) = closed
THEN lockdoor ( dd ) k removekey ( unlocks
( dd ) )
END
END
Exercise 10.3
MACHINE Safes
INCLUDES Locks , Keys
PROMOTES opendoor , closedoor , lockdoor
VARIABLES unlocks
INVARIANT status 1 [ { unlocked } ] unlocks [ keys ]
unlocks KEY 7 DOOR keys dom ( unlocks )
INITIALISATION unlocks := {}
OPERATIONS
allocate ( kk , dd ) =
b
PRE kk KEY kk 6 dom ( unlocks ) dd DOOR dd 6 ran ( unlocks )
THEN unlocks ( kk ) := dd
END
deallocate ( kk , dd ) =
b
PRE kk KEY dd DOOR kk dd unlocks kk 6 keys status ( dd ) = locked
THEN unlocks := { kk } unlocks
END
insert ( kk , dd ) =
b
PRE kk KEY dd DOOR unlocks ( kk ) = dd
THEN insertkey ( kk )
END
extract ( kk , dd ) =
b
PRE kk KEY dd DOOR unlocks ( kk ) = dd status ( dd ) = locked
THEN removekey ( kk )
END
unlock ( dd ) =
b
PRE dd DOOR unlocks
( dd ) keys
25
unlockdoor ( dd )
THEN
END
quicklock ( dd ) =
b
PRE dd DOOR position ( dd ) = closed dd ran ( unlocks )
THEN lockdoor ( dd ) k removekey ( unlocks 1 ( dd ) )
END
END
Exercise 10.4
MACHINE RobustLocks
INCLUDES Locks
SETS REPORT = { ok , error }
OPERATIONS
rep - robustopen ( dd ) =
b
PRE dd DOOR
THEN IF status ( dd ) = unlocked
THEN opendoor ( dd ) k rep := ok
ELSE rep := error
END
END
rep - robustclose ( dd ) =
b
PRE dd DOOR
THEN closedoor ( dd ) k rep := ok
END
rep - robustunlock ( dd ) =
b
PRE dd DOOR
THEN unlockdoor ( dd ) k rep := ok
END
rep - robustlock ( dd ) =
b
PRE dd DOOR
THEN IF position ( dd ) = closed
THEN lockdoor ( dd ) k rep := ok
ELSE rep := error
END
END
END
Exercise 10.5
MACHINE Hotelregister ( sze )
INCLUDES Hotel ( sze ) , Hotelguests ( sze )
PROMOTES guestquery , presentquery , roomquery , vacancies , totalguests
INVARIANT guests 1 [ { empty } ] = numbers 1 [ { 0 } ]
26
OPERATIONS
fullcheckin ( room , name , number ) =
b
PRE name NAME number 1 . . 6
room ROOM guests ( room ) = empty name empty
( room small number 4 )
THEN checkin ( room , number ) k guestcheckin ( room , name )
END
fullcheckout ( room ) =
b
PRE room ROOM
THEN checkout ( room ) k guestcheckout ( room )
END
END
27
N1
pp - limitquery ( gg ) =
b
PRE gg GOODS THEN pp := limit ( gg ) END
END
MACHINE Customer
SEES Price , Goods , Limit
VARIABLES purchases
INVARIANT purchases GOODS
INITIALISATION purchases := {}
OPERATIONS
pp - buy ( gg ) =
b
PRE gg GOODS price ( gg ) limit ( gg )
THEN purchases := purchases { gg } k pp - pricequery ( gg )
END
END
Exercise 11.2
change ( nn ) =
b
PRE nn PERSON nn male female
THEN IF nn male
THEN female := female { nn } k male := male { nn }
ELSE male := male { nn } k female := female { nn }
END
END
The sexchange operation must take into account the possibility that
the person nn is married. Here we simply include as a precondition that
nn should not be married. Thus the function marriage will not change. An
28
Exercise 11.3
MACHINE Voters
USES Life
SETS RESPONSES = { listed , notlisted }
VARIABLES voters
INVARIANT voters male female
INITIALISATION voters := {}
OPERATIONS
addvoter ( nn ) =
b
PRE nn male female
THEN voters := voters { nn }
END
removevoter ( nn ) =
b
PRE nn male female
THEN voters := voters { nn }
END
resp - voterquery ( nn ) =
b
PRE nn PERSON
THEN IF nn voters
THEN resp := listed
ELSE resp := notlisted
END
END
END
In fact, Voters can be included in Registrar, and all its operations can be
promoted, so the extends clause is used. The dies operation requires amendment: when a person dies then they should also be removed from the electoral
roll.
MACHINE Registrar
EXTENDS Marriage , Voters
INCLUDES Life
PROMOTES born
OPERATIONS
dies ( nn ) =
b
29
nn male female
PRE
THEN
die ( nn ) k removevoter ( nn ) k
IF nn dom ( marriage )
THEN part ( nn , marriage ( nn ) )
ELSIF nn ran ( marriage )
THEN part ( marriage 1 ( nn ) , nn )
END
END
END
Exercise 11.4
MACHINE Fullregistrar
INCLUDES Registrar
PROMOTES partner
SETS STATUS = { bachelor , spinster , married , divorced , widow , widower }
VARIABLES status
INVARIANT status male female STATUS
status 1 [ { married } ] = dom ( marriage ) ran ( marriage )
INITIALISATION status := {}
OPERATIONS
birth ( nn , ss ) =
b
PRE nn PERSON nn 6 ( male female ) ss SEX
THEN born ( nn , ss )
k IF ss = boy
THEN status ( nn ) := bachelor
ELSE status ( nn ) := spinster
END
END
death ( nn ) =
b
PRE nn PERSON nn male female
THEN dies ( nn )
k IF status ( nn ) married
THEN status := { nn } status
ELSE IF nn male
THEN status := { nn } status <+ { marriage ( nn ) widow }
ELSE status := { nn } status <+ { marriage 1 ( nn ) widower }
END
C
C
END
END
marry ( mm , ff ) =
b
PRE mm male mm 6 dom ( marriage ) ff female ff 6 ran ( marriage )
THEN wed ( mm , ff )
30
divorce ( mm , ff ) =
b
PRE mm male ff female mm ff marriage
THEN part ( mm , ff )
k status := status <+ { mm divorced , ff divorced }
END
ss - maritalstatus ( nn ) =
b
PRE nn male female
THEN ss := status ( nn )
END
END
31
N ran(aa) = orders
2. aa 1..300 7
Exercise 12.2
The first refinement uses an 11-place array.
REFINEMENT PlayerR
REFINES Player
VARIABLES teamr
INVARIANT teamr 1 . . 11
PLAYER ran ( teamr ) = team
PLAYER
INITIALISATION teamr : 1 . . 11
OPERATIONS
substitute ( pp , rr ) =
b
BEGIN
teamr ( teamr
END
( pp ) ) := rr
aa - query ( pp ) =
b
IF pp ran ( teamr )
THEN aa := in
ELSE aa := out
END
END
The second refinement uses an array indexed by the players, recording for
each whether he is in or out of the team.
REFINEMENT PlayerR2
REFINES Player
VARIABLES teamr
INVARIANT teamr PLAYER ANSWER team = teamr 1 [ { in } ]
INITIALISATION ANY tr WHERE tr PLAYER ANSWER card ( tr
THEN teamr := tr
[ { in } ] ) = 11
32
END
OPERATIONS
substitute ( pp , rr ) =
b
BEGIN
teamr ( pp ) := out ;
teamr ( rr ) := in
END
aa - query ( pp ) =
b aa := teamr ( pp )
END
Exercise 12.3
In the abstract machine:
jumpqueue ( ss , qq ) =
b
PRE ss SHIP ss 6 ran ( waiting ) ss 6 ran ( docked )
qq QUAY qq 6 dom ( docked )
THEN docked ( qq ) := ss
END
In the refinement:
jumpqueue ( ss , qq ) =
b insert ( ss , qq ) ;
33
REFINEMENT JobshopR
REFINES Jobshop
VARIABLES jobarr
INVARIANT jobarr 1 . . limit
7 JOB ran ( jobarr ) = jobs
INITIALISATION jobarr := {}
OPERATIONS
take ( jj ) =
b
ANY tmp WHERE tmp 1 . . limit tmp 6 dom ( jobarr ) THEN
jobarr ( tmp ) := jj
END
jj - process =
b
ANY tmp WHERE tmp dom ( jobarr ) THEN
jj := jobarr ( tmp ) ;
jobarr := { tmp } jobarr
END
prioritise ( jj ) =
b jobarr := jobarr { jj }
END
REFINEMENT JobshopRR
REFINES Jobshop
VARIABLES jobarr , counter
INVARIANT jobarr 1 . . limit JOB counter 0 . . limit
jobarr [ 1 . . counter ] = jobs counter = card ( jobs )
INITIALISATION jobarr : 1 . . limit JOB ; counter := 0
OPERATIONS
take ( jj ) =
b
BEGIN
jj - process =
b
BEGIN
jj := jobarr ( counter ) ;
counter := counter 1
END
prioritise ( jj ) =
b
ANY ii WHERE ii 1 . . counter jobarr ( ii ) = jj THEN
34
END
Exercise 13.2
REFINEMENT BoothR
REFINES Booth
VARIABLES reserved , ticketsr
INVARIANT ticketsr SEAT
7 CUSTOMER
cc . ( cc CUSTOMER card ( ticketsr
= card ( tickets
[ { cc } ] )
[ { cc } ] ) + reserved ( cc ) )
reserved ( cc ) := reserved ( cc ) + nn k
ANY ss WHERE ss SEAT card ( ss ) = nn ss dom ( ticketsr ) = {} THEN
ticketsr := ticketsr ss { cc }
END
END
collect ( cc ) =
b reserved ( cc ) := 0
END
35
i.e. there is some subset of {red, green}) which contains redand this proof
obligation is true.
Each operation PRE P1 THEN S 1 END which refines PRE P THEN S END
will have the proof obligation that I J P [S 1[out /out ]][S ](J
out = out ), where I is the invariant of Colours. For each operation in turn we
calculate [S 1[out /out ]][S ](J out = out ) and show that it is implied by
I J P.
add(cc): This operation does not have any outputs.
[S 1][S ]J
=
red cols
I J P
(= J )
cc - query:
[S 1[out /out ]][S ]J
=
red cols
I J P
(= J )
36
true
I J P
The penultimate line follows from the fact that there will always be some subset
of COLOUR other than cols which contains red (since there are 4 such subsets
altogether).
Thus all proof obligations are discharges, establishing that ColoursR2 is a
refinement of Colours.
If the invariant is simply true then the query operations proof obligations
will not discharge. This linking invariant is not strong enough to establish that
ColoursR2 is a refinement of Colours.
Exercise 14.2
There are no sets or constants introduced by TeamR, so there are no proof
obligations generated there.
The proof obligation for initialisation is as follows:
[teamr := nn . (nn 1..11 | nn)]
[team := 1..11]
(teamr 1..11
=
(teamr 1..11
=
I J P
(teamr <+ {teamr 1
37
I J
[ IF pp ran(teamr ) THEN aa := in ELSE aa := out END ]
J (pp team aa = in
pp 6 team aa = out )
I J
J (pp ran(teamr ) pp team in = in
pp 6 ran(teamr ) pp team out = in
pp ran(teamr ) pp 6 team in = out
pp 6 ran(teamr ) pp 6 team out = out )
REFINEMENT Colours2R
REFINES Colours2
VARIABLES in , out
INVARIANT in cols out COLOUR
( cols COLOUR out COLOUR cols ) in out
INITIALISATION in := red k out := blue
OPERATIONS
add ( cc ) =
b BEGIN IF cc = out THEN out : COLOUR { in , out } END
cc - inquery =
b cc := in ;
cc - outquery =
b cc := out ;
change =
b skip ;
invert =
b VAR tt IN tt := in ; in := out ; out := tt
END
END
END
38
39
The first and the fifth are true. The second is false in the case where r = b or
r < 0. The third is falser could be negative. The fourth is false when b 0,
since then r b does not decrease r . The third and fourth indicate that the
invariant requires strengthening to state that b > 0 and that r 0. The second
proof obligations indicates that the guard of the loop should be r
b rather
than r > b.
>
>
>b
DO q := q + 1; r := r b
INVARIANT r N b N1 r + (q b) = a
VARIANT r
END
Since the invariant must be true when the loop is started, it requires that a
N b N1 .
Exercise 15.4
ans := TRUE
j := 2
WHILE j < n
DO IF n mod j = 0 THEN ans := FALSE END ; j := j + 1
INVARIANT ans = TRUE ( i.(i 2..j 1 n mod i 0)) j
VARIANT n j
END
Exercise 15.5
i := 0;
maximum := 0;
WHILE i < N
DO i := i + 1;
IF arr (i) > maximum THEN maximum := arr (i) END
INVARIANT maximum = max(arr [1..i] {0}) i 0..N
VARIANT N i
END
6n
40
Exercise 15.6
We first calculate
[ IF i = 0 THEN rep := FALSE ELSE rep := TRUE END ](rep = TRUE p ran(a))
=
(i = 0 p 6 ran(a)) (i 0 p ran(a))
(=
P)
This is the postcondition for the loop section of the program. The proof conditions for the loop are therefore:
1. (p 6 a[(i + 1)..N ] i
a[(i + 1)..N ] i N)
3. (p 6 a[(i + 1)..N ] i N i N
These are all straightforward to establish, except the second, which bears
closer examination:
(p 6 a[(i + 1)..N ] i N (i > 0 a(i) p))
=
i = 0 p 6 a[(i + 1)..N ]
a(i) = p p 6 a[(i + 1)..N ]
i = 0 p 6 ran(a)
a(i) = p i 0 p ran(a)
6 a(x + 1))
x . (x dom(b) x size(b) b(x) 6 b(x + 1))
x . (x dom(a) x size(a) a(x)
41
Exercise 15.8
i := a;
j := b;
k := a;
l := b;
WHILE i j
DO IF i < j
THEN j := j i; l := l + k
ELSE i := i j ; k := k + l
END
INVARIANT (i l) + (j k) = 2 a b
VARIANT i + j
END ;
gcd := i;
x := (k + l)/2
The value of x at the end of the loop is (k + l)/2, and i = j = gcd(a, b). Since
the invariant il + jk = 2ab is true on termination, i.e. gcd(a, b) (l + k) = 2ab,
we have that (k + l)/2 = ab/gcd(a, b) = lcm(a, b), i.e. x is the lowest common
multiple of a and b: the smallest number that they both divide into.
42
Exercise 16.1
[ VAR nn IN nn - number ;
IF nn < cap
END ]
[ VAR nn IN nn - number ;
END ]
IF nn < cap
THEN rr := ok; input (ee); inc
ELSE rr := failed
END
(size(queue) < cap (counter = size(contents) contents = queue ee rr = ok)
size(queue)
=
[ VAR nn IN nn := counter ;
IF nn < cap
THEN rr := ok;
PRE ee ELEM size(contents < cap)
THEN contents := contents ee
END ;
counter := counter + 1
ELSE rr := failed
END
END ]
(size(queue) < cap ( counter = size(contents)
contents = queue ee
rr = ok)
size(queue)
= failed)
43
size(queue)
counter
> cap
ok = failed))
(size(queue) < cap ( counter = size(contents)
contents = queue ee
failed = ok)
size(queue)
counter
> cap
size(queue)
contents = queue)
I J P
as required.
Exercise 16.2
MACHINE RussianMult
OPERATIONS
rr - mult ( aa , bb ) =
b
PRE aa N1 bb N1
THEN rr := aa bb
END
END
IMPLEMENTATION RussianMultI
REFINES RussianMult
IMPORTS RussianBody
OPERATIONS
rr - mult ( aa , bb ) =
b
VAR xx , yy , total IN
xx := aa ;
yy := bb ;
total := 0 ;
WHILE xx > 0
DO xx , yy , total - body ( xx , yy , total )
44
INVARIANT
VARIANT
END
total + xx yy = aa bb xx
N yy N total N
xx
rr := total
END
END
MACHINE RussianBody
OPERATIONS
dd , ee , tt - body ( xx , yy , ss ) =
b
PRE xx N yy N ss N
THEN
IF xx mod 2 = 1 THEN
tt := ss + yy END
k dd := xx / 2
k ee := yy 2
END
END
Exercise 16.3
IMPLEMENTATION DateI
REFINES Date
SEES DateFields
PROPERTIES
DATE = { dd , mm , yy | dd DAY mm MONTH yy YEAR
( mm { April , June , September , November } dd 30 )
( mm = February dd 29 )
( mm = February ( yy YEAR yy mod 4 0 }
( yy mod 100 = 0 yy mod 400 0 ) )
dd 28 )
END
MACHINE DateFields
SETS DAY ; YEAR ;
MONTH = { January , February , March , April , May , June ,
July , August , September , October , November , December }
PROPERTIES DAY = 1 . . 31 YEAR = N
END
45
inc ;
VAR ii , rep IN
ii - number ;
rep := TRUE ;
append ( nn ) ;
WHILE ii > 1 rep = TRUE
DO rep - siftup ( ii ) ; ii := ii / 2
INVARIANT ii 1 . . counter counter = size ( queue ) + 1
( xx , yy ) . ( xx 2 . . counter 1 yy 1 . . counter 1
( xx yy parent *
( rep = FALSE
xx . ( xx
xx ii ) heaparray ( yy ) heaparray ( xx ) ) )
card ( heaparray
[ { xx } ] )
ii
END
END
END
MACHINE Heaparray
...
rr - siftup ( ii ) =
b
PRE ii 2 . . size ( heaparray )
THEN IF heaparray ( ii / 2 ) > heaparray ( ii )
THEN heaparray := heaparray <+ { ii / 2 heaparray ( ii ) , ii heaparray ( ii / 2 ) }
k rr := TRUE
ELSE rr := FALSE
END
END
Exercise 17.2
sort ( ii , jj ) =
b
PRE ii 1 . . cap jj 1 . . cap ii < jj
46
THEN
ANY
pp
pp ii . . jj ii . . jj
nn . ( nn ii . . jj 1 pp ; aa ( nn ) pp ; aa ( nn + 1 ) )
THEN aa := aa <+ ( pp ; aa )
WHERE
END
END
IMPLEMENTATION SortarrayI
...
sort ( ii , jj ) =
b
BEGIN
cc , nn IN
cc := ii 1 ;
WHILE cc < jj
DO cc := cc + 1 ;
nn - get ( cc ) ;
insert ( nn )
INVARIANT cc ii 1 . . jj
pp . ( pp ii . . cc 1 . . cc ( ii 1 ) ( pp ; queue ) = ii . . cc
array = aa
VARIANT jj cc
VAR
C array )
END
END
cc , nn IN
cc := ii 1 ;
WHILE cc < jj
DO cc := cc + 1 ;
nn - extract ;
set ( cc , nn )
INVARIANT cc N cc cap
VAR
pp . ( pp ii . . jj ii . . jj ( pp ; queue ( ii . . cc array ) ) = ii . . jj
xx . ( xx ii . . cc 1 array ( xx ) array ( xx + 1 ) )
( xx , yy ) . ( xx ran ( queue ) yy array [ ii . . cc ] yy xx )
VARIANT cap cc
END
END
END
END
C aa )
47
IMPLEMENTATION SizeCounterI
REFINES SizeCounter
IMPORTS sze Nvar ( maximum )
INVARIANT sze Nvar = sze
INITIALISATION sze STO NVAR ( 0 )
OPERATIONS
szeinc =
b sze INC NVAR ;
szedec =
b sze DEC NVAR ;
ss - szeget =
b ss - sze VAL NVAR
END
Exercise 18.2
MACHINE Checkouts
...
OPERATIONS
closeandmove ( co1 , co2 ) =
b
PRE co1 COUNTER co2 COUNTER
THEN opencounters := opencounters { co1 }
...
IMPLEMENTATION CheckoutsI
...
closeandmove ( co1 , co2 ) =
b
VAR tt1 , tt2 , bb IN
tt1 - get ( co1 ) ;
tt2 - get ( co2 ) ;
bb - queues APP SEQ OBJ ( tt2 , tt1 ) ;
queues KIL SEQ OBJ ( tt1 ) ;
remove ( co1 )
END
...
a queues ( co1 ) ) }
48
Exercise 18.3
Specification:
jumpqueue ( co , cu ) =
b
PRE
co opencounters cu CUSTOMER
S
cu 6 cc . ( cc dom ( queues ) | ran ( queues ( cc ) ) )
THEN queues ( co ) := cu queues ( co )
END
Implementation:
jumpqueue ( co , cu ) =
b
VAR pp , bb IN
pp - get ( co ) ;
queues REV SEQ OBJ ( pp ) ;
bb - queues PSH SEQ OBJ ( pp , cu ) ;
queues REV SEQ OBJ ( pp )
END
Exercise 18.4
rep - present ( cu ) =
b
PRE cu CUSTOMER
THEN
IF cu
;
Implementation:
rep - present ( cu ) =
b
VAR nn , pp , bb , ii , ans IN
nn , pp - queues FIRST SEQ OBJ ;
ans := FALSE ;
WHILE nn > 0
DO bb , ii - queues MBR SEQ OBJ ( pp , cu ) ;
IF bb = TRUE THEN ans := TRUE END ;
nn , pp - queues NEXT SEQ OBJ ( nn , pp )
INVARIANT nn N
VARIANT nn
END
rep := ans
END
49
Exercise 18.5
mm - maximum =
b
VAR vv , ii , msf IN
msf := 0 ;
ii - marks CRD SET ;
WHILE ii > 0
DO vv - marks VAL SET ( ii ) ;
IF vv > msf THEN msf := vv END ;
ii := ii 1
INVARIANT
ii N
msf = max ( marks ordn [ ii + 1 . . card ( marks ) ] { 0 } )
marks sset = marks
VARIANT
ii
END
mm := msf
END
Exercise 18.6
IMPLEMENTATION BasketsI
REFINES Baskets
IMPORTS
Baskets set obj ( GOODS , 1000 , 1000 ) ,
Baskets set ctx , Pfun ( CUSTOMER , Baskets SETOBJ ) , Bool TYPE
INVARIANT ( pfun ; Baskets setstruct ) = baskets
ran ( pfun ) = Baskets settok
OPERATIONS
enter ( cu ) =
b
VAR bb , pp IN
bb , pp - Baskets CRE SET OBJ ;
set ( cu , pp )
END
add ( cu , gg ) =
b
VAR pp , bb IN
pp - get ( cu ) ;
bb - Baskets ENT SET OBJ ( pp , gg )
END
nn - checkout ( cu ) =
b
VAR pp , ll , ii , total , vv IN
pp - get ( cu ) ;
50
ii 0 . . ll
P
total =
jj . ( jj Baskets setord ( pp ) [ 1 . . ii ] | price ( jj ) )
VARIANT ll ii
END
nn := total ;
Baskets KIL SET OBJ ( pp )
END
END