Semantics of the while-loop and the soundness of its Hoare-logic rule ---------------------------------------------------------------------- Recall that a loop is understood as the limit or union of its approximating loops: for W = while B do C end define W0 = alwaysloop W1 = if B then C; W0 else return W2 = if B then C; W1 else return ... W(i+1) = if B then C; Wi else return ... The results returned by W will be exactly the same ones as the union of all the results returned by the Wi's. W is the "limit" of the sequence of functions defined by the Wi's. (This same idea holds for the semantics of a recursively defined function --- such a function is the limit of a sequence of approximating functions.) The denotational semantics of the while-loop employs this idea: To keep it simple, let's omit Environments: C : Command -> Store -> Store_ C[[ while B do C end ]] = Union { wi | i >= 0 } where w0 = lam s. _|_ w(i+1) = lam s. if B[[ B ]] s : check(wi, C[[ C ]] s) else s Details: a function's _graph_ is the set of its argument, answer pairs, where the answer value is not _|_. For example, for f(n) = n+1, where n: Nat, its graph is {(0,1), (1,2), (2,3), ... (i, i+1), ...} graph(w0) = { } graph(w1) = {(s, s) | B[[ B ]]s == ff } graph(w2) = {(s, s) | B[[ B ]]s == ff } union {(s, s') | s' = C[[ C ]]s s' != _|_ and B[[ B ]]s' == ff } = {(s, s) | B[[ B ]]s == ff } union {(s, s'') | B[[ B ]]s = tt, s' = C[[ C ]s, s' != _|_, and (s', s'') in graph(w1)} ... graph(w(i+1)) = {(s, s) | B[[ B ]]s == ff } union {(s, s'') | B[[ B ]]s = tt, s' = C[[ C ]s s' != _|_, and (s', s'') in graph(wi)} So, graph(w) = union( { graph(wi) | i >= 0 } ) where w is C[[ while B do C end ]] Properties: for all i >= 0, graph(wi) defines a function. for all i >= 0, graph(wi) subset graph(i+1) for all s: Store, (s,s') in graph(w) iff there is some k such that (s,s') in graph(wk). graph(wk) defines a function. The "Union" defined at the top of this page is more precisely a _join_ operation on the lattice of functions of form, Store -> Store_ (It takes some work to formalize this, so we stick with the graphs!) ==================================== The while-loop rule: { I ^ B } C { I } ---------------------------------- { I } while B do C end { ~B ^ I } How to prove its soundness: 1) First, show for all i >= 0 that { I ^ B } C { I } ------------------------- { I } wi { ~B ^ I } using the definition of soundness I gave you last week. Here it is again: {P}f{Q} is sound iff for all s: Store, if B[[P]]s = tt and (f s) != _|_, then B[[Q]](f s) = tt. Prove by mathematical induction on the value of i: First, assume soundness of { I ^ B } C { I }. Basis step: i = 0: graph(w0) = {}, so there is no s such that w0(s) != _|_ . The result is vacuously true. Induction step: i = k+1. The induction hypothesis lets us assume soundness of the above rule for wk. We must prove, for every s: Store, if (a) B[[ I ]]s = tt and (b) (w(k+1) s) = s'', where s'' != _|_. then B[[ ~B ^ I ]]s'' = tt. (*) Recall that graph(w(i+1)) = {(s, s) | B[[ B ]]s = ff } union {(s, s'') | B[[ B ]]s = tt, s' = C[[ C ]s and (s', s'') in graph(wi)} This makes two cases to consider: (i) B[[ B ]]s = ff. This and (a) give us B[[ ~B ^ I ]]s = tt. (*) Done. (ii) B[[ B ]]s = tt, s' = C[[ C ]s, s' != _|_, and (s', s'') in graph(wk). By (a), we have that B[[I ^ B]]s = tt. By the soundness of { I ^ B } C { I }, we have B[[ I ]]s'. But (s', s'') in graph(wk), too. By the induction hypothesis on wk, we deduce that { I } wk { ~B ^ I } is sound, that is, wk(s') = s'' and B[[~B ^ I]]s'' (*). Done. 2) Now we obtain the main result: Assume { B ^ I } C { I } is sound. Show, for all s: Store, if B[[ I ]]s = tt and (w s) != _|_, then B[[ ~B ^ I ]](w s) = tt. Recall the crucial property of w : (s, s') in graph(w) iff there is some k >= 0 such that (s, s') in graph(wk). If B[[ I ]]s = tt, (w s) = s', s' != _|_, then there is some k >=0 such that (s, s') in graph(wk) as well. By the result proved in Step (1), B[[ ~B ^ I ]](wk s) = tt, that is, B[[ ~B ^ I ]]s' = tt. Done.