Model solutions for hw3. ------------------------------------------ 11.12 1. Show P is true b4 execution of the loop begins. It will suffice to show wp(q,r:=0,x;,P) => (x>=0 ^ 0 < y) = T wp(q,r:=0,x;,P) = 0 <= x ^ 0 < y ^ 0 * y + x = x = x >= 0 ^ y > 0 ^ T = x >= 0 ^ y > 0 which is identical to the consequent so the implication holds. 2. Show that {P ^ Bi}Si{P}, for 1 <=i<=n. For our case, n=1 and it will suffice to show P^B1 => wp(S1,P) = T. P^B1=(0<=r ^ 0=y) wp(r,q:=r-y,q+1,P) =0<=r-y ^ 0=y in the antecedent. 3. Show that P^~BB=>R. P^~BB =(0<=r ^ 0=y) = (0<=r ^ 0(t>0) t=r so it will suffice to show P^BB=>(r>0). P^BB = (0<=r ^ 0=y y>0 and r>=y => r>0. 5. Show that {P^Bi}t1:=t;Si{twp("t1:=t,S1",t=y wp("t1:=t,S1",tr-y0. ------------------------------------------ 14.1d { P ^ ( 0 < a + 1 < b ) ^ a = A ^ b = B } c = (round(a + b)/2 ); if c^2 <= n -> a := c [] c^2 > n -> b := c fi { P ^ half(a, b, A, B, round((a+b)/2) } Where half is the predicate half(a, b, x, y, z) = { ( a = x ^ b = z v a = z ^ b = y ) ^ ( abs((z - x) - (y - z)) <= 1 ) } The preservation of P is evident from checking the two guarded statements. The half predicate expresses the requirement that the two half intervals be within one of each other in length. It's truth after the command is evident after manipulating the abs() expression in the definition of half a bit (and after textual substitution of A, B, c for x, y, z) abs((c - A) - (B - c)) <= 1 ) } = abs(2c - (A + B)) = 2*abs(c - ((A+B)/2) <= 2*1/2, since c is a rounding of (A + B)/2 = 1. ----------- 14.1d some more ------------- Also informative is this solution which is wrong for the given def, but would be correct if the definition of halving were that number of integers in interval, b+1 - a, be no more than half the original number of ints, rounded up, ceil((B+1-A)/2). Let P be the condition a^2 <= n < b^2. With initial condition {Q: P ^ ( 0 < a + 1 < b ) }, assign either a or b to round( (a + b)/2 ), while achieving an interval a:b half the original in length. (for 'round(), using some rounding strategy such as floor, ceiling, nearest even integer, etc.) Solution: I'm not 100% sure what the author means by (a + b)/2 in the case that a + b is odd, so I'll write an if statement that allows for any particular rounding strategy and afterwards discuss the possibilities. Since either a or b is to be assigned, an IF with two guarded commands is called for. The first question is what guards to put for B_1 and B_2. in the if statement below. I've also initially assigned the interval length to t1 so that the postcondition can discuss whether it has been "halved". t1 doesn't really need to be a program variable. In the condition on interval length halving, I decided to be generous and allow rounding up, so that, for example, with initial interval length 5 it would be sufficient to reduce the length to 3. { P ^ ( 0 < a + 1 < b ) } t1 := b+1 - a; if B_1 -> a := round(a+b)/2 [] B_2 -> b := round(a+b)/2 fi { P ^ ( b+1 - a <= ceil(t1/2) ) } To preserve P, the obvious guards are B_1 = (round(a + b)/2 )^2 <= n B_2 = (round(a + b)/2 )^2 > n Note that there is really no choice in the guards. And then it is evident that P ^ ( 0 < a + 1 < b ) -> BB, so the burning question remains: is the interval halved? Try floor, ceiling, etc. When the interval length is 3, everything seems fine. How about an interval of length 4? Nothing works. Why? Consider this case: a = 0, n = 1, b = 3. The interval length is 4. Before rounding, (a + b)/2 is 1.5. To halve the interval, we would have to set a := 2 or b := 1, both of which violate P. To maintain P we would have to set a := 1 or b := 2, both of which violate halving. Aha: trying to write the program, and considering the form it should take led me to a simple counterexample that shows the problem is unsolvable and that the issue is not really about rounding strategies at all. This has implications for design of a loop for computing integer square root. ------------------------------------------ 15.1.3 {0 i, x:= i+1, b[i] [] b[i]>=x -> i := i+1 fi od Note: an instance of the least value is stored in x. When there is more than one, which instance you get is nondeterministic. An ordering <= is called a "strict weak ordering" if it is possible for a <= b and b <= a with a and b distinct (but the ordering transitive (a <= b ^ <= c -> a <= c) and total (a <= b v b <= a)). For instance consider struct foobar { string name; int number; }; bool operator<=(const foobar& a; const foobar& b) { return a.name <= b.name; } This <= operator on foobar's is a strict weak ordering since several foobars with different numbers may have the same name. The C++ standard template library contains many generic functions that only depend on the strict weak order property when manipulating the data. ------------------------------------------ 15.2.5 v:=0; do j!=80 cand b[j]!='' -> v,s[v],j:=v+1,b[j],j+1 [] j=80 -> read(b); j:=0 od ------------------------------------------ 14.2 ...