1 / 35

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

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

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

## PowerPoint Slideshow about ' 15-820A Proving Software with PVS' - lars

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-820AProving Software with PVS

Edmund Clarke

Daniel Kroening

Carnegie Mellon University

• Modeling Software with PVS

• Complete Example for Sequential Software,including proof

• The Magic GRIND

• Modularization

int a[10];

unsigned i;

int main() {

. . .

}

1. Define Type for STATE

C: TYPE = [#

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

i: nat

#]

A

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{-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.

• 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…”

• 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

• 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

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

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

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

find_linear(start: C): C=

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

?

find_linear_correct: THEOREM

FORALL (c: C):

LET new=find_linear(c) IN

new=c WITH

[result:=correct_result(c)]

What is missing?

A

find_linear(start: C): C=

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

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