COP4020 Programming Languages Introduction to Axiomatic Semantics Prof. Robert van Engelen (modified by Prof. Em. Chris Lacher) Assertions and Preconditions Assertions are used by programmers to verify run-time execution An assertion is a logical formula to verify the state of variables and data to ensure safe continuation A failed assertion should stop the program Assertions are placed by programmers explicitly in code assert (len>0); mean = sum/len; By contrast, preconditions state the initial conditions under which an algorithm has been proven correct 5/29/2016 COP4020 Fall 2006 2 Preconditions, Postconditions and Partial Correctness We will place assertions before and after a command C: { Precondition } C { Postcondition } We say that the command C is partially correct with respect to the <precondition,postcondition> specification, provided that The command C is executed with values that make the precondition true If the command terminates, then the resulting values make the postcondition true Total correctness requires termination 5/29/2016 COP4020 Fall 2006 3 Assignment Axiom If we view assertions as predicates, the assignment axiom can be stated { P(E) } V := E { P(V) } that is, if we state a property of V after the assignment, then the property must hold for expression E before the assignment We can use substitution to derive the precondition given a postcondition formula P: this is the assignment axiom: { P[VE] } V := E { P } where P[VE] denotes the substitution of V by E in P 5/29/2016 COP4020 Fall 2006 4 Examples for Assignments { k = 5 } k := k + 1 { k = 6 } (k = 6)[kk+1] (k+1 = 6) (k = 5) { j = 3 and k = 4 } j := j + k { j = 7 and k = 4 } (j = 7 and k = 4)[jj+k] (j+k = 7 and k = 4) (j = 3 and k = 4) { true } x := 2 { x = 2 } (x = 2)[x2] (2 = 2) (true) { a > 0 } a := a - 1 { a > 0 } (a > 0)[aa - 1] (a - 1 > 0) (a > 0) { false } y := 1 { y = 2 } 5/29/2016 Assuming a is int ! No state can satisfy precondition ! = partially correct COP4020 Fall 2006 5 Validity of Assignment Axiom At first glance it seems that working backward from a postcondition is more complicated than necessary and we could use { true } V := E { V = E } assignment However, consider equality { true } m := m + 1 { m = m + 1} and we find that { m = m + 1 } { false } 5/29/2016 COP4020 Fall 2006 6 Statement Composition: Sequence Axiom The sequence axiom: { P } C1 { Q } C2 { R } Q is a postcondition of C1 and a precondition for C2 Written as a rule of inference { P } C1 { Q } { Q } C2 { R } { P } C1 ; C2 { R } 5/29/2016 COP4020 Fall 2006 7 Example Sequencing We usually write the sequencing vertical and insert the assertions between the statements: {i>0} (k > 0)[ki + 1] k := i + 1; { k > 0 and j = j } { k > 0 } i := j; (k > 0 and i = j)[ij] { k > 0 and i = j } The rule of inference: { i > 0 } k := i + 1 { k > 0 } { k > 0 } i := j { k > 0 and i = j } { i > 0 } k := i + 1; i := j { k > 0 and i = j } 5/29/2016 COP4020 Fall 2006 8 Skip Axiom The ‘skip’ statement is a no-op { P } skip { P } pre- and postconditions are identical 5/29/2016 COP4020 Fall 2006 9 If-then-else Axiom The if-then-else axiom written vertically: {P} if B then { P and B } C1 {Q} else { P and not B } C2 {Q} end if {Q} 5/29/2016 COP4020 Fall 2006 10 If-then-else Axiom And as an inference rule: { P and B } C1 { Q } { P and not B } C2 { Q } { P } if B then C1 else C2 end if { Q } 5/29/2016 COP4020 Fall 2006 11 The if-then-else Weakest Precondition Rule We can derive the weakest precondition P of and if-then-else using: P (not B or P1) and (B or P2) where P1 is the precondition of C1 given postcondition Q and P2 is the precondition of C2 given postcondition Q Example: { ( x < 0 or x > 0) and (x > 0 or true) } { true } if x > 0 then {x>0} y := x else Compute preconditions { 0 > 0 } { true } P1 and P2 of C1 and C2 y := 0 end if {y>0} 5/29/2016 COP4020 Fall 2006 12 Precondition Strengthening Logical implication ( or ) means stronger condition weaker condition (more restrictive) (less restrictive) For example: 5/29/2016 x = y and y = 0 y = 0 x 0 x = 0 or x < 0 or x > 0 x=0x>0 x = y true false x = y2 COP4020 Fall 2006 13 Using Precondition Strengthening We can always make a precondition stronger than necessary to complete a proof For example, suppose we know that x > 0 and y = 2 at the start of the program: { x > 0 and y = 2} { x > 0} (y = x and y > 0)[yx] y := x (x = x and x > 0) { y = x and y > 0 } 5/29/2016 COP4020 Fall 2006 14 Loops and Loop Invariants A loop-invariant condition is a logical formula that is true before the loop, in the loop, and after the loop An common example: grocery shopping The invariant is: groceries needed = groceries on list + groceries in cart cart := empty; { groceries needed = groceries on list + groceries in cart } { groceries needed = groceries on list } while grocery list not empty do { groceries needed = groceries on list + groceries in cart and not empty list } add grocery to cart; take grocery off list; { groceries needed = groceries on list + groceries in cart } end do; { groceries needed = groceries on list + groceries in cart and empty list } { groceries needed = groceries in cart } 5/29/2016 COP4020 Fall 2006 15 While-loop Axiom The while-loop axiom uses a loop invariant I, which must be determined Invariant cannot generally be automatically computed and must be “guessed” by an experienced programmer {I} while B do { I and B } C {I} end do { I and not B } 5/29/2016 COP4020 Fall 2006 16 While-loop Example (1) Loop invariant I (f*k! = n! and k > 0) {n>0} k := n; f := 1; while k > 0 do Proof that this algorithm is correct given precondition n>0 and postcondition f=n! f := f*k; k := k-1; end do { f = n! } 5/29/2016 COP4020 Fall 2006 17 While-loop Example (2) Loop invariant I (f*k! = n! and k > 0) {n>0} k := n; f := 1; { f*k! = n! and k > 0 } while k > 0 do { f*k! = n! and k > 0 and k > 0 } Add while-loop preconditions and postconditions based on the invariant f := f*k; k := k-1; { f*k! = n! and k > 0 } end do { f*k! = n! and k > 0 and k < 0 } { f = n! } 5/29/2016 COP4020 Fall 2006 18 While-loop Example (3) Loop invariant I (f*k! = n! and k > 0) {n>0} k := n; { 1*k! = n! and k > 0 } f := 1; { f*k! = n! and k > 0 } while k > 0 do { f*k! = n! and k > 0 and k > 0 } Use assignment axioms f := f*k; { f*(k-1)! = n! and k-1 > 0 } k := k-1; { f*k! = n! and k > 0 } end do { f*k! = n! and k > 0 and k < 0 } { f = n! } 5/29/2016 COP4020 Fall 2006 19 While-loop Example (4) Loop invariant I (f*k! = n! and k > 0) {n>0} { n! = n! and n > 0 } k := n; { 1*k! = n! and k > 0 } f := 1; { f*k! = n! and k > 0 } while k > 0 do { f*k! = n! and k > 0 and k > 0 } { f*k*(k-1)! = n! and k-1 > 0 } f := f*k; { f*(k-1)! = n! and k-1 > 0 } k := k-1; { f*k! = n! and k > 0 } end do { f*k! = n! and k > 0 and k < 0 } Use assignment axioms { f = n! } 5/29/2016 COP4020 Fall 2006 20 While-loop Example (5) Loop invariant I (f*k! = n! and k > 0) {n>0} { n! = n! and n > 0 } k := n; { 1*k! = n! and k > 0 } f := 1; { f*k! = n! and k > 0 } Use precondition while k > 0 do { f*k! = n! and k > 0 and k > 0 } strengthening to prove the correctness of implications { f*k*(k-1)! = n! and k-1 > 0 } f := f*k; { f*(k-1)! = n! and k-1 > 0 } k := k-1; { f*k! = n! and k > 0 } end do { f*k! = n! and k > 0 and k < 0 } { f = n! } 5/29/2016 COP4020 Fall 2006 21 While-loop Example (6) Loop invariant I (f*k! = n! and k > 0) {n>0} { n! = n! and n > 0 } k := n; { 1*k! = n! and k > 0 } f := 1; { f*k! = n! and k > 0 } Use simplification and logical while k > 0 do { f*k! = n! and k > 0 and k > 0 } implications to complete the proof { f*k*(k-1)! = n! and k-1 > 0 } f := f*k; { f*(k-1)! = n! and k-1 > 0 } k := k-1; { f*k! = n! and k > 0 } end do { f*k! = n! and k > 0 and k < 0 } { f*k! = n! and k = 0 } { f = n! } 5/29/2016 COP4020 Fall 2006 22 Specifications A postcondition specification can by any logical formula A specification that states the input-output requirements of an algorithm is needed to prove correctness A specification that tests a violation can aid in debugging For example (precondition strengthening is disallowed): if (n < 0) p = 2; else p = n+1; k = m / (p-1); // Error when p = 1 5/29/2016 { (n > 0 or false) and (n < 0 or n = 0) } { false } if (n < 0) { false } p = 2; else {n=0} p = n+1; Means: never possible {p=1} k = m / (p-1); COP4020 Fall 2006 23