Software Correctness Proofs

Document Sample
Software Correctness Proofs Powered By Docstoc
					Software Correctness Proofs

          CIS 376
       Bruce R. Maxim
        UM-Dearborn

                              1
              Formal Analysis
• Refers to tool-based methods used to explore,
  debug, and verify formal specifications
• Methods
   – Theorem proving
   – Proof checking
   – Model checking
   – Animation and simulation


                                                  2
             Formal Proof - part 1
• Use deductive reasoning
• Proofs are based on a formal system that includes
   – set of primitives
      • finite strings from a fixed alphabet
   – set of axioms
      • specifying the rules of behavior for the primitives
   – set of inference rules
      • allow deduction of additional true statements (known a
        theorems) within the system


                                                                 3
             Formal Proof - part 2
• Deductive system
   – axioms and inference rules for a formal system
• Theory
   – axioms and derived theorems in a formal system
• Proof of theorem
   – sequence of statement transformations that adheres to
     the system’s inference rules
• s1, s2, s3, … , sn |- T
   – theorem T is provable following the sequence si
                                                             4
         Formal System Properties
• Consistent
   – not possible to derive a statement and its contradiction
     form the same set of initial statements
• Complete
   – every true statement is provable
• Decidable
   – there is an algorithm for determining whether any legal
     statement is true
• Note: consistency must be present, completeness
  and decidability would be nice
                                                                5
              Proof Construction
• Forward argument (deductive calculus)
   – starting with axioms and proven results the inference
     rules are used to prove the desired consequent
• Backward argument (test calculus)
   – starting with the desired result and applying the
     inference rules to derive a known result, axiom, or
     theorem




                                                             6
        Program Verification
• Similar to writing a mathematical proof
• You must present a valid argument that is
  believable to the reader
• The argument must demonstrate using
  evidence that the algorithm is correct
• Algorithm is correct if code correctly
  transforms initial state to final state

                                              7
        State of Computation
• Most programming algorithms are based on
  the notion of transforming the inputs to
  outputs
• The state of computation may be defined by
  examining the contents of key variables
  before and after the execution of each
  statement

                                           8
                    Assertions
• Assertions are facts about the state of the program
  variables
• It is wasteful to spend your time looking at
  variables that are not effected by a particular
  statement
• Default assertion
   – any variable not mentioned in the assertion for a
     statement do not affect the state of computation


                                                         9
           Use of Assertions
• Pre-condition
  – assertion describing the state of computation
    before statement is executed
• Post condition
  – assertion describing the state of computation
    after a statement is executed
• Careful use of assertions as program
  comments can help control side effects
                                                    10
       Code Verification Example
• Let’s assume we have an array with a search
  operation that corresponds to the English
  specifications below
   – The procedure searches and array A of length N for a
     value X
   – If X is found than the value of Y is set to the array
     index where X was found on exit
   – If no array element in A matches X then Y will be set to
     zero on exit

                                                           11
    Example - Formal Specifications
• Pre-condition
  –N>0
• Post condition
  – {X = A[Y] and (1 <= Y <= N)} or
  – {(Y = 0) and (k : (1 <= k <= N)  A[k] <> X)}
• Proof would need to show that algorithm
  transformed state of computation from pre-
  condition to the post condition

                                                 12
13
14
           Simple Algorithm
• Model {P} A {Q}
  – P = pre-condition
  – A = Algorithm
  – Q = post condition
• Sum algorithm
  {pre: x = x0 and y = y0}
  z=x+y
  {post: z = x0 + y0}

                              15
          Sequence Algorithm
• Model
  if {P} A1 {Q1} and {Q1} A2 {Q}
  then {P} A1 ; A2 {Q} is true
• Swap algorithm
  {pre: x = x0 and y = y0}
  temp = x
  x=y
  y = temp
  {post: temp = x0 and x = y0 and y = x0}
                                            16
      Intermediate Assertions
• Swap algorithm
  {pre: x = x0 and y = y0}
  temp = x
  {temp = x0 and x = x0 and y = y0}
  x=y
  {temp = x0 and x = y0 and y = y0}
  y = temp
  {post: temp = x0 and x = y0 and y = x0}

                                            17
       Conditional Statements
• Absolute value
  {pre: x = x0}
  if x < 0 then
    y=-x
  else
    y=x
  {post: y = | x0 |}

                                18
    Intermediate Assertions
if x < 0 then
  {x = x0 and x0< 0}
  y=-x
  {y = | x0 |}
else
  {x = x0 and x0>= 0}
  y=x
  {y = | x0 |}
                              19
     Understanding the While Loop
• Every well designed while loop must
   – make progress to ensure eventual termination
   – must maintain the loop invariant to ensure that it is valid
     at each loop exit point

              //invariant holds here
              while (condition) do
                        //invariant holds here
                        make_progress
                        restore_invariant
              //invariant and not(condition) hold here

                                                              20
              Loop Invariant
• Type of assertion that describes the variables
  which remain unchanged during the execution of a
  loop
• In general the stopping condition should remain
  unchanged during the execution of the loop
• Some people show the loop invariant as a
  statement which becomes false when loop
  execution is complete

                                                 21
        Loop Invariant Example
k = 0;
//invariant: A[1], … , A[k] equal 0
//assert: N >= 0
while k < N do
   k = k +1;        //make progress
   A[k] = 0;        //restore invariant
//assert: A[1], … , A[k] equal 0 and k >= N
Note: say k=N will require an induction argument
                                                   22
        While Loop Example
• Algorithm
  while y <> 0 do
    z=z+x
    y=y–1
  ans = z


• What does it do?

                             23
      While Loop Assertions
{pre: x = x0 and z = z0 and y = y0 and y0 >= 0}
while y <> 0 do
begin
{0 < n <= y0 and z’ = z0 + n * x0}
  z=z+x
  y=y–1
end
{y = 0 and z’ = z0 + y0 * x0}
ans = z
{post: ans = z0 + y0 * x0}
                                                  24
                    Proof -1
• If y = 0 loop does not execute and no
  variables change so
  z = z + 0 * x = ans
• If we assume that for n = k if program
  begins loop with y = k it will exit with
  ans = z + k * x



                                             25
                   Proof - 2
• We must prove that when program begins
  loop with y = k + 1 it will exit loop with
  ans = z + (k + 1) * x
• Suppose y = k + 1 at top of loop and the
  body of the loop executes one time
  x=x‘=x
  y = y’ = (k + 1) – 1 = k
  z = z’ = z + x

                                               26
                       Proof - 3
• Since we are at the top of the loop with y = k, we
  can use our induction hypothesis to get
   ans = z’ + k * x’
• Substituting we get
   ans = (z + x) + k * x
       = z + (x + k * x)
       = z + (1 + k) * x
       = z + (k + 1) * x


                                                       27
     Second While Loop Example
Prod = 0
I = 0
{X and N are initialized and Prod = I * X and I <= N}
while (I < N) do
begin
  {Prod = I * X and I < N}
  Prod = Prod + X
  {Prod = (I + 1) * X and I < N}
  I = I + 1
  {Prod = I * X and I <= N}
end
{loop exited with Prod = I * X and I >= N}
{Prod = N * X}
                                                  28
                  Proof - 1
• Check I = 0
  Verify that invariant is true
  Prod = 0
  Prod = 0 * X = 0
  If N = 0 condition is false and loop terminates
  If N > 0 condition is true and loop execution
     continues

                                                    29
                  Proof - 2
• Assume correctness of the invariant at the top
  of the loop when I = K
  Prod = K * X
  If K < N condition is true and the loop execution
     continues
  If K = N condition is false and loop terminates
  So post condition is true
• So we are assuming that
  X0 + X0 + X0 + … + X0 + X0 = K * X0 = Prod
               k times
                                                      30
                     Proof - 3
• If we are at the top of the loop and execution
  continues the body adds X0 to both sides
• Using our induction hypothesis we get
   (X0 + X0 + X0 + … + X0 + X0) + X0 = K * X0 + X0
                  k times
• Which gives us
   X0 + X0 + X0 + … + X0 + X0 + X0 = K * X0 + X0
                 k + 1 times
• Which can be written as
   X0 + X0 + X0 + … + X0 + X0 + X0 = (K + 1) *X0 = Prod
                                                          31
                  Proof - 4
• Since assuming the invariant is true for K
  we showed that it held for K + 1
• If the loop condition is true execution
  continues
• otherwise is halts with
  I=N+1
  Prod = X0 * N

                                               32
         Counting Loop Example
• This loop stores the sum of the first I array
  elements in position C[I]

  {pre: max >= M >= 1 and C initialized}
  for I = 1 to M
    C[I] = C[I] + C[I – 1]
  {post: I = M + 1 and
   for each J = 1 to I – 1 : C’[J] = C[0] + … + C[J]}



                                                  33
                  Proof - 1
• Show for the case M = 1 that the program
  will exit with
  C[1] = C[1] + C[0] and C’[0] = C[0]
• If M = 1 loop executes with I = 1 and
  C’[1] = C[0] + C[1]
• Loop is satisfied and result is
  I = 2 and C[1] = C[1] + C[0] and C[0] = C[0]
• This gives us our intended result
                                                 34
                  Proof - 2
• For our induction hypothesis we assume
  if loop reaches top with M = K the loop exits
  C’[K] = C[0] + … + C[K]
  …
  C’[1] = C[0] + C[1]
  C’[0] = C[0]



                                                  35
                 Proof - 3
• We need to show that if loop reaches the top
  with M = K + 1 the loop ends with
  C’[K + 1] = C[0] + … + C[K + 1]
  C’[K] = C[0] + … + C[K]
  …
  C’[1] = C[0] + C[1]
  C’[0] = C[0]

                                            36
                Proof - 4
• C’[K + 1] = C[K + 1] + C[(K + 1) - 1]
• C’[K + 1] = C[K + 1] + C[K]
• By our induction hypothesis C[K] now
  contains C’[K] so
  C’[K + 1] = C[K + 1] + C’[K]
  C’[K + 1] = C[K + 1] + C[K] + … + C[0]


                                           37
                  Proof - 5
• Loop condition is satisfied and
  I = (K + 1) + 1 = K + 2
• The array should now contain
  C’[K + 1] = C[0] + … + C[K + 1]
  C’[K] = C[0] + … + C[K]
  …
  C’[1] = C[0] + C[1]
  C’[0] = C[0]

                                    38
These proof examples were posted on
      the World Wide Web by
          Ken Abernathy
         Furman University




                                      39
     Proof Technique Sequent Calculus

• One type of deductive calculus
• A sequent is written  |- , which means /\ 
  implies \/ , where  is a (possibly empty) list of
  formulas {A1, …, An} and  is a (possibly empty)
  list of formulas {B1, …, Bn}
   – the formulas in  are called the antecedents
   – the formulas in  are called the consequents
• To restate,  |-  means
     A1 /\ … /\ An implies B1 \/ … \/ Bn

                                                        40
                 Sequent Calculus
• A sequent calculus proof is a tree of sequents whose root
  is a sequent of the form |- T where T is the formula to be
  proved and the antecedent is empty
• The proof tree is then generated by applying inference
  rules of the form:
       1 |- 1 … n |- n
                                Rule N
      |- 
• Intuitively, this rule replaces a leaf node in the proof tree
  of form  |-  with the n new leaves specified in the rule.
  If n is zero, that branch of the proof tree terminates.


                                                             41
          Sequent Calculus - Example Rule 1
• The Propositional Axiom (Prop_Axiom) is one of the rules of
  inference in sequent calculus. It has the following form form:
      

                                            Prop_Axiom
           , A |- (A, 


• Intuitively, this rule indicates that a proof branch is complete
  when the sequent above is derived. Note that the consequent
  means the following:                       
                 /\ A implies A \/ 
  which is obviously true.

                                                                     42
     Sequent Calculus - Example Rule 2

• The Rule for Conjunction on the Right (And_Right) is
  another of the rules of inference in the sequent calculus. It
  has the following form:
    |- A,  |- B, 
                                             And_Right
      |- (A /\ B, 
• This rule is typical of many sequent calculus inference
  rules which divide, but simplify, a branch of the proof tree.
  Note that the consequent is replaced by two simpler
  formulas which will be easier for a mechanized theorem
  prover to deal with.

                                                                  43
     Sequent Calculus - Example Rule 3
• The Rule for Conjunction on the Left (And_Left) is another
  of the rules of inference in the sequent calculus. It has the
  following simple (non-branching) form:
   A, B,  |- 
                                        And_Left
     (A /\ B, |- 


• This rule is typical of several sequent calculus inference
  rules which simply restate the “obvious,” thereby providing
  a form easier for a mechanized theorem prover to deal with.


                                                                  44
 Sequent Calculus - Example Rule 4
• The Rule for Implication on the Left (Implies_Left)
  is another of the rules of inference in the sequent
  calculus. It has the following form:
    |- A, B,  |- 
                                          Implies_Left
    (A => B, |- 


• Similar to the And_Right rule, this rule again splits
  the proof into two cases, each of which will be
  easier for the mechanical prover to deal with.


                                                          45
  Sequent Calculus - Example Rule 5
• The Rule for Implication on the Right (Implies_Right)
  is another of the rules of inference in the sequent
  calculus. It has the following form:
   A |- B, 
                                      Implies_Right
    |- (A => B, 


• This rule does not branch, but provides a form easier
  for a mechanized theorem prover to deal with.



                                                          46
    Sequent Calculus Proof Example

     Theorem 1: (P => (Q => R)) =>      ((P /\ Q) => R)
We begin the proof by forming the requisite sequent:
   Antecedents:
          none

   Consequents:
          Formula 1: (P => (Q => R)) =>      ((P /\ Q) => R)

                                                               47
        Proof Example - Step 1
As our first step we apply the rule Implies_Right. This rule
will decompose the entire formula. Remember there is an
implied “implies” in the sequent. In other words this sequent
could be written

       |- (P => (Q => R)) => ((P /\ Q) => R).


 Antecedents:
        Formula 1: P => (Q => R)

 Consequents:
       Formula 1: (P /\ Q) => R
                                                          48
             Proof Example Step 2
A second application of the rule Implies_Right will decompose
the formula below the line in a similar way. Remember that
rules applying to the “left” part of the sequent work on formulas
above the bar; rules applying to the “right” part of the sequent
work below the bar.

 Antecedents:
        Formula 1: P => (Q => R)
        Formula 2: P /\ Q

 Consequents:
       Formula 1: R

                                                              49
             Proof Example Step 3
We next apply the rule And_Left -- this rule will modify
(rewrite) Formula 2 above the line. Remember that all
formulas above the line are connected by AND’s; formulas
below the line are connected by OR’s.


Antecedents:
       Formula 1: P => (Q => R)
       Formula 2: P
       Formula 3: Q

Consequents:
      Formula 1: R
                                                           50
           Proof Example Step 4
We next apply the rule Implies_Left -- this rule will modify
Formula 1 above the line. Remember that Implies_Left splits
the proof tree into two branches. We show and deal with
Case 1 first, then move to Case 2 later.

Case 1:
Antecedents:
       Formula 1: Q => R
       Formula 2: P
       Formula 3: Q

Consequents:
      Formula 1: R
                                                           51
           Proof Example Step 5
To modify Formula 1 above the line, we next apply the rule
Implies_Left again. Again this splits the proof tree into two
branches. We show and deal with Case 1.1 first, then move to
Case 1.2 later.

Case 1.1:
Antecedents:
       Formula 1: R                 Case 1.1 will now
       Formula 2: P                 yield to an
       Formula 3: Q                 application of
                                    Prop_Axiom
Consequents:
      Formula 1: R
                                                          52
       Proof Example Steps 5 & 6
As noted, an application of Prop_Axiom (Step 5) completes
Case 1.1. We now move to Case 1.2. This is the second case
resulting from the application of Implies_Left on the Case 1
sequent. Another application of Prop_Axiom (Step 6) completes
Case 1.2 (and in turn Case 1 itself).
Case 1.2:
Antecedents:
       Formula 1: P               Case 1.2 will also
       Formula 2: Q               yield to an
                                  application of
Consequents:
                                  Prop_Axiom
      Formula 1: Q
      Formula 2: R
                                                         53
            Proof Example Step 7
Having completed the proof for Case 1, we now move to
Case 2. Recall that this is the second case resulting from
our first application of Implies_Left. Another application of
Prop_Axiom (Step 7) completes Case 2 (and in turn the
entire proof).
Case 2:
Antecedents:
       Formula 1: P                  Case 2 will also
       Formula 2: Q                  yield to an
                                     application of
Consequents:                         Prop_Axiom
      Formula 1: P
      Formula 2: R
                                                                54
     Mechanical Theorem Provers
• Many mechanical theorem provers require human
  interaction
• Users typically are required to choose the rule of
  inference to be applied at each step
• The theorem prover may be able to discover (by
  heuristic search) some rules to apply on its own
• The user needs to translate the statements to some
  normal form prior to beginning

                                                   55
    Proving Algorithm Correctness
• Suppose you have a software component that
  accepts as input an array T of size N
• As output the component produces an T` which
  contains the elements of T arranged in ascending
  order
• How would we convert the code to its logical
  counterpart and prove its correctness?


                                                     56
              Bubble Sort Algorithm
        T` = T
        more = true
lab1:    i=0
        if (more ~= true) then go to end
                 not(more) = true
                           //** assertion needed
lab2:                      i=i+1
                 if i >= N then go to lab1
                           if T`(i) < T`(i+1) then go to lab2
                                     //* assertion needed
                                     exchange T`(i) with T`(i+1)
                                     more = true
                                     go to lab2
                                                                   57
                         Step 1
• Write assertions to describe the components input
  and output conditions
• input assertion
      A1: (T is an array) & (T is of size N)
• output assertion
      Aend: (T` is an array) &
      ( i if i < N then (T`(i) <= T`(i+1)) &
      ( i if i < N then j(T`(i) = T(j)) &
      (T` is of size N)
                                                  58
                         Step 2
• Draw a flow diagram to represent the logical flow
  through the component
• Indicate points where data transformations will
  occur and write assertions
• Ex. Assuming a bubble sort is used two assertions
  might be
   – [(not(more) = true)) & (i < N) & T`(i) > T`(i+1))] 
     [T`(i) is exchanged with T`(i+1)] //*
   – [(not(more) = true)) & (I >= N)]  [T`(i) sorted] //**

                                                          59
                      Step 3
• From the assertions a we generate a series of
  theorems to be proved
• If your first assertion is A1 and the first
  transformation point has assertion A2 associated
  with it the theorem to be proved is
      A1  A2
• Once the list of theorems is established each must
  be proved individually (order does not matter)

                                                   60
                Steps 4 and 5
• We need to locate each loop in the flow diagram
  and write an if-then assertion for each loop
  condition
• To prove correctness, each logic path beginning
  with A1 and ending with Aend Following each of
  these paths allows us to demonstrate that the code
  shows that the truth of the input condition will
  lead to the truth of the output condition

                                                   61
                 Steps 6 & 7
• After identifying each logic paths the truth of each
  path is proved rigorously (showing the the input
  assertion implies the output assertion according to
  the logic transformations found on that path)
• Finally you need to prove the program terminates
  (which may mean an induction argument if loops
  are involved)



                                                     62
 Cost of Correctness Proofs - part 1
• Advantages
  – You can discover algorithmic faults in the code
  – Gives you a formal understanding of the logical
    structures of the program
  – Regular use of proofs forces you to be more precise in
    specifying data, data structures and algorithmic rules
• Disadvantages
  – Code is often smaller size than its proof
  – It may take less effort to create code than to prove its
    correctness
                                                               63
 Cost of Correctness Proofs - part 2
• Disadvantages (continued)
  – Large programs require complex diagrams and contain
    many transformations to prove
  – Nonnumeric algorithms are hard to represent logically
  – Parallel processing is hard to represent
  – Complex data structures require complex
    transformations
  – Mathematical proofs have occasionally been found to
    be incorrect after years of use

                                                        64
              Symbolic Execution
• Involves simulated execution of the program code using
  symbols rather than data variables
• The test program is viewed as having an input state defined
  by the input data and preconditions
• As each line of code is executed the program statement is
  checked for state changes
• Each logical path in the program corresponds to an ordered
  sequence of state changes
• The final state of each path must be a proper output state
• A program is correct if each input state generates the
  appropriate output state
                                                            65
     Symbolic Execution Example
• Consider the following lines of code
     a = b + c;
     if (a > d)
            call_task1( );
     else
            call_task2( );



                                         66
         Symbolic Execution Steps
• A symbolic execution tool would decide that (a>d) can be
  true or false, without worrying about the values assigned to
  a and d
• This gives us two states
   – (a > d) is false
   – (a > d) is true
• All data values are presumed to fall into one of the
  equivalence classes defined by the two states (so only a
  small number of test cases need be considered in a proof)
• This technique has many of the same costs and
  disadvantages of using logical correctness proofs
                                                              67
              Structural Induction
• Induction can be used to show loop termination
  and correctness of list processing algorithms
• To show the f(list) is true for every list you must
  prove that
   – f(list) is true for an empty list //the base case
   – whenever f(list`) is true, so is f(x :: list) in other words
     adding an element to the list preserves truth no matter
     how the list is            //induction step
   – f([x1, … ,xn]) is true after n steps

                                                                    68
           Generalizing Induction
• Suppose you want to show that
   – k addlen(k. list) = k + nlength(list)
• Give the following definitions
   nlength([ ])       =      0
   nlength(x :: xs)   =      1 + nlength(xs)

   addlen(k, [ ])     =      k
   addlen(k, x::xs)   =      addlen(k + 1, xs)


                                                 69
       Induction Correctness Proof
• k addlen(k. list) = k + nlength(list)
• Base case:
   addlen(k, [ ])     = k
                      = k+0
                      = k + nlength([ ])
• Induction step - assume that
   addlen(k, x::list`) = addlen(k + 1, list`)
                       = k + 1 + nlength(list`) //IHOP
                       = k + nlength(x :: list`) // must prove
                                                                 70

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:9
posted:7/24/2012
language:
pages:70