15 820a proving software with pvs
This presentation is the property of its rightful owner.
Sponsored Links
1 / 35

15-820A Proving Software with PVS PowerPoint PPT Presentation


  • 99 Views
  • Uploaded on
  • Presentation posted in: General

15-820A Proving Software with PVS. Edmund Clarke Daniel Kroening Carnegie Mellon University. Outline. Modeling Software with PVS Complete Example for Sequential Software, including proof The Magic GRIND Modularization. Modeling Software with PVS. int a[10]; unsigned i; int main() {

Download Presentation

15-820A Proving Software with PVS

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


15 820a proving software with pvs

15-820AProving Software with PVS

Edmund Clarke

Daniel Kroening

Carnegie Mellon University


Outline

Outline

  • Modeling Software with PVS

    • Complete Example for Sequential Software,including proof

    • The Magic GRIND

    • Modularization


Modeling software with pvs

Modeling Software with PVS

int a[10];

unsigned i;

int main() {

. . .

}

1. Define Type for STATE

C: TYPE = [#

a: [below(10)->integer],

i: nat

#]

A


Modeling software with pvs1

Modeling Software with PVS

2. Translate your program into goto program

int a[10];

unsigned i,j,k;

int main() {

L1: i=k=0;

L2: if(!(i<10)) goto L4;

L3: i++;

k+=2;

goto L2;

L4: j=100;

k++;

}

int a[10];

unsigned i,j,k;

int main() {

i=k=0;

while(i<10) {

i++;

k+=2;

}

j=100;

k++;

}

A


Modeling software with pvs2

Modeling Software with PVS

3. Partition your program into basic blocks

4. Write transition function for each basic block

L1(c: C):C=

c WITH [i:=0, k:=0]

L2(c: C):C= c

L3(c: C):C=

c WITH [i:=c`i+1,

k:=c`k+2]

L4(c: C):C=

c WITH [j:=100, k:=c`k+1]

int a[10];

unsigned i,j,k;

int main() {

L1: i=k=0;

L2: if(!(i<10)) goto L4;

L3: i++;

k+=2;

goto L2;

L4: j=100;

k++;

}

A


Modeling software with pvs3

Modeling Software with PVS

5. Combine transition functions using a program counter

PCt: TYPE =

{ L1, L2, L3, L4, END }

int a[10];

unsigned i,j,k;

int main() {

L1: i=k=0;

L2: if(!(i<10)) goto L4;

L3: i++;

k+=2;

goto L2;

L4: j=100;

k++;

}

t(c: C): C= CASES c`PC OF

L1: L1(c) WITH [PC:=L2],

L2: L2(c) WITH [PC:= IF NOT (c`i<10) THEN L4 ELSE L3 ENDIF,

L3: L3(c) WITH [PC:=L2],

L4: L4(c) WITH [PC:=END],

END: c

ENDCASES

A


Modeling software with pvs4

Modeling Software with PVS

6. Define Configuration Sequence

c(T: nat, initial: C):RECURSIVE C=

IF T=0 THEN

initial WITH [PC:=L1]

ELSE

t(c(T-1, initial))

ENDIF MEASURE T

7. Now prove properties about PC=LEND states

program_correct: THEOREM

FORALL (initial: C):

FORALL (T: nat | c(T)`PC=LEND):

c(T)`result=correct_result(initial)

A


Example i

Example I

1. Define Type for STATE

bool find_linear(unsigned size,

const int a[],

int x) {

unsigned i;

for(i=0; i<size; i++)

if(a[i]==x)

return TRUE;

return FALSE;

}

C: TYPE = [#

size: nat,

a: [nat -> integer],

x: integer,

i: nat,

result: bool,

PC: PCt

#]

A


Example ii

Example II

bool find_linear(unsigned size,

const int a[],

int x) {

L1: i=0;

L2: if(!(i<size)) goto L8;

L3: if(!(a[i]==x)) goto L6;

L4: result=TRUE;

L5: goto LEND;

L6: i++;

L7: goto L2;

L8: result=FALSE;

LEND:;

return result;

}

bool find_linear(unsigned size,

const int a[],

int x) {

unsigned i;

for(i=0; i<size; i++)

if(a[i]==x)

return TRUE;

return FALSE;

}

2. Translate your program into goto program

A


Example iii iv

Example III/IV

3. Partition your program into basic blocks

4. Write transition function for each basic block

L1(c: C):C=c WITH

[i:=0]

L2(c: C):C=c

L3(c: C):C=c

L4(c: C):C=c WITH

[result:=TRUE]

L5(c: C):C=c

L6(c: C):C=c WITH

[i:=c`i+1]

L7(c: C):C=c

L8(c: C):C=c WITH

[result:=FALSE]

bool find_linear

(unsigned size,

const int a[],

int x) {

L1: i=0;

L2: if(!(i<size)) goto L8;

L3: if(!(a[i]==x)) goto L6;

L4: result=TRUE;

L5: goto LEND;

L6: i++;

L7: goto L2;

L8: result=FALSE;

LEND:;

return result;

}

A


Example v

Example V

5. Combine transition functions using a program counter

t(c: C):C=CASES c`PC OF

L1: L1(c) WITH [PC:=L2],

L2: L2(c) WITH[PC:=

IF NOT c`i < c`size THEN L8

ELSE L3 ENDIF],

L3: L3(c) WITH [PC:=

IF NOT c`a(c`i)=c`x THEN L6

ELSE L4 ENDIF],

L4: L4(c) WITH [PC:=L5],

L5: L5(c) WITH [PC:=LEND],

L6: L6(c) WITH [PC:=L7],

L7: L7(c) WITH [PC:=L2],

L8: L8(c) WITH [PC:=LEND],

LEND: c

ENDCASES

bool find_linear

(unsigned size,

const int a[],

int x) {

L1: i=0;

L2: if(!(i<size)) goto L8;

L3: if(!(a[i]==x)) goto L6;

L4: result=TRUE;

L5: goto LEND;

L6: i++;

L7: goto L2;

L8: result=FALSE;

LEND:;

return result;

}

A


Example vi

Example VI

6. Define Configuration Sequence

c(T: nat, initial: C):RECURSIVE C=

IF T=0 THEN

initial WITH [PC:=L1]

ELSE

t(c(T-1, initial))

ENDIF MEASURE T

What is the correct result?

7. Now prove properties about PC=LEND states

program_correct: THEOREM

FORALL (initial: C):

FORALL (T: nat | c(T)`PC=LEND):

c(T)`result=correct_result(initial)

A


Example iv

Example IV

C: TYPE = [#

size: nat,

a: [nat -> integer],

x: integer,

i: nat,

result: bool,

PC: PCt

#]

correct_result(c: C): bool=

EXISTS (j: below(c`size)): c`a(j)=c`x

OK!LET’S PROVE THIS!

A


Something useful first

Something useful first…

C: TYPE = [#

size: nat,

a: [nat -> integer],

x: integer,

i: nat,

result: bool,

PC: PCt

#]

We need to say:

c(T)`a = initial`aÆ

c(T)`x = initial`xÆ

c(T)`size = initial`size

OR: The program only changes i, result, PC

program_correct: THEOREM

FORALL (initial: C):

FORALL (T: nat | c(T)`PC=LEND):

c(T)`result=correct_result(initial)

This relates initial state and final state

A


Something useful first1

Something useful first…

We need to say:

c(T)`a = initial`aÆ

c(T)`x = initial`xÆ

c(T)`size = initial`size

OR: The program only changes i, result, PC

invar_constants(T: nat, initial: C): bool=

c(T, initial)`size=initial`size AND

c(T, initial)`a =initial`a AND

c(T, initial)`x =initial`x;

constants: LEMMA

FORALL (initial:C, T: nat):

invar_constants(T, initial)

Proof:Induction on T + GRIND

next: the real invariant…

A


Loop invariant

Loop Invariant

bool find_linear(unsigned size,

const int a[],

int x) {

unsigned i;

for(i=0; i<size; i++)

if(a[i]==x)

return TRUE;

return FALSE;

}

FORALL (j: below(c`i)):

c`a(j)/=c`x

A


The invariant

The Invariant

invar(c: C):bool=CASES c`PC OF

L1:

% i=0;

L2:

% if(!(i<size)) goto L8;

L3:

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6:

% i++;

L7:

% goto L2;

L8:

% result=FALSE;

LEND:c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

Beginning

of the Loop

End

of the Loop

A


The invariant1

The Invariant

What here?

invar(c: C):bool=CASES c`PC OF

L1:

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3:

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6:

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8:

% result=FALSE;

LEND:c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

A


The invariant2

The Invariant

invar(c: C):bool=CASES c`PC OF

L1: TRUE,

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3:

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6:

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8:

% result=FALSE;

LEND:c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

Exiting

the Loop

Exiting

the Loop

A


The invariant3

The Invariant

invar(c: C):bool=CASES c`PC OF

L1: TRUE,

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3:

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6:

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8: c`i>=c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% result=FALSE;

LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

What here?

A


The invariant4

The Invariant

invar(c: C):bool=CASES c`PC OF

L1: TRUE,

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3: c`i<c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6:

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8: c`i>=c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% result=FALSE;

LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

What here?

A


The invariant5

The Invariant

invar(c: C):bool=CASES c`PC OF

L1: TRUE,

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3: c`i<c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(a[i]==x)) goto L6;

L4:

% result=TRUE;

L5:

% goto LEND;

L6: FORALL (j: below(c`i+1)): c`a(j)/=c`x,

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8: c`i>=c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% result=FALSE;

LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES

What here?

A


The invariant6

The Invariant

invar(c: C):bool=CASES c`PC OF

L1: TRUE,

% i=0;

L2: FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(i<size)) goto L8;

L3: c`i<c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% if(!(a[i]==x)) goto L6;

L4: c`i<c`size AND c`a(c`i)=c`x,

% result=TRUE;

L5: c`i<c`size AND c`a(c`i)=c`x AND c`result=true,

% goto LEND;

L6: FORALL (j: below(c`i+1)): c`a(j)/=c`x,

% i++;

L7: FORALL (j: below(c`i)): c`a(j)/=c`x,

% goto L2;

L8: c`i>=c`size AND FORALL (j: below(c`i)): c`a(j)/=c`x,

% result=FALSE;

LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x

ENDCASES


The invariant7

The Invariant

DARING CLAIM

“Once you have found the invariant,the proof is done.”

We now have the invariant.

Lets do the actual proof.

Who believes we are done?

A


The gentzen sequent

The Gentzen Sequent

{-1} i(0)`reset

{-2} i(4)`reset

|-------

{1} i(1)`reset

{2} i(2)`reset

{3} (c(2)`A AND NOT c(2)`B)

Conjunction (Antecedents)

Disjunction

(Consequents)

Or: Reset in cycles 0, 4 is on, and off in 1, 2.Show that A and not B holds in cycle 2.


The magic of grind

The Magic of (GRIND)

  • Myth: Grind does it all…

  • Reality:

  • Use it when:

    • Case splitting, skolemization, expansion, and trivial instantiations are left

  • Does not do induction

  • Does not apply lemmas

“... frequently used to automatically complete a proof branch…”


The magic of grind1

The Magic of (GRIND)

  • If it goes wrong…

    • you can get unprovable subgoals

    • it might expand recursions forever

  • How to abort?

    • Hit Ctrl-C twice, then (restore)

  • How to make it succeed?

    • Before running (GRIND), remove unnecessary parts of the sequent using (DELETE fnum).It will prevent that GRIND makes wrong instantiations and expands the wrong definitions.


Now let s prove the invariant

NOW LET’S PROVE THE INVARIANT


A word on automation

A word on automation…

  • The generation of C, t, and c can be trivially automated

  • Most of the invariant can be generated automatically – all but the actual loop invariant (case L7/L2)

  • The proof is automatic unless quantifier instantiation is required

A


Modularization

Modularization

t(c: C):C=CASES c`PC OF

L1: L1(c) WITH [PC:=L2],

L2: L2(c) WITH[PC:=

IF NOT c`i < c`size THEN L8

ELSE L3 ENDIF],

L3: L3(c) WITH [PC:=

IF NOT c`a(c`i)=c`x THEN L6

ELSE L4 ENDIF],

L4: L4(c) WITH [PC:=L5],

L5: L5(c) WITH [PC:=LEND],

L6: L6(c) WITH [PC:=L7],

L7: L7(c) WITH [PC:=L2],

L8: L8(c) WITH [PC:=LEND],

LEND: c

ENDCASES

bool find_linear

(unsigned size,

const int a[],

int x) {

L1: i=0;

L2: if(!(i<size)) goto L8;

L3: if(!(a[i]==x)) goto L6;

L4: result=TRUE;

L5: goto LEND;

L6: i++;

L7: goto L2;

L8: result=FALSE;

LEND:;

return result;

}

How about a program with a 1000 basic blocks?= 1000 cases?

  • Better not

  • Remedy: Modularize the program and the proof

  • Idea: find_linear is a function in the C program, make it a function in PVS as well

    C  C

  • Functions in PVS must be total, thus, this requires proof of termination

A


Modularization1

a T such that c(T, start)`PC=LEND

Modularization

find_linear(start: C): C=

c(epsilon! (T: nat): c(T, start)`PC=LEND, start)

"epsilon! (x:t): p(x)”

is translated to

"epsilon(LAMBDA (x:t): p(x))”

epsilon_ax: AXIOM

(EXISTS x: p(x)) => p(epsilon(p))

THIS IS WHATREQUIRES TERMINATION

A


Modularization2

Modularization

termination: THEOREM

FORALL (initial: C):

EXISTS (T: nat): c(T, initial)`PC=LEND

allows to show the left hand side of

epsilon_ax: AXIOM

(EXISTS x: p(x)) => p(epsilon(p))

the right hand side then says

c(epsilon! (T: nat): c(T, start)`PC=LEND, start)`PC=LEND

A


Modularization3

Modularization

find_linear(start: C): C=

c(epsilon! (T: nat): c(T, start)`PC=LEND, start)

What to prove about it?

?

find_linear_correct: THEOREM

FORALL (c: C):

LET new=find_linear(c) IN

new=c WITH

[result:=correct_result(c)]

What is missing?

A


Modularization4

Modularization

find_linear(start: C): C=

c(epsilon! (T: nat): c(T, start)`PC=LEND, start)

What to prove about it?

find_linear_correct: THEOREM

FORALL (c: C):

LET new=find_linear(c) IN

new=c WITH

[result:=correct_result(c),

PC:=new`PC,

i:=new`i]

“All variables but result, PC, and i are unchanged,

and result is the correct result.”

A


Now let s prove the theorem

NOW LET’S PROVE THE THEOREM


  • Login