Documentos de Académico
Documentos de Profesional
Documentos de Cultura
This document contains sample solutions to the exercises in the book The B-Method: an Introduction by Steve Schneider. Steve Schneider S.Schneider@rhul.ac.uk June 2001
Exercise 1.2 MACHINE Ticket VARIABLES serve , next INVARIANT serve next serve next next 501 INITIALISATION serve , next := 0 , 0 OPERATIONS ss serve next = PRE serve < next THEN ss , serve := serve + 1 , serve + 1
END
tt
Exercise 1.4 MACHINE Ticket14 VARIABLES serve , next , record INVARIANT serve next record serve next INITIALISATION serve , next , record := 0 , 0 , 0 OPERATIONS ss serve next = PRE serve < next THEN ss , serve , record := serve + 1 , serve + 1 , 0
END
tt
take ticket = PRE true THEN tt , next , record := next , next + 1 , record + 1
END
rr
END
Exercise 1.5 MACHINE Ticket VARIABLES serve , next , lim INVARIANT serve next lim serve next next lim INITIALISATION serve , next , lim := 0 , 0 , 500 OPERATIONS ss serve next = PRE serve < next THEN ss , serve := serve + 1 , serve + 1
END
tt
take ticket = PRE next < lim THEN tt , next := next , next + 1
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 contents 640 INITIALISATION contents := 0 OPERATIONS
nn
END
MEMBER.
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, {olly} 0, {pat } 0, {olly, pat } 1, {} 1, {olly} 1, {pat } 1, {olly, pat } 2, {olly, pat } 2, {olly} 2, {pat } 2, {}
0, {} 0, {olly} 0, {pat } 0, {olly, pat } 1, {} 1, {olly} 1, {pat } 1, {olly, pat } 2, {olly, pat } 2, {olly} 2, {pat } 2, {}
Exercise 3.2
0, 0 0, 1 0, 2 1, 0 1, 1 1, 2 2, 0 2, 1 2, 2
0, 0 0, 1 0, 2 1, 0 1, 1 1, 2 2, 0 2, 1 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 < y [y := y x](x + y = 2)) (x (x 2 [x := x y](x + y = 2)) y x y + y = 2) y x = 2) (x < y x + y x = 2) (x < y 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
E1 [S1 ]P (E1 E2 ) [S2 ]P = ... (E1 ... En1 En ) [Sn ]P (E1 E2 ... En ) [Sn+1 ]P
3. z.(z 7 < z 2 ) (= false) 4. house set {x, y} (x 1)..(y + 1) = house set x 1..y + 1 5. num = card(house set ) 6. house set old set {new} Exercise 3.5 If i is even then it sets ans to even, otherwise it sets it to odd. The weakest precondition for it to establish that ans = even is that i mod 2 = 0. Exercise 3.6 That (i + 2)/3 is not 2 or 3; i.e. that i < 4 or that i > 9.
This operation is consistent with the invariant of Paperround. Exercise 4.2 removehouse(hh) = PRE hh papers THEN papers := papers {hh} || magazines := magazines {hh}
END
The proof obligations for this operation are given by instantiating I P [S ]I : in this case, that (papers 1..163 magazines papers card(papers) 60) hh papers 60)
[papers := papers {hh} || magazines := magazines {hh}] (papers 1..163 magazines papers card(papers)
or, using the weakest precondition rule for assignment, that (papers 1..163 magazines papers card(papers) card(papers {hh}) 60) 60) hh papers
which is true by elementary logic and set theory. Exercise 4.3 The operations addmagazine and remove are not consistent with the new invariant. Their preconditions require strengthening, for example as follows: addmagazine ( hh ) = PRE hh papers card ( magazines ) < card ( papers ) / 2 THEN magazines := magazines { hh }
END
10 THEN END
papers := papers { hh }
magazines := magazines { hh }
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 passengers tickets passengers INITIALISATION tickets , passengers := 0 , 0 OPERATIONS buy ( mm ) = PRE mm tickets + mm passengers THEN tickets := tickets + mm
END
END With the additional clause passengers tickets + 45 in the invariant, the operations board and double which increase the number of passengers require stronger preconditions to prevent violation of this new clause. The new precondition for board is nn passengers + nn tickets + 45
11
12
eats = {ian eggs, ian cheese, ian pizza} ken pizza, lisa cheese, lisa salad, lisa pizza}
3. {jim} eats = { ian eggs, ian cheese, ian pizza 4. eats {cheese, pizza} = { ian cheese, ian pizza, ken pizza, lisa cheese, lisa pizza 5. dom(eats 6. dom(eats 7. dom(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, kenmapstoexpensive, lisa cheap, lisa expensive} 5. eats ; (cost {expensive}) = {ian cheap, jim cheap, lisa cheap} 6. eats 1[cost 1 [{expensive}]] = {ian, ken, lisa}
+ 7. eats < {lisa steak} = { ian eggs, ian cheese, ian pizza,
13
Exercise 6.3 The invariant becomes access USER PRINTER uu . (uu USER card(access[{uu}]) 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}]) . Exercise 6.4 exchange ( u1 , u2 ) = PRE u1 USER u2 USER + THEN access := access < ( { u1 } access [ { u2 } ] { u2 } access [ { u1 } ] )
END
Exercise 6.5 maintenance ( pp , alt ) = 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
dom ( options ) = PRINTER ran ( options ) = OPTION VARIABLES access , barred INVARIANT access USER PRINTER barred USER OPTION ( access ; options ) barred = {} INITIALISATION access , barred := {} , {} OPERATIONS addbar ( uu , oo ) = PRE uu USER oo OPTION THEN barred := barred { uu oo } access := access { uu } options
END
[ { oo } ]
unify ( u1 , u2 ) = PRE u1 USER u2 USER access ; options [ { u1 , u2 } ] barred [ { u1 , u2 } ] = {} THEN access := access { u1 } access [ { u2 } ] { u2 } access [ { u1 } ]
END
END
15
start ( rr , cc ) = PRE rr READER cc copies copyof ( cc ) hasread [ { rr } ] rr dom ( reading ) cc ran ( reading ) THEN reading := reading { rr cc }
END
nished ( rr , cc ) = PRE rr READER cc copies cc = reading ( rr ) THEN hasread := hasread { rr copyof ( cc ) } reading := { rr } reading
END
;
precurrentquery ( rr ) = rr READER
resp
PRE THEN
bb
;
hasreadquery ( rr , bb ) = rr READER bb BOOK
resp
PRE
pp BE pp = nish
LET IN END END
( rr ) ( nish pp )
nish := nish pp 1
17
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 = guests := xx . ( xx Exercise 8.5 MACHINE Hotelguests ( sze ) CONSTRAINTS sze 1 SETS NAME ; REPORT = { present , notpresent } CONSTANTS empty , ROOM PROPERTIES card ( ROOM ) = sze empty NAME ROOM VARIABLES pguests INVARIANT pguests ROOM NAME INITIALISATION pguests := {} OPERATIONS guestcheckin ( rr , nn ) =
xx + 1 ROOM
| guests ( xx + 1 ) )
18 PRE
nn
rr
presentquery ( nn ) = PRE nn NAME THEN IF nn ran ( pguests ) THEN rr := present ELSE rr := notpresent
END END
ss dom ( pguests ) + THEN pguests := pguests < { rr pguests ( ss ) , ss pguests ( rr ) } ELSE pguests := { rr } pguests { ss pguests ( rr ) }
xx + 1 dom ( pguests )
| pguests ( xx + 1 ) )
19
total
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) = = = s . s 1..N card(s) s . s 1..N card(s) N 14 3 THEN myset := s END ](i.(i myset | i) < 40)
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
[ ANY d WHERE d : order [{p}] THEN delivery := d END ](delivery fridge) = = = d.(d : order [{p}] [delivery := d](delivery fridge)) d.(d : order [{p}] d fridge)) fridge order [{p}]
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] (salary 1.03 > 14000) (salary > 13600) salary > 13592 salary > 13600 salary > 13600
Exercise 9.7 1. WHEN betty here THEN hh := betty WHEN clarissa here THEN hh := clarissa ELSE hh := do END = SELECT albert here THEN hh := albert (hh = clarissa)
albert here [hh := albert ](hh = clarissa) (betty here [hh := betty](hh = clarissa)) (clarissa here [hh := clarissa](hh = clarissa) (albert here betty here clarissa here [hh := do](hh = clarissa)
albert here false (betty here false (clarissa here true (albert here betty here clarissa here false
= 2.
WHEN betty here THEN hh := betty WHEN clarissa here THEN hh := clarissa ELSE hh := do END =
(hh albsert )
albert here [hh := albert ](hh albert ) (betty here [hh := betty](hh albert )) (clarissa here [hh := clarissa](hh albert ) (albert here betty here clarissa here [hh := do](hh albert )
21
(clarissa here true (albert here betty here clarissa here true = 3. SELECT albert here THEN hh := albert WHEN betty here THEN hh := betty WHEN clarissa here THEN hh := clarissa ELSE hh := do END = (hh do) albert here
albert here [hh := albert ](hh do) (betty here [hh := betty](hh do)) (clarissa here [hh := clarissa](hh do) (albert here betty here clarissa here [hh := do](hh do)
albert here true (betty here true (clarissa here true (albert here betty here clarissa here false
= Exercise 9.8
MACHINE Deliveries SETS ITEM ; ADDRESS VARIABLES van , nogo INVARIANT van ADDRESS INITIALISATION van := {} OPERATIONS load ( aa , ii ) = PRE aa ADDRESS ii THEN van := van { aa
END
ITEM ii }
22 THEN CHOICE END ELSIF aa dom ( van ) THEN nogo := nogo { aa } END END
END
23
;
The new operation for Safes is
( 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 ) = PRE dd DOOR masterkey = {} THEN masterkey := { dd }
END
24 THEN END
insertkey ( kk )
;
1
( dd ) keys dd masterkey
( dd ) )
END
Exercise 10.3 MACHINE Safes INCLUDES Locks , Keys PROMOTES opendoor , closedoor , lockdoor VARIABLES unlocks INVARIANT status 1 [ { unlocked } ] unlocks [ keys ] DOOR keys dom ( unlocks ) unlocks KEY INITIALISATION unlocks := {} OPERATIONS allocate ( kk , dd ) = PRE kk KEY kk dom ( unlocks ) dd DOOR dd ran ( unlocks ) THEN unlocks ( kk ) := dd
END
deallocate ( kk , dd ) = PRE kk KEY dd DOOR kk dd unlocks kk keys status ( dd ) = locked THEN unlocks := { kk } unlocks
END
;
1
( dd ) keys
25 THEN END
unlockdoor ( dd )
quicklock ( dd ) = PRE dd DOOR position ( dd ) = closed dd ran ( unlocks ) THEN lockdoor ( dd ) removekey ( unlocks 1 ( dd ) )
END
END
Exercise 10.4 MACHINE RobustLocks INCLUDES Locks SETS REPORT = { ok , error } OPERATIONS rep robustopen ( dd ) = PRE dd DOOR THEN IF status ( dd ) = unlocked THEN opendoor ( dd ) rep := ok ELSE rep := error
END END
rep
rep
rep
robustlock ( dd ) = PRE dd DOOR THEN IF position ( dd ) = closed THEN lockdoor ( dd ) 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 ) = PRE name NAME number 1 . . 6 room ROOM guests ( room ) = empty name empty ( room small number 4 ) THEN checkin ( room , number ) guestcheckin ( room , name )
END
guestcheckout ( room )
fullswap ( room1 , room2 ) = PRE room1 ROOM room2 ROOM room1 small ( room2 small ) THEN swap ( room1 , room2 ) guestswap ( room1 , room2 )
END
END
27
;
limitquery ( gg ) = gg GOODS THEN pp := limit ( gg ) END
pp
PRE
END MACHINE Customer SEES Price , Goods , Limit VARIABLES purchases INVARIANT purchases GOODS INITIALISATION purchases := {} OPERATIONS pp buy ( gg ) = PRE gg GOODS price ( gg ) limit ( gg ) THEN purchases := purchases { gg } pp pricequery ( gg )
END
END
Exercise 11.2 change ( nn ) = PRE nn PERSON nn male female THEN IF nn male THEN female := female { nn } male := male { nn } ELSE male := male { nn } 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
alternative would be to accept married nn as well as unmarried, and update the function marriage by removing nn from it. sexchange ( nn ) = PRE nn male female nn dom ( marriage ) nn ran ( marriage ) THEN change ( nn )
END
Exercise 11.3 MACHINE Voters USES Life SETS RESPONSES = { listed , notlisted } VARIABLES voters INVARIANT voters male female INITIALISATION voters := {} OPERATIONS addvoter ( nn ) = PRE nn male female THEN voters := voters { nn }
END
resp
PRE
voterquery ( nn ) = 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 ) =
29 PRE THEN
nn male female
die ( nn ) removevoter ( nn ) 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 ) = PRE nn PERSON nn ( male female ) ss SEX THEN born ( nn , ss ) IF ss = boy THEN status ( nn ) := bachelor ELSE status ( nn ) := spinster
END END
death ( nn ) = PRE nn PERSON nn male female THEN dies ( nn ) 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 END END
marry ( mm , ) = PRE mm male mm dom ( marriage ) female ran ( marriage ) THEN wed ( mm , )
30
+ status := status < { mm married , married }
END
divorce ( mm , ) = PRE mm male female mm marriage THEN part ( mm , ) + status := status < { mm divorced , divorced }
END
ss
PRE
END
31
ran(aa) = orders
ll seq() ran(ll) = orders ii, jj . (ii : dom(ll) jj dom(ll) (ii < jj ll(ii) < ll(jj )
REFINEMENT PlayerR REFINES Player VARIABLES teamr INVARIANT teamr 1 . . 11 PLAYER ran ( teamr ) = team PLAYER INITIALISATION teamr : 1 . . 11 OPERATIONS substitute ( pp , rr ) =
BEGIN
teamr ( teamr
END
( pp ) ) := rr
;
query ( pp ) =
aa
IF pp ran ( teamr )
aa := in ELSE aa := out
THEN END
END The second renement 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 ) =
BEGIN
;
query ( pp ) = aa := teamr ( pp )
aa END
Exercise 12.3 In the abstract machine: jumpqueue ( ss , qq ) = PRE ss SHIP ss ran ( waiting ) ss ran ( docked ) qq QUAY qq dom ( docked ) THEN docked ( qq ) := ss
END
33
REFINEMENT JobshopR REFINES Jobshop VARIABLES jobarr INVARIANT jobarr 1 . . limit JOB ran ( jobarr ) = jobs INITIALISATION jobarr := {} OPERATIONS take ( jj ) = ANY tmp WHERE tmp 1 . . limit tmp dom ( jobarr ) THEN jobarr ( tmp ) := jj
END
jj
process = ANY tmp WHERE tmp dom ( jobarr ) THEN jj := jobarr ( tmp ) ; jobarr := { tmp } jobarr
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 ) =
BEGIN
jj
BEGIN
END
34
REFINEMENT BoothR REFINES Booth VARIABLES reserved , ticketsr INVARIANT ticketsr SEAT CUSTOMER cc . ( cc CUSTOMER card ( ticketsr
1
[ { cc } ] ) [ { cc } ] ) + reserved ( cc ) ) ticketsr := {}
= card ( tickets
reserved ( cc ) := reserved ( cc ) + nn ANY ss WHERE ss SEAT card ( ss ) = nn ss dom ( ticketsr ) = {} THEN ticketsr := ticketsr ss { cc }
END 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 renes 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 = = [skip][cols := cols {cc}](red cols) red (cols {cc}) red cols I J P (= J )
cc query: [S 1[out /out ]][S ]J = = = = [cc := red][cc : cols](red cols cc = cc) ( cc . cc cols (red cols red = cc)) cc . (cc cols (red cols red = cc)) red cols I J P (= J )
change: This operation has no outputs: [S 1][S ]J = [skip][cols : (COLOUR) {cols}](red cols)
36
= = =
( cs . (cs (COLOUR) {cols} (red cs))) cs . (cs (COLOUR) {cols} red cs) 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 renement 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 renement 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 = 1..22 ran(teamr = team)) 1..22) ( nn . (nn 1..11 | nn) 1..11
ran( nn . (nn 1..11 | nn) = 1..11 (which is true) The proof obligation for substitute is I J P [teamr (teamr 1(pp)) := rr ] [team := team {rr } {pp}] (teamr 1..11 = I J P
+ (teamr < {teamr 1 (pp) rr } 1..11 + ran(teamr < {teamr
(which is true) The proof obligation for query is I J [ IF pp ran(teamr ) THEN aa := in ELSE aa := out END ] [ IF pp team THEN aa := in ELSE aa := out END ] (J aa = aa)
37
I J J (pp ran(teamr ) pp team in = in pp ran(teamr ) pp team out = in pp ran(teamr ) pp team in = out pp ran(teamr ) pp team out = out )
(and this is true, since J implies ran(teamr ) = team.) Exercise 14.3 No, it is not possible. If ColoursR is in the state colour = blue, then this is related to four states of Colours, including {blue} and {blue, green}. In the rst case, alter will result in the state {blue, red} and in the second case {green}. Thus any possible resulting state of alter in the renement ColoursR must match both of these states, since it must rene alter called from either of them. But this is not possible, since there is no resulting value for colour which is in both sets. Exercise 14.4
REFINEMENT Colours2R REFINES Colours2 VARIABLES in , out INVARIANT in cols out COLOUR ( cols COLOUR out COLOUR cols ) in out INITIALISATION in := red out := blue OPERATIONS add ( cc ) = BEGIN IF cc = out THEN out : COLOUR { in , out } END cc inquery = cc := in ; cc outquery = cc := out ; change = skip ; invert = VAR tt IN tt := in ; in := out ; out := tt
END
END
END
38
39
4. (r + (q b) = a r > b r = ) [q := q + 1; r := r b](r < ) 5. [r := a; q := 0](r + (q b) = a) The rst and the fth 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. Thus the loop should be as follows: r := a; q := 0; WHILE r b DO q := q + 1; r := r b VARIANT r END Since the invariant must be true when the loop is started, it requires that a
INVARIANT r b 1 r + (q b) = a
b 1 .
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 n
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
40
Exercise 15.6 We rst calculate [ IF i = 0 THEN rep := FALSE ELSE rep := TRUE END ](rep = TRUE p ran(a)) = = (= i = 0 (FALSE = TRUE p ran(a)) i 0 (TRUE = TRUE p ran(a)) (i = 0 p 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 a[(i + 1)..N ] i a[(i + 1)..N ] i )
3. (p a[(i + 1)..N ] i i
These are all straightforward to establish, except the second, which bears closer examination: (p a[(i + 1)..N ] i (i > 0 a(i) p)) = = i = 0 p a[(i + 1)..N ] a(i) = p p a[(i + 1)..N ] i = 0 p ran(a) a(i) = p i 0 p ran(a) P (p a[(i + 1)..N ] i (i = 0 a(i) = p))
Thus the postcondition of the loop is established. Exercise 15.7 i := 1; j := 1; WHILE a(i) b(j ) DO IF a(i) < b(j )THEN i := i + 1ELSE j := j + 1END INVARIANT ran(a (i 1)) ran(b (j 1)) {} x . (x dom(a) x size(a) a(x) x . (x dom(b) x size(b) b(x) VARIANT size(a) + size(b) i j END a(x + 1)) b(x + 1))
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
We must establish that I J P [S 1[out /out ]][S 1]J , where S 1 and S are the bodies of the implementation and specication respectively of add.
[ VAR nn IN nn number ;
IF nn < cap THEN rr := ok; input (ee); inc ELSE rr := failed END
END ]
THEN rr := ok; input (ee); inc ELSE rr := failed END (size(queue) < cap (counter = size(contents) contents = queue ee rr = ok) size(queue) = cap (counter = size(contents) contents = queue rr = failed) 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) cap ( counter = size(contents) contents = queue rr = failed) [ VAR nn IN nn := counter ;
43
counter < cap (size(queue) < cap ( counter + 1 = size(contents ee) contents ee = queue ee ok = ok) size(queue) cap ( counter + 1 = size(contents) contents ee = queue ok = failed)) counter cap (size(queue) < cap ( counter = size(contents) contents = queue ee failed = ok) size(queue) cap ( counter = size(contents) contents = queue failed = failed))
counter < cap size(queue) < cap (counter + 1 = size(contents ee) contents ee = queue ee) counter cap size(queue) cap (counter = size(contents) contents = queue)
END
IMPLEMENTATION RussianMultI REFINES RussianMult IMPORTS RussianBody OPERATIONS rr mult ( aa , bb ) = VAR xx , yy , total IN xx := aa ; yy := bb ; total := 0 ; WHILE xx > 0 DO xx , yy , total body ( xx , yy , total )
total + xx yy = aa bb xx
yy total
xx
tt := ss + yy END
dd := xx / 2 ee := yy 2
END
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 = 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
VARIANT END END END
[ { xx } ] )
MACHINE Heaparray ... rr siftup ( ii ) = PRE ii 2 . . size ( heaparray ) THEN IF heaparray ( ii / 2 ) > heaparray ( ii ) + THEN heaparray := heaparray < { ii / 2 heaparray ( ii ) , ii heaparray ( ii / 2 ) } rr := TRUE ELSE rr := FALSE
END END
46 THEN ANY
pp
WHERE
pp ii . . jj ii . . jj nn . ( nn ii . . jj 1 pp ; aa ( nn ) pp ; aa ( nn + 1 ) ) + THEN aa := aa < ( pp ; aa )
END
END
array )
END VAR
cc , nn IN cc := ii 1 ; WHILE cc < jj DO cc := cc + 1 ; nn extract ; set ( cc , nn ) INVARIANT cc cc cap 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
aa )
END END
END
47
IMPLEMENTATION SizeCounterI REFINES SizeCounter IMPORTS sze Nvar ( maximum ) INVARIANT sze Nvar = sze INITIALISATION sze STO NVAR ( 0 ) OPERATIONS szeinc = sze INC NVAR ; szedec = sze DEC NVAR ; ss szeget = ss sze VAL NVAR END
Exercise 18.2 MACHINE Checkouts ... OPERATIONS closeandmove ( co1 , co2 ) = PRE co1 COUNTER co2 COUNTER THEN opencounters := opencounters { co1 }
+ queues := { co1 } queues < { co2 ( queues ( co2 )
queues ( co1 ) ) }
END
... IMPLEMENTATION CheckoutsI ... closeandmove ( co1 , co2 ) = 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
...
48
;
Implementation:
jumpqueue ( co , cu ) = 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
cc . ( cc dom ( queues ) | ran ( queues ( cc ) ) ) THEN rep := TRUE ELSE rep := FALSE
END END
IF cu
;
Implementation:
rep
VAR
present ( cu ) = 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 VARIANT nn
END
rep := ans
END
49
Exercise 18.5 mm maximum = 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
VAR
mm := msf
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 ) = VAR bb , pp IN bb , pp Baskets CRE SET OBJ ; set ( cu , pp )
END
nn
VAR
50
ll Baskets CRD SET OBJ ( pp ) ; ii := 0 ; total := 0 ; WHILE ii < ll DO ii := ii + 1 ; vv Baskets VAL SET OBJ ( pp , ii ) ; total := total + price ( vv )
INVARIANT
END