CS 641 meeting -*- Outline -*- * Weakest preconditions (Hesselink ch. 1) command language (straight-line) and semantic framework semantics of a boolean expression is a boolean function on state space. ** predicates and predicate transformers (1.0 and 1.1) *** predicates a predicate is a boolean-valued function. a predicate transformer is a function from predicates to predicates such as wp or wlp. -------------------- PREDICATES def: X is the *state space* of a computer program (a set). Elements x \in X are *states*. def: |B = {true, false}. def: |P = X -> |B is the set of boolean functions on state space, Elements p \in |P are *predicates*. -------------------- note a predicate is not a syntactic thing, but the meaning of such. The italicized *false*, *true* \in |P are constant functions. Extend boolean operators and quantifiers to predicates pointwise. e.g., (p /\ q).x =def= p.x /\ q.x (all i \in I :: p.i).x =def= (all i \in I :: p.i.x) *** everywhere operator ------------------- EVERYWHERE OPERATOR def: Let p \in |P be a predicate. [p] =def= (all x \in X :: p.x) examples: [~(3 = 4)] [i < 3] ------------------- (these examples aren't quite right, have to take meaning of syntax...) example: [~(3 = 4)] means that in all states, x, ~(3 = 4) holds. [i < 3] means that in all states, x, i is less than 3. Q: what does [(exists i \in Nat :: b.i > 3)] mean? Q: what does (exists i \in Nat :: [b.i > 3]) mean? Compare? Q: What does [false] mean? **** equality of predicates ------------------- def (equality of predicates): Let p, q \in |P. p = q iff [p equiv q]. -------------------- hence p = q if and only if (all x \in X :: p.x equiv q.x) so predicates are equal if they have the same value in all states. Q: What is the connection between ~(p = true) and (p = false)? Suppose p is (i > 3), then ~(p = true) and ~(p = false) Q: Can you prove that (p = false) ==> ~(p = true)? So there are many predicates, not just true and false **** examples, theorems Thms (from section 1.9): [true] equiv true [p /\ q] equiv [p] /\ [q] [(all i \in I :: q.i)] equiv (all i \in I :: [q.i]) Q: can you prove this last one? discuss the role of states in such proofs. Note that (all x \in X :: (p equiv q)) equiv [p equiv q], so can ignore everywhere around the outside? Q: What is the connection between ~[p] and [~p]? [~p] ==> ~[p] \/ ~(exists x :: x \in X) ~[p] \/ ~(exists x :: x \in X) equiv { def of everywhere operator } ~(all x : x \in X : p.x) \/ ~(exists x :: x \in X) equiv { deMorgan } (exists x : x \in X : ~p.x) \/ ~(exists x :: x \in X) <== { trading and instantiation, twice } (x \in X /\ ~p.x) \/ ~(x \in X) equiv { excluded middle } ~(x \in X) \/ ~p.x equiv { connection between ~ and ==> } x \in X ==> ~p.x <== { instantiation } (all x :: x \in X ==> ~p.x) equiv { def of everywhere operator } [~p] However, it's quite reasonable to assume that X is not empty as we'll see. Q: What is the connection between ([p] \/ [q]) and [p \/ q]? [p] \/ [q] ==> [p \/ q] Also: [[p] \/ q] ==> [p \/ q] Q: What is the connection between ([p] ==> [q]) and [p ==> q]? [p ==> q] ==> ([p] ==> [q]) Q: What is the connection between ([p] equiv [q]) and [p equiv q]? [p equiv q] ==> ([p] equiv [q]) This is particularly important for translating formulas from propositional calculus to everywhere operator. Example: Excluded middle law is ~p \/ p equiv true So (by [true] equiv true) [~p \/ p equiv true] And thus by this law [~p \/ p] equiv [true] Note, however, that [~p] \/ [p] = true is invalid! Q: is ~[p] \/ [p] equiv true? Similarly [p \/ q] equiv [p] equiv [q] equiv [p /\ q] etc. Other theorems: [[p]] equiv [p] (exists p \in U :: [p]) ==> [(exists p \in U :: p)] *** predicate transformers ------------------- PREDICATE TRANSFORMERS def: a function f: |P -> |P is a *predicate transformer* -------------------- Q: examples? Liebniz: p = q ==> f.p = f.q i.e., [p equiv q] ==> [f.p equiv f.q] -------------------- def: for predicates p and q, p is *stronger than q iff [p ==> q] -------------------- (note that the everywhere operator is used to lift ==>) Q: What does weaker mean for predicates? Q: what's the strongest predicate? -------------------- def: a transformer f: |P -> |P is *monotone* iff for all p,q \in |P, [p ==> q] ==> [f.p ==> f.q] --------------------- compare monotone functions to monotone functions in denotational semantics, to homs of ordered sets... example: let v:int be the only variable, so can represent X as { x | x.v \in Int } let f.p.x = p.(x.v + 1) /\ (x.v > 0) Q: can you prove f is monotone? ** weakest preconditions (1.2) informally: a *precondition* is just a predicate. wp.c.p is the *weakest precondition* such that every execution of c terminates in state where p holds wlp.c.p is the *weakest liberal precondition* such that every execution of c terminates in state where p holds or does not terminate. Q: what is wp.(do ~(j = 0) -> j := j-1 od).(~(j = 0))? Q: what is wlp.(do ~(j = 0) -> j := j-1 od).(~(j = 0))? but our aim is to formalize these, so we will axiomatize them, instead of relying on these defs. *** axioms -------------- AXIOMS FOR PREDICATE TRANSFORMERS {wp.c.p is stronger}: [wp.c.p ==> wlp.c.p] {wp.c is monotone}: [p ==> q] ==> [wp.c.p ==> wp.c.q] {wlp.c is monotone}: [p ==> q] ==> [wlp.c.p ==> wlp.c.q] --------------- *** example let *serve* be defined by wp.serve.p.x = (exists y \in X :: p.y) wlp.serve.p.x = true Q: what does this do? can you implement it? *** semantic equality ----------------- SEMANTIC EQUALITY def: commands c and d are *semantically equal*, written c =~= d, iff (wp.c = wp.d) /\ (wlp.c = wlp.d) ------------------ why? want (skip [] abort) to differ both from skip and abort. the notation c = d is used for defintions, and syntactic equality. ** guards, assertions, termination, and totality (1.3) Operational idea: a command can either: refuse to execute, go forever, produce a new state. can imagine the mechanism asking a command whether it wants to execute, and then doing it. relational semantics: a command is a set-valued function on states (binary relation), c(x) = {} (means refuses to execute in state x) c(x) = \bot (means goes forever in state x) c(x) = {x',x''} (can either get to x' or x'' from x) *** guards ---------------- GUARDS form: ?b examples: ?(x < 3), ?(x = 3) axioms: wp.(?b).p = (b ==> p) wlp(?b).p = (b ==> p) ----------------- just test state, don't execute if the predicate isn't true. note that ?b is not a total command, a given initial state only has a final state if b is true of the initial state. usefulness of ?b: if b then c else d fi =~= (?b;c) [] (?~b;d) *** assertions --------------- ASSERTIONS form: !b examples: !(x < 3), !(x = 3) axioms: wp.(!b).p = (b /\ p) wlp(!b).p = (b ==> p) --------------- checks if b holds, abort if it doesn't. usefulness of !b: program abort by !false used to write assertions into programs instead of as comments. *** special cases skip = ?true so skip =~= !true abort = !false miracle = ?false miracle is also called Fail [Nelson] and magic [Back & von Wright] Q: do our wp laws for skip and abort hold? Q: what is wlp.skip.p? wlp.abort.p? wp.miracle.p? wlp.miracle.p? (put on board) Q: how is miracle miraculous? {q} miracle {p} holds for all q,p. e.g., {true} miracle {3 = 4} here's where the operational idea starts to break down... *** termination def: command c is *necessarily terminating* iff [wp.c.true] (i.e., wp.c.true = true, for all states x) Q: is skip? abort? miracle? assignment? havoc? *** totality for a state x wp.c.false.x means every computation starting in x terminates in a state where false holds, i.e., since no such states, no computations start at x, so c is not defined at x. a command c is *defined* in state x iff ~wp.c.false.x def: command c is *total* iff [~wp.c.false] Q: can you prove that (?b is total) equiv (b = true)? *** summary It's helpful to think about Hesselink's language as a two-dimensional space. ------------------------------------------ !false = abort abort[]miracle ! ! ! less !!(odd(i)) termin.! ! ! ! ?(odd(i)) miracle !true !_____________________= =skip=?true ?false less defined (total) ------------------------------------------ nondeterminate choice (see below) is a way of combining commands with varying levels of termination and totality. At the bottom left are commands guaranteed to terminate that are also total ** composition and nondeterministic choice (1.4) *** sequential composition --------------- SEQUENTIAL COMPOSITION form: c;d example: x:=1; y:= 2 axioms: wp.(c;d).p = wp.c.(wp.d.p) wlp.(c;d).p = wlp.c.(wlp.d.p) i.e., wp.(c;d) = wp.c o wp.d wlp.(c;d) = wlp.c o wlp.d --------------- Q: can you verify the laws of wp and wlp for these? *** nondeterminate choice ---------------------- NONDETERMINATE CHOICE form: c[]d example: x:=1 [] x:=2 axioms: wp.(c [] d).p = wp.c.p /\ wp.d.p wlp.(c [] d).p = wlp.c.p /\ wlp.d.p ---------------------- Q: why these axioms? binding power of [] is lower than that of ; generalized to a quantifier: when C is not empty: ([] c \in C :: c) is such that for wg in wp,wlp wg.([] c \in C :: c).p = (all c \in C :: wg.c.p) Assumption: assume C is not empty whenever mentioned in this context Q: can you develop the semantic of angelic and demonic choice? __ angelic: c \/ d always terminates if either c or d always does; has all the computations of c and d but can loop forever only if both can loop forever __ e.g., skip \/ abort =~= skip execution: run both c and d in parallel (on copies of the state), use the state of the first one that terminates. as a relation on states: angelic(c,d).x = { y | (~(y = \bot) /\ (y \in c.x \/ y \in d.x)) \/ (y = \bot /\ (\bot \in c.x /\ \bot \in d.x))} demonic: c /\ d always terminates if both c and d always do; -- has all the computations of c and d, but cannot terminate when one must loop forever. e.g., skip /\ abort =~= abort -- execution: run c and d until they both terminate (on copies of state), pick one final state. Q: as a relation on states, what is demonic(c,d).x? wp.angelic(c,d).true = wp.c.true \/ wp.d.true wp.angelic(c,d).p = wp.angelic(c,d).true /\ wlp.angelic(c,d).p wp.demonic(c,d).true = wp.c.true /\ wp.d.true wp.demonic(c,d).p = wp.demonic(c,d).true /\ wlp.angelic(c,d).p Q: What are the wlps? *** semantics is compositional Thm: c0 =~= c1 /\ d0 =~= d1 ==> c0;d0 =~= c1;d1 /\ c0[]d0 =~= c1[]d1 ** conditionals (1.5) if b then c else d fi =~= ?b;c [] ?~b;d proof: for wg in wp,wlp, and p \in |P, if b then c else d fi =~= ?b;c [] ?~b;d = {standard def} (b ==> wg.c.p) /\ (~b ==> wg.d.p) Q: can you continue from here? Q: can you express Dijkstra's if using guards? if =~= !(exists i \in I :: b.i); ([] i \in I :: ?b.i;c.i) Conversely: ?b =~= if b -> skip [] true -> miracle fi !b =~= if b -> skip fi ([] c \in C :: c) =~= if [] c \in C :: true -> c fi Hesselink uses ? and ! because they are simpler and have better algebraic properties. ** program variables, state functions, and localized relations (1.6) In programming state space is a mapping from var names to values. *** program variables def: V is set of variable names. def: T is set of values (union of all types used in program) Then the state space X = V -> T. (i.e., the state space is a set of environments, or a store...) Q: What is X if V is empty? has one element, empty function. =V (with V written as a subscript) means identity of variable names *** state functions a variable's value in a state defines a function: X -> T so does a predicate. Hence, def: a *state function* is a map X -> T **** construction of state functions constuct state functions by lifting constants, variables and operators to state functions. ----------------- CONSTRUCTION OF STATE FUNCTIONS Abstract syntax: f,g in State-function-syntax t in constant v in variable = V (+) in binary-operator-syntax f ::= t | v | f (+) g meaning: State-function-syntax -> (X -> T) example: meaning.(i < j).x = x.i < x.j meaning.t.x = constMeaning.t meaning.v.x = x.v meaning.(f (+) g).x = (meaning.f.x) opMeaning.(+) (meaning.g.x) where opMeaning: binary-operator-syntax -> (T * T -> T) a (opMeaning.-) b = a - b a (opMeaning.*) b = a * b etc. constMeaning: constant -> T constMeaning.i = i ------------------ Hesselink drops the functions: meaning, constMeaning, opMeaning. This is called pointwise extension, or *localized interpretation* For relating functions, Hesselink uses global interpretation so for functions, f = g means (all x :: f.x = g.x) if used localized interpretation, would have to write [f = g] for f = g. Q: what's the relation of a state function to a PL expression? it's the semantics of it by the invisible brackets, it's the expression of a state fun. Q: is a state function total? can it have side-effects? narrowly yes, because defined everywhere, but could model partial functions by using \bot \in T and defining operators on T. no side effects, since doesn't return new state Q: is a state function deterministic? narrowly no but could model nondeterminism if T was a set of sets This is a way of avoiding problems that crop up in real languages, or put another way, it doesn't treat the hard cases... (but ok, since we're not working on verification) ** assignment (1.7) ---------------- ASSIGNMENT form: v := f where v in V, f in X -> T examples: i := 3; j := j + 1 def (state update): The update of state x at location v to value f.x is (v <- f).x, which is defined by: (v <- f).x.v = f.x (v <- f).x.w = x.w if ~(w =V v) Hence, for wg in wp, wlp: wg.(v:=f).p.x = p.((v <- f).x) i.e., wg.(v:=f).p = p o (v <- f) ---------------- Note that, semantically, f is total, and pure. Notation: textual substution v p means p with f substituted for free occurrences of v f Same as Cohen's p(v:=f) Thm (substitution rule): Let p be a predicate expression (satisfying grammar for f). Then for wg in wp, wlp, v wg.(v:=f).p = p f do the proof? ** deterministic choice (1.8) used to model procedures a deterministic choice is a choice that is determined by the value of a state function (e.g., by a variable's value) like a function call with state function as actual parameter because the value (of the parameter) determines what to do. example: ([] t \in Nat :: i := t+1) is a command that assigns to i a positive integer ([] t \in Nat :: ?(f = t); i:=t+1) =~= i := f+1 so can model procedure that puts f+1 in i as q.f = ([] t \in Nat :: ?(f = t); i := t+1) def: Let I \subseteq T be a type. Let (t \in I :: q.t) be a family of commands, want to treat this family as a procedure with formal param t. Let f: X -> I be an I-valued state function (the actual). Then the call q.f is defined by q.f = ([] t \in I :: ?(f = t);q.t) Note: the call q.f is defined for all f, but only does something sensible when f takes a value in I The advantage of this coding is that we can manipulate it. Q: what's this in terms of an if? q.f = if [] t \in I :: (f = t) -> q.t fi example (for loops): for i := 0 to f do q.i od modeled by ?(f<0) [] ([] i \in Nat :: ?(f=i); r.(i+1)) where r.0 = skip r.(i+1) = r.i; q.i for i \in Nat ** appendix on pred calc. (Skip because already did Cohen, but tell students to pay attention to the everywhere operator.)