Today’s Agenda Correctness Issues
Why Correctness? Programming is engineering Program is a product Program quality to be determined during production process Program Correctness is one essential aspect of quality
Design Correctness Solution (design) meets requirements Verified offline (often on paper) Proof arguments Implementation Correctness Implementation (program code) matches design Verified online (often by execution) Tests and Test Cases
Output of Design step: Program Design High level solution to problem Consists of modules and module interconnections Modules are solutions to sub-problems Interconnections capture ways to combine sub-solutions
Module Correctness Often reduces to algorithm correctness: Algorithm should terminate Algorithm should produce required result when it terminates. Both arguments are fairly easy for “straight- line” programs – i.e., no loops.
Module Correctness e.g., Define function to compute square (x) as return x * x It is easy to verify the requirements: It terminates: a single step It computes the square of a given number: x 2 =x*x
Module Correctness Similar argument can be applied for more than one step as well. Problem: Given a, b, and c, solve quadratic equation – a*x 2 + b*x + c = 0 Solution X1 = (-b + √b 2 – 4ac ) / 2a X2 = (-b - √b2 – 4ac ) / 2a
Module Correctness Solution: Define function quad(a, b, c, sign) disc = b*b – 4*a*c; if (sign) return (-b + sqrt(disc)) / (2 *a); else return (-b – sqrt(disc)) / (2*a);
Module Correctness Termination: if sqrt terminates, quad() function terminates. Valid results: if sqrt is correct then quad() returns correct value. How to verify this? Contracts
Inter-Module Correctness Whoever writes sqrt function, specifies input- output contract: /* Pre-condition: m > 0 Post-condition: return n such that |n * n – m| / m <.01 */ float sqrt(float m) argument must be +ve definite
Inter-Module Correctness Observation: Precondition m > 0 This is required for sqrt to be correct (or may be even to terminate). So, quad module must guarantee before invocation of sqrt: disc > 0
Inter-Module Correctness The previous contract may propagate up: /* Pre-condition: b*b > 4*a*c Post-condition: return x such that | a*x*x + b*x + c | <= epsilon */ float quad(float a, float b, float c, int sign)
Note: Function interfacing errors minimized due to the Pre -conditions and Post conditions.
Why do we need correctness ? Testing will be easy -Helpful to the third party users When you write a function you should write: /* Pre-condition : ……. */ /* Post-condition: …….*/
Module Correctness for sqrt(x) R = x/2 Err = abs(R * R – x) Err <.01? Yes return R R= (R + x/R)/2 Err = abs(R*R – x) No
Illustration: sqrt(9) IterationR next Err next =R 2 –x 0=x/2=9/2= <0.01? N 1(4.5+9/4.5)/2= <0.01N [ = ] 2 (3.25+9/3.25)/2 = <0.01N [ ] 3 ( / )/2 =3.00 R next ~ sqrt(9) <0.01 Y Exits from while
Functions for quadratic eqn int main() { float a,b,c,x1,x2; scanf("%f %f %f",&a,&b,&c); x1 = quad(a,b,c,1); x2 = quad(a,b,c,-1); printf("x1 = %f x2 = %f\n",x1,x2); return(0); }
float quad(float a,float b,float c,int sign) { float disc,res ; disc= b*b - 4*a*c; if(disc > 0) { if(sign) res = (-b + sqrt(disc))/(2*a); else res = (-b - sqrt(disc))/(2*a); return (res); } return(-1.0); }
float sqrt(float x) { float r,err; r = x/2.0; err = abs(r*r - x); while((err > 0.01)||(err == 0.01)) { r = (r + x/r)/2; err = abs(r*r - x); } printf("sqrt of disc is %f\n",r); return (r); } }
What is a loop invariant? Property that is maintained “invariant” by iterations in a loop. How is it used? Verify before the loop Verify each iteration preserves it. Property on termination of loop must result in “what is expected”
Loop Invariants: Method to prove correctness of loops Loop has the following appearance: [pre-condition for loop] while (Guard) [Statements in body of loop. Branching statements that lead outside the loop.] end while [post-condition for loop]
Loop Invariance (Example 1 ) Program to do sum of the elements in an array. Sum() { int s = 0; i = 0; // pre condn : s=0 && i=0 While(i < n) { // s is the sum of first i array elements // s = a[0] + … + a[i-1] s = s + a[i]; i = i + 1; } //post condn s = a[0] + ….+ a[i-1] Return s; //post cond : s = a[0] + ………+ a[n-1]
Loop Invariance (Example 2 ) Factorial (int n) fact (int n)// pre condn n>=0 { int i =1, fact = 1; // pre cond while(i<=n) { // invariance here is (fact = (i-1)! && i >0) fact = fact * i; i = i+1; } // post cond: fact = (i-1)! && i > 0 return fact; // post cond: fact = (n+1- 1)! }