15 820a proving software with pvs
Download
1 / 35

15-820A Proving Software with PVS - PowerPoint PPT Presentation


  • 120 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() {

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha

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.



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



ad
  • Login