Arguing for program correctness and writing correct programs

Similar documents
Lecture Notes: Hoare Logic

Hoare Logic: Proving Programs Correct

AXIOMS OF AN IMPERATIVE LANGUAGE PARTIAL CORRECTNESS WEAK AND STRONG CONDITIONS. THE AXIOM FOR nop

Backward Reasoning: Rule for Assignment. Backward Reasoning: Rule for Sequence. Simple Example. Hoare Logic, continued Reasoning About Loops

Lecture 5 - Axiomatic semantics

Part II. Hoare Logic and Program Verification. Why specify programs? Specification and Verification. Code Verification. Why verify programs?

Hardware versus software

Mathematical Induction

Outline. Introduction. 2 Proof of Correctness. 3 Final Notes. Precondition P 1 : Inputs include

Review: Hoare Logic Rules

CITS5501 Software Testing and Quality Assurance Formal methods

Reasoning About Imperative Programs. COS 441 Slides 10

An Annotated Language

Recall our recursive multiply algorithm:

Formal Methods. CITS5501 Software Testing and Quality Assurance

CS 1110: Introduction to Computing Using Python Loop Invariants

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

Recursion and Induction

CS 161 Computer Security

Reasoning about programs

Last time. Reasoning about programs. Coming up. Project Final Presentations. This Thursday, Nov 30: 4 th in-class exercise

Qualifying Exam Languages

Complexity, Induction, and Recurrence Relations. CSE 373 Help Session 4/7/2016

Readability [Skrien 4.0] Programs must be written for people to read, and only incidentally for machines to execute.

a correct statement? You need to know what the statement is supposed to do.

1 The sorting problem

Lecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning

Specifications. Prof. Clarkson Fall Today s music: Nice to know you by Incubus

Software Architecture. Abstract Data Types

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

CS Lecture 19: Loop invariants

Semantics. There is no single widely acceptable notation or formalism for describing semantics Operational Semantics

CIS 500 Software Foundations. Final Exam. May 3, Answer key

6.170 Lecture 6 Procedure specifications MIT EECS

Verifying Safety Property of Lustre Programs: Temporal Induction

Fall Recursion and induction. Stephen Brookes. Lecture 4

Announcements. CS243: Discrete Structures. Strong Induction and Recursively Defined Structures. Review. Example (review) Example (review), cont.

Symbolic Execution and Proof of Properties

Introduction to Axiomatic Semantics

CORRECTNESS ISSUES AND LOOP INVARIANTS

Overview. A mathema5cal proof technique Proves statements about natural numbers 0,1,2,... (or more generally, induc+vely defined objects) Merge Sort

CS158 Section B Exam 1 Key

Fundamentals of Software Engineering

How invariants help writing loops Author: Sander Kooijmans Document version: 1.0

Correctness of specifications. Correctness. Correctness of specifications (2) Example of a Correctness Proof. Testing versus Correctness Proofs

Concurrent Programming Lecture 3

ASYMPTOTIC COMPLEXITY

Lectures 20, 21: Axiomatic Semantics

Verification Condition Generation

SECTION 1: CODE REASONING + VERSION CONTROL

Lecture Notes on Contracts

12/30/2013 S. NALINI,AP/CSE

Spark verification features

SECTION 1: CODE REASONING + VERSION CONTROL

Chapter 3 (part 3) Describing Syntax and Semantics

(a) (4 pts) Prove that if a and b are rational, then ab is rational. Since a and b are rational they can be written as the ratio of integers a 1

Programming Languages Third Edition

CSE 20 DISCRETE MATH WINTER

#23: Sequences March 28, 2009

SEQUENCES, MATHEMATICAL INDUCTION, AND RECURSION

Hoare Logic. COMP2600 Formal Methods for Software Engineering. Rajeev Goré

Fundamental mathematical techniques reviewed: Mathematical induction Recursion. Typically taught in courses such as Calculus and Discrete Mathematics.

Basic Verification Strategy

Program Verification. Aarti Gupta

Compositional Cutpoint Verification

Announcements. Specifications. Outline. Specifications. HW1 is due Thursday at 1:59:59 pm

Compiler Design Prof. Y. N. Srikant Department of Computer Science and Automation Indian Institute of Science, Bangalore

Testing, Debugging, and Verification

The Rule of Constancy(Derived Frame Rule)

Formal Methods of Software Design, Eric Hehner, segment 24 page 1 out of 5

SECTION 5.1. Sequences

Section 1.4 Proving Conjectures: Deductive Reasoning

What is Iteration? CMPT-101. Recursion. Understanding Recursion. The Function Header and Documentation. Recursively Adding Numbers

Warm-Up Problem. 1. What is the definition of a Hoare triple satisfying partial correctness? 2. Recall the rule for assignment: x (assignment)

Lecture 10 Design by Contract

Checking Program Properties with ESC/Java

Chapter 3. Describing Syntax and Semantics ISBN

Introduction to Axiomatic Semantics (1/2)

Unit #3: Recursion, Induction, and Loop Invariants

Chapter 3: Theory of Modular Arithmetic 1. Chapter 3: Theory of Modular Arithmetic

An Interesting Way to Combine Numbers

Formal Systems II: Applications

6. Hoare Logic and Weakest Preconditions

Specifications and Assertions

Unit #2: Recursion, Induction, and Loop Invariants

Integers and Mathematical Induction

SEQUENCES, MATHEMATICAL INDUCTION, AND RECURSION

Semantic Analysis Type Checking

Formal Specification. Objectives

THE PRINCIPLE OF INDUCTION. MARK FLANAGAN School of Electrical, Electronic and Communications Engineering University College Dublin

1 Unit 8 'for' Loops

Softwaretechnik. Program verification. Albert-Ludwigs-Universität Freiburg. June 28, Softwaretechnik June 28, / 24

CSE 331 Midterm Exam 11/9/15 Sample Solution

LECTURES 3 and 4: Flows and Matchings

Softwaretechnik. Program verification. Software Engineering Albert-Ludwigs-University Freiburg. June 30, 2011

Program Verification. Program Verification 307/434

Excerpt from "Art of Problem Solving Volume 1: the Basics" 2014 AoPS Inc.

CSC313 High Integrity Systems/CSCM13 Critical Systems. CSC313/CSCM13 Chapter 2 1/ 221

Comparing procedure specifications

CSE 417 Network Flows (pt 4) Min Cost Flows

Transcription:

Arguing for program correctness and writing correct programs Saying things about states, programs Program state s1: x=4, y=-1.5, A={ me, you, he Assertions about program states x=3 False in s1 (y=x) x>=0 True in s1 Programs connect pairs of states e.g. x := x+4 leads from s1 to a state where x is now 9 Assertions about programs {Q code {P FOR ALL STATES s,s : if Q was true in starting state s, and code finishes in state s, then R mus be true in ending state s {x>3 x := x+4 {x>6 {x>3 x := x+4 {x>10 true false (e.g.,start state when x=4) ABorgida 1 ABorgida 2 Instead of Easier notation in my lecture notes {x=3 x := x+4 {x>6 we will write // x = 3 x := x + 4 // x > 6 We use x := x+4 for the Java assignment statement x = x+4; because otherwise equality = in logical formulas is confused with = in assignment statements. Reasoning about programs in general //PREcondition: what you assume in order for the program to work correctly //POSTcondition: what you want your program to ensure/ accomplish ABorgida 3 ABorgida 4

Reasoning about assignment statements BACKWARDS! The weakest condition that holds before an assignment x := e which guarantees condition P afterwards is { P with x replaced by e // (y + x) z > (y+x)/2 y := y + x; // y z > y/2 (A condition p is weaker than q, if q implies p. e.g. y>1 implies y>0 so y>0 is weaker than y>1 ) Proof for a Hoare assertion about assignment Therefore, to prove {Q x := e {P step #1 {P with x replaced by e x := e {P step #2 >>> show Q implies {P with x replaced by e using algebra,logic //PRE y > 0 >>>> show y> 0 implies y+4=1 // y + 4 > 1 x:= 4; // y + x > 1 y := y + x; // y > 1 ABorgida 5 ABorgida 6 (Aside, only for those who care: why the rule {P x :=e {P with x replaced by e is wrong ) Try reasoning forward from PRE to POST here //PRE: y = 4 y := y + 3; // y + 3 = 4 >>> y = 4-3 // POST: y= 1 Initial state: y will be 4 in memory This would be the result of applying the forward rule But in the final state the above program y will be 7, not 1!!! (Aside, only for those who care: why Epp s way of using x old and x new does not work in general ) Try reasoning forward from PRE to POST here //PRE: y = 4 // y old = 4 y := y + 1; // y new = y old + 1 y := y + 1; // y new = y old + 1 which leaves y new = 5, not 6 as desired. One would have to go on to use ( y new ) new etc. ABorgida 7 ABorgida 8

Simple example Reasoning about Loops with Invariants //PRE: true //POST: sum = 1+...+25 Unfortunately, there is no weakest precondition for loops, which you can drive back, as for assignment. ABorgida 9 ABorgida 10 What is a loop invariant? A loop invariant INV is an assertion about relationship between program variables. It is used like P(n) in induction, but n is counting the number of times thru the loop, so it doesn t appear in our formulas. //PRE: What is assumed for the program to work <Set-up> // need INV true here [Prove Basis P(0)] while ( TEST CONDITION C) { // have INV here [assume I.H. P(k)] <Loop body> // need INV here [Prove P(k+1)] // therefore have INV here [Have proven by induction Forall n P(n) //POST: What is desired at the end (Between the top and bottom of the loop, headway is being made towards reaching the loop's goal. This might disturb (make false) the invariant. The point of Loop Invariants is the promise that the invariant will be What is a loop invariant? Augment the preceding with knowledge about how WHILE loop works by testing the loop condition //PRE: What is assumed for the program to work <Set-up> // need INV here while ( TEST CONDITION C) { // have INV here & C <Loop body> // need INV here // therefore have INV here & ( C) //POST: What is desired at the end restored before repeating the loop body each time.) ABorgida 12 ABorgida 11

Loop invariant in pictures A formal statement INV about the relationship between variables in your program. needs to be proven true just before the loop is ever run (establishing the invariant) [Induction basis] assume/have it true at the top of loop, when you enter it [Induction Hypothesis] needs to be proven true again at the bottom of the loop, after the loop body is executed (maintaining the invariant). infer at the exit from the loop it is still true! (by induction on # of times thru loop) enter loop body body body exit INV INV INV loop INV & C & C & C & C because we got into the body because we exited ABorgida 14 ABorgida 13 Simple example (cont d) //PRE: //POST: sum = 1+2+...+25 1. Think about why program works? Trace it 2. Find an INV 3. Then show post condition is implied by INV 4. Then show the loop body maintain INV (it is an invariant) 5. Then show the set-up establishes INV. Simple example guessing an invariant by tracing //PRE: //POST: sum = 1+...+25 k sum 0 0 1 1 = 0 + 1 2 3 = 0 +1 + 2 3 6 = 0 +1 + 2 + 3 Where INV belongs in this program //have PRE : << just before loop begins //need INV: sum = 0 +... + k (prove) << just after loop entry //have INV&: (sum=0+... +k)&(k 25) (assume) INV: sum = 0 +... + k << at end of loop body //need INV: sum = 0 +... + k (prove) << just after loop exit //have INV+: sum = 0+... +k) & k=25 (proven) //need POST: sum = 1+...+25 (prove) ABorgida 15 ABorgida 16

Proof obligations //PRE: true // INV: sum = 0 +... + k (prove true here) #A // INV&: sum = 0 +... + k & k 25 (assume here) #B // INV: sum = 0 +... + k (prove true here) #C // INV+: sum = 0 +... + k & k=25 (proven by now) #D //need POST: sum = 1+...+25 We will not be able to go top-down, because the assignment := rule is backwards/bottom-up. So, we will have to show #D implies POST push #C backwards through the body, and then show #B implies it push #A backwards through the initialization, and show PRE implies it ABorgida 17 i) Prove POST implied //PRE: true #1 // INV: sum = 0 +... + k (prove) #4 // INV : sum = 0 +... + k &(k 25) (assume) #5 // INV: sum = 0 +... + k (prove) #8 // INV : sum = 0 +... + k & (k=25) (have) #9 >>> show #9! #10: just substitute 25 for k, & drop 0 //POST: sum = 1+2+...+25 (prove) #10 ABorgida 18 ii) Push backward invariant in loop body using assignment //PRE: true // INV: sum = 0 +... + k (prove) // INV : sum = 0 +... + k &(k 25) (assume) ii) Push backward invariant (cont d) //PRE: true // INV: sum = 0 +... + k (prove) // INV : sum = 0 +... + k &(k 25) (assume) // sum + k := 0 +... + k // INV: sum = 0 +... + k (prove) // INV : sum = 0 +... + k & (k=25) >>> #9! #10 //need POST: sum = 1+2+...+25 // sum + (k+1) = 0 +... + (k+1) // sum + k := 0 +... + k // INV: sum = 0 +... + k (prove) // INV : sum = 0 +... +k & (k = 25) have >>> #9! #10 //need POST: sum = 1+2+...+25 ABorgida 19 ABorgida 20

iii) Prove #5 implies #6 //PRE: true #1 iv) Push INV at #4 back //PRE: true #1 // INV: sum = 0 +... + k (prove) #4 // INV : sum = 0 +... + k &(k 25) (assume) #5 >>>show #5! #6: subtract (k+1) from both sides of #6 // sum + (k+1) = 0 +... + (k+1) #6 // sum + k := 0 +... + k #7 // INV: sum = 0 +... + k (prove) #8 // INV : sum = 0 +... + k & (k=25) (have) #9 >>> #9! #10: //POST: sum = 1+2+...+25 (prove) #10 ABorgida 21 // k = 0 +... + k #3 // INV: sum = 0 +... + k (prove) #4 // INV&: sum = 0 +... + k &(k 25) (assume) #5 >>> #5! #6 // sum + (k+1) = 0 +... + (k+1) #6 // sum + k := 0 +... + k #7 // INV: sum = 0 +... + k (prove) #8 // INV+: sum = 0 +... + k & (k=25) (have) #9 >>> #9! #10: //POST: sum = 1+2+...+25 (prove) #10 ABorgida 22 iv) Push INV at #4 back (cont d) //PRE: true #1 // 0 = 0 +... + 0 #2 // k = 0 +... + k #3 // INV: sum = 0 +... + k (prove) #4 // INV&: sum = 0 +... + k &(k 25) (assume) #5 >>> #5! #6 // sum + (k+1) = 0 +... + (k+1) #6 // sum + k := 0 +... + k #7 // INV: sum = 0 +... + k (prove) #8 // INV+: sum = 0 +... + k & (k=25) (have) #9 >>> #9! #10: //POST: sum = 1+2+...+25 (prove) #10 ABorgida 23 v) Show #2 is implied by #1 //PRE: true #1 >>> show #1! #2: obviously true // 0 = 0 +... + 0 #2 // k = 0 +... + k #3 // INV: sum = 0 +... + k (prove) #4 // INV&: sum = 0 +... + k &(k 25) (assume) #5 >>> #5! #6 // sum + (k+1) = 0 +... + (k+1) #6 // sum + k := 0 +... + k #7 // INV: sum = 0 +... + k (prove) #8 // INV+: sum = 0 +... + k & (k=25) (have) #9 >>> #9! #10: //POST: sum = 1+2+...+25 (prove) #10 ABorgida 24

DONE! ABorgida 25 Identical proof for 25 replaced by N //PRE: true #1 >>>#1! #2: obviously true // 0 = 0 +... + 0 #2 // k := 0 +... + k #3 // INV: sum = 0 +... + k (prove) #4 while (k!= N) { // INV&: sum = 0 +... + k &(k N) (assume) #5 >>> #5! #6: subtract (k+1) from both sides of #6 // sum + (k+1) = 0 +... + (k+1) #6 // sum + k := 0 +... + k #7 // INV: sum = 0 +... + k (prove) #8 // INV+: sum = 0 +... + k & (k=n) (have) #9 >>> #9! #10: substitute N for k //POST: sum = 1+2+...+N (prove) #10 ABorgida 26 Can we find mistakes using invariants? Lets swap the two lines inside the loop: //PRE: //POST: sum = 1+...+25 k sum 0 0 1 0 2 1 = 0 +1 3 3 = 0 +1 + 2 4 6 = 0 + 1 + 2 + 3 INV : sum = 0 +... + (k-1) Does INV (k=25) imply POST? INV (k=25) is sum = 0+...+(25-1) which does not imply POST!! Bad program. (Proof gives you a hint on how to fix it: (k!=26) ABorgida 27 Multiplication program 1 //PRE: true // Strategy: 1. Find a reasonable INV 2. Check it guarantees POST, once the loop stops 3. Then show the loop body maintains INV 4. And then show the set-up establishes INV (Notation: on assignments, etc we will use function( int m, int n) to indicate that m and n are inputs, and will not change these.) ABorgida 29

// PRE: true y:= y + n; x:= x + 1; // Multiplication program 1 There are infinitely many (useless) loop invariants! look for something that when the loop ends guarantees the needed condition afterwards; understand how code works. (Repeated addition Trace the loop to see what values variables take, and so what conditions relate them.also ask yourself why should this program work x y n m 0 0 1 n * Conjecture: INV is (y=x*n). 2 2n 3 3n ABorgida 30 Multiplication program 1 proof pattern After guessing an invariant INV, we will fill the following pattern: >>> prove PRE implies H H) is INV established before loop? G) F) need INV E) have INV & (x!= m) >>> prove E implies D D) C) B) need INV A) have INV & (x=m) >>> prove A implies POST is INV maintained by the loop body? is POST established by INV& C? ABorgida 31 Multiplication program 1:fill in proof pattern >>> prove PRE implies H H) G) >>> prove E implies D D) C) Multiplication program 1:fill in proof pattern >>> prove PRE -> H H) G) >>> prove E implies D D) C) need y=(x+1)*n >>> prove A implies POST y=x*n & x=m y=m*n >>> A implies POST ABorgida 33 ABorgida 34

Multiplication program 1:fill in proof pattern >>> prove PRE -> H H) G) >>> prove E implies D D) need (y+n)=(x+1)*n C) need y=(x+1)*n >>> A implies POST Multiplication program 1:fill in proof pattern >>> prove PRE -> H H) G) >>> prove E implies D D) need (y+n)=(x+1)*n C) need y=(x+1)*n >>> A implies POST D is y+n=x*n+n; subtract n from both sides, leaving y=x*n E implies this. QED ABorgida 35 ABorgida 36 Multiplication program 1:fill in proof pattern >>> prove PRE -> H H) G) need y=0*n >>> E implies D D) need (y+n)=(x+1)*n C) need y=(x+1)*n >>> A implies POST Multiplication program 1:fill in proof pattern >>> prove PRE -> H H) need 0=0*n G) need y=0*n >>> E implies D D) need (y+n)=(x+1)*n C) need y=(x+1)*n >>> A implies POST ABorgida 37 ABorgida 38

Multiplication program 1:fill in proof pattern >>> prove PRE implies H H) need 0=0*n G) need y=0*n >>> E implies D D) need (y+n)=(x+1)*n C) need y=(x+1)*n >>> A implies POST True 0=0 QED Summary of approach 1. Guess at an invariant INV such that INV& Cond! POST 2. Leave blank lines between code text lines 3. Work your way up filling in the blanks using Hoare or regular logic //have PRE: >>> algebra/logic proof <intialization code> //need INV: while (Cond) { // have INV & Cond: >>> algebra/logic proof <loop body> // need INV: // have INV & Cond >>> algebra/logic proof // need POST: ABorgida 39 ABorgida 40 Summary of proof for multiplication 1 have PRE: True >>> Prove True! 0=0*n [algebra] need 0 = 0*n need y=0*n need INV: y=x*n have INV & C: y=x*n & x!=m >>> prove (y=x*n & x!=m)! y+n=(x+1)*n [algebra] need y+n = (x+1)*n need y=(x+1)*n need INV: y=x*n have INV & ~C == y=x*n & ~(x!=m) >>> prove previous line! POST [algebra] Another multiplication program 2 PRE: 0 <= m while (x < m) { trace the loop to see what values variables take, and so what conditions relate them x y 0 0 1 n 2 2n Conjecture: INV is still (y=x*n). Verify that INV /\ ~(x < m) implies y=m*n -- see next page ABorgida 41 ABorgida 42

multiplication program 2 Finding the right invariant that implies POST Conjecture: INV is (y=n*x). Verify that INV & (x < m) (y=n*x) & (x>=m) implies y=m*n OUCH! It does not! So we need to strengthen the invariant so it makes x=m. Can do so by adding (x <= m) to INV, because this together with (x>=m) yields x=m. Let INV in this case be (y=n*x) & (x <= m) multiplication program 2 proof outline PRE:??? >>> show PRE -> A A) B) C) need INV: y=x*n & x<=m while (x < m) { D) have INV & C: y=x*n & x<=m & x<m >>> show D -> D D ) E) & x<=m G)have INV & ~C: y=x*n & x<=m & ~(x < m) >>> show G -> POST (done) Then INV & (x>=m) does imply x=m, and hence y=m*n, POST ABorgida 44 ABorgida 43 multiplication program 2 push back invariant PRE:??? need y=x*n & x<=m while (x < m) { //D: have y=x*n & x<=m & x<m //>>> show D! D using algebra // D : need (y+n)=(x+1)*n & (x+1) <= m // E: need y=(x+1)*n & (x+1) <= m // F: need y=x*n & x<=m have y=x*n & x<=m & ~(x < m) multiplication program 2 push back invariant PRE:??? need y=x*n & x<=m while (x < m) { //D: have y=x*n & x<=m & x<m //>>> show D! D using algebra // D : need (y+n)=(x+1)*n & (x+1) <= m // E: need y=(x+1)*n & (x+1) <= m // F: need y=x*n & x<=m have y=x*n & x<=m & ~(x < m) y=x*n implies y+n=x*n+n; if x and m are integers, then x<m implies x+1<=m QED ABorgida 45 ABorgida 46

mult program 2 - establish INV before loop PRE: //??? >>> prove PRE -> A A // 0=0*n & 0<=m // y=0*n & 0<=m // INV:need y=x*n & x<=m while (x < m) { // now y=x*n & x<=m & x<m // need (y+n)=(x+1)*n & (x+1) <= m // need y=(x+1)*n & (x+1) <= m // need y=x*n & x<=m // now y=x*n & x<=m & ~(x < m) // So PRE needs to ensure (0<=m) ABorgida 47 PRE: true while (x <= m) { multiplication program 3 trace the loop to see what values variables take, and so what conditions relate them x y Conjecture: 0 0 INV3 is INV2: (y=n*x) & (x<=m) 1 n Verify that INV2 /\ ~(x <= m) imply y=m*n. 2 2n (y=n*x) & (x<=m) & x>m false which implies anything. But sign of something amiss ABorgida 48 PRE:??? multiplication program 3 while (x <= m) { // have INV2 & (x<=m): (y=x*n & x<=m) & x<=m // need INV: y=x*n & x<=m here INV2 & ~(x<=m): (y=x*n & x<=m) & ~(x <= m) Try to prove that INV2 is in fact loop invariant PRE:??? multiplication program 3 OOPS: Logic & algebra do not give P4->P3!!! INV2 is not a loop invariant! while (x <= m) { // INV : have y=x*n & x<=m & x<=m >>>> prove that P4 P3 using algebra // P3: need (y+n)=(x+1)*n & (x+1) <= m // P2: need y=(x+1)*n & (x+1) <= m // INV: need y=x*n & x<=m here y=x*n & x<=m & ~(x <= m) ABorgida 49 ABorgida 50

PRE:??? multiplication program 3 OOPS: Logic & algebra do not give P4->P3!!! INV2 is not a loop invariant! while (x <= m) { // INV : have y=x*n & x<=m & x<=m >>>> prove that P4 P3 using algebra // P3: need (y+n)=(x+1)*n & (x+1) <= m // P2: need y=(x+1)*n & (x+1) <= m // INV: need y=x*n & x<=m here y=x*n & x<=m & ~(x <= m) What does this program compute? y=(m+1)*n. So there should be no loop invariant to show that it computes y=m*n Programs with counter pattern k := <init> while (k!= m) {... k := k + 1 Such programs tend to make an invariant hold for a range of values from <init> to k, so that at the end of the loop, when k=m, it holds for an entire range. ABorgida 51 ABorgida 52