1. Modify the program developed in class for the Maximum Segment Sum problem (see the relevant web page) so that, in addition to the variable z, there are two other "output" variables, left and right, which (when the program completes execution) satisfy the condition that A[left..right) is a segment with the maximum sum.
It is important not only to modify the program correctly but also to modify the postcondition and loop invariant properly, i.e., so that items (i) and (ii) on the loop checklist are provable. Obviously, both the postcondition and loop invariant need to mention S.left.right (i.e., the sum of the elements in array segment A[left..right)). Solutions that include a proof of (ii) will be looked upon favorably relative to those that don't.
It may make your task easier if you consider that the assignment commands y := (y + A.r) max 0 and z := z max y that appear in our Maximum Segment Sum solution are equivalent to selection commands as indicated here:
Assignment Command | Equivalent Selection Command |
---|---|
y := (y + A.r) max 0 | if y + A.r ≥ 0 ⟶ y := y + A.r [] y + A.r ≤ 0 ⟶ y := 0 fi |
z := z max y | if z ≥ y ⟶ skip [] z ≤ y ⟶ z := y fi |
For a few bonus points, have your program ensure that A[left..right) is a shortest segment with the maximum sum. In other words, any segment having shorter length must also have a smaller sum. Of course, this additional requirement calls for an additional conjunct to appear in both the postcondition and loop invariant.
3. Prove the correctness of the following program, which sorts an array. (Do you recognize which sorting algorithm it is based upon?) Because it is obvious that items (iii), (iv), and (v) on the loop checklist are satisfied, all you need to show are items (i) and (ii). (Regarding (ii), all you need to consider is the line of code that swaps two array elements, as is explained below.)
|[ con N : int { N≥0 } ;var b : array[0..N) of T { b=B } ;var k, m : int ;k := 0 {I: inOrder(b,0,k) ∧ boundary(b,k) ∧ 0≤k≤N ∧ perm(b,B)} {t: N-k} do k ≠ N ⟶ {I ∧ k≠N} m := locOfMin(b,k,N); {I ∧ k≠N ∧ k≤m<N ∧ (∀j | k≤j<N : b.m ≤ b.j) } ;swap(b,k,m); {I(k:=k+1)} ;k := k+1 {I} od {Q: inOrder(b,0,N) ∧ perm(b,B)} ]|where inOrder(f,p,q) : (∀i,j | p≤i≤j<q : f.i ≤ f.j) boundary(f,p) : (∀i,j | 0≤i<p ∧ p≤j<#f : f.i ≤ f.j) perm(f,g) : arrays f and g are permutations of one another |
Notes/Hints:
The command swap(a,i,j) is, in effect, the assignment a := a(i,j : a.j,a.i) and therefore (in accord with the wp assignment law) has the following semantics:
where (provided that i=j implies E=F)
a(i,j : E,F).r = | { | E | if i=r |
F | if j=r | ||
a.r | otherwise |
Using the if function, this can be written as follows:
Thus, if b'.i occurs within a quantification in which i is a dummy that varies over a range that includes neither k nor m, you can cite the Irrelevant Array Element Axiom to justify replacing that occurrence of b'.i by b.i.