Lecture #8: Program Specification and Proof Rules For Program Correctness
Lecture #8: Program Specification and Proof Rules For Program Correctness
Topics 1) Formal Specification for Imperative programs 1.1) A Little Programming Language 1.2) Partial Correctness Specification 1.3) Total Correctness Specification 1.4) Auxiliary Variables in Program Specifications 1.5) Examples of various Program Specifications 2) Floyd-Hoare Logic for proving Partial Correctness 2.1) Axiom for SKIP, Assignment, Sequential commands 2.2) Rule for Precondition Strengthening 2.3) Rule for Postcondition Weakening 2.4) The Block Rule 2.5) The conditional Rule 2.6) The while Rule - Invariant 2.7) Finding Invariants
Overview
This lecture is concerned with formal specification Natural language specifications are often inconsistent ambiguous difficult to follow (long rambling sentences) cannot be reasoned about
Formal specifications
A formal specification: describes a programs effect in a mathematically precise notation Formal specifications: force the software designer to think more precisely about what the specification says provide less scope for confusion about the meaning of the specification can be used to prove the correctness of programs can be used to generate test cases Our formal notation: is based on predicate calculus applies to imperative programs is due to Professor C.A.R. Hoare of Oxford
Some Terminology
The symbols V, V1, , Vn stand for arbitrary variables. For example, X, R, Q. The symbols E, E1, , En stand for arbitrary expressions (or terms). For example, X + 1, Y!, Z The symbols C, C1, , Cn stand for arbitrary commands of our programming language which will be discussed next. The symbols S, S1, , Sn stand for arbitrary statements. These are conditions (assertions) like X < Y, X2 = 1, which can be either true or false. Note that statements are used for expressing conditions on program variables, and they are parts of specifications.
Imperative Programs
Imperative Programming Language is a kind of programming language which allows destructive assignment, eg. x := y. Examples of imperative programming languages are PASCAL, C, etc. Our litter programming language is also an imperative prog. lang. Executing an imperative program has the effect of changing the state A state consists of the values of program variables. Note that languages more complex than those described here may have states consisting of other things than the values of variables (e.g. I/O) To use an imperative program first establish an initial state i.e. set some variables to have values of interest then execute the program (to transform the initial state into a final one) One then inspects the values of variables in the final state to get the desired results
Some Examples
{ X = 1 } Y:=X { Y = 1 } this says that if the command Y := X is executed in a state satisfying the condition X = 1 i.e. a state in which the value of X is 1 then, if the execution terminates (which it does for this case) then condition Y = 1 will hold clearly this specification is true. { X = 1 } Y:=X { Y = 2 } this says that if the execution of Y := X terminates when started in a state satisfying X =1 then Y=2 will hold this is clearly false. {X = 1 } WHILE T DO SKIP { Y=2 } Note that T stands for true. this specification is true! This is because the command WHILE T DO SKIP does not terminate. (See definition 1 for the partial correctness)
10
Some Examples
[X = 1] Y:=X [Y = 1] this says that if the command Y := X is executed in a state satisfying the condition X = 1 then, the execution will terminate and the condition Y =1 will hold of the final state clearly this specification is true [X = 1] Y:=X; WHILE T DO SKIP [Y = 1] this says that execution of Y:=X; WHILE T DO SKIP terminates when started in a state satisfying X = 1 after which Y = 1 will hold this is clearly false
11
Total Correctness
Informally Total correctness = Termination + Partial correctness Total correctness is the ultimate goal Usually easier to show partial correctness and termination separately Termination is usually straightforward to show, but there are examples where it is not: no one knows whether the program below terminates for all values of X WHILE X >1 DO IF ODD(X) THEN X := (3 X) + 1 ELSE X := X DIV 2 If X = 2, this program terminates. But how about X = 3 ? The expression X DIV 2 produces the result of rounding down X/2 to a whole number. Exercise: Write a specification which is true if and only if the program above terminates Solution {T}P{X0}
12
Auxiliary Variables
{X=x Y=y} R:=X; X:=Y; Y:= R {X=y Y=x} this says that if the execution of R:=X; X:=Y; Y:=R terminates (which it does) then the values of X and Y are exchanged Note that variables X and Y are called program variables since they appear in the program. The variables x and y, which dont occur in the command and are used to name the initial values of program variables X and Y. They are called auxiliary variables. also called ghost variables. Informal convention program variable are upper case auxiliary variable are lower case
13
14
This program is to calculate the result of dividing X by Y, giving to Q, and the remainder R of the division. This is {T} C {R < Y X = R + (Y Q)} where C is the program above the specification is true if whenever the execution of C halts, then Q is quotient and R is the remainder resulting from dividing Y into X
15
16
17
18
Sorting
Suppose Csort is a command that is intended to sort the first n elements of an array To specify this formally, let SORTED(A,n) mean A(1) A(2) A(n) A first attempt to specify that Csort sorts is {1 N} Csort {SORTED(A,N)} Not enough: SORTED(A,N) can be achieved by simply putting zero into the first n elements of A
19
Permutation Required
It is necessary to require that the sorted array is a rearrangement, or permutation, of the original array To formalise this, let PERM(A,A,N) mean that A(1),A(2),..,A(n) is a rearrangement of A(1),A(2),..,A(n) An improved specification of Csort sorts: {1 N A=a} Csort {SORTED(A,N) PERM(A, a, N)}
20
Still Not Correct The following specification is true {1 N} N:=1 {SORTED(A, N) PERM(A, a, N)} Must say explicitly that N is unchanged A better specification is thus: {1 N A=a N=n} Csort {SORTED(A, N) PERM(A, a, N) N=n} Is this the correct specification? what if N is larger than the size of the array?
21
Summary
We have given a notation for specifying the partial correctness of programs the total correctness of programs Specifications can still be incorrect however, their meaning is precise We next describe the predicate calculus: the precise language upon which they are based
22
23
Judgements
Three kinds of things that could be true or false have been introduced statement of mathematics, e.g. (X+1)2 = X2 + (2 X) +1 partial correctness specifications {P} C {Q} total correctness specifications [P] C [Q] These three kinds of things are examples of judgements a logical system provides rules for establishing the truth (i.e. proving) various kinds of judgements Floyd-Hoare logic provides rules for proving partial correctness specifications the laws of arithmetic, which are assumed known, provide ways of proving statements about integers ! S means statement S can be proved We have discussed the predicate calculus, first-order predicate logic, in particular its proof theory. This course covers axioms and rules for proving program correctness statements
24
25
Skip
Syntax: SKIP Semantics: the state is unchanged The Skip Axiom ! {P} SKIP {P}
It is a single axiom schema P can be instantiated with different values Instances of the skip axiom are: ! {Y = 2} SKIP {Y = 2} ! {T} SKIP {T} ! {R=X+(Y Q)} SKIP {R=X+(Y Q)}
26
Assignments
Syntax: V := E Semantics: the state is changed by assigning the value of the term E to the variable V Example: X :=X+1 this adds one to the value of the variable X
27
28
Substitution Notation
Define P[E/V] to mean the result of replacing all occurrences of V in P by E read P[E/V] as P with E for V for example, (X+1 > X)[Y+Z/X] = ((Y+Z)+1 > Y+Z)
29
The Assignment Axiom ! {P[E/V]} V:=E {P} Where V is any variable, E is any expression, P is any statement and the notation P[E/V] denotes the result of substituting the term E for all occurrences of the variable V in the statement P.
Instances of the assignment axiom are ! {Y = 2} X:=2 {Y = X} where P stands for Y = X , and P[2/X] is just Y = 2. ! {X+1 = n+1} X:=X+1 {X = n + 1} ! {E = E} X := E {X = E} (if X does not occur in E) if X occurs in E, the postcondition X = E may not hold even after the execution of X := E. for example, suppose E is X+1, clearly it is not true that { X+1 = X+1} X := X+1 { X = X+1 }.
30
V:=E
P(E)
P(V)
31
32
Validity
The fact that it is easy to have wrong intuitions about the assignment axiom shows that it is important to have rigorous means of establishing the validity of axioms and rules. We will not go into this topic here it is possible to give a formal semantics of our little programming language and then to prove that axioms and rules of inference of Floyd-Hoare logic are sound this will only increase our confidence in the axioms and rules to the extent that we believe the correctness of the formal semantics The simple assignment axiom about is not valid for real programming languages G. Ligler has shown that is can fail to hold in six different ways for the language Algol 60
33
34