goto program 10 Theorem Proving and Model Checking in PVS

Theorem Proving and Model Checking in PVS
15-820A
Proving Software with PVS
Edmund Clarke
Daniel Kroening
Carnegie Mellon University
1
Theorem Proving and Model Checking in PVS
Outline
• Modeling Software with PVS
– Complete Example for
Sequential Software,
including proof
– The Magic GRIND
– Modularization
2
Theorem Proving and Model Checking in 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
#]
3
A
Theorem Proving and Model Checking in PVS
Modeling Software with PVS
2. Translate your program into goto program
int a[10];
unsigned i,j,k;
int a[10];
unsigned i,j,k;
int main() {
i=k=0;
int main() {
L1: i=k=0;
}
while(i<10) {
i++;
k+=2;
}
L2: if(!(i<10)) goto L4;
L3: i++;
k+=2;
goto L2;
j=100;
k++;
L4: j=100;
k++;
}
4
A
Theorem Proving and Model Checking in PVS
Modeling Software with PVS
3. Partition your program into
basic blocks
4. Write transition function for
each basic block
int a[10];
unsigned i,j,k;
L1(c: C):C=
c WITH [i:=0, k:=0]
int main() {
L1: i=k=0;
L2(c: C):C=
c
L3(c: C):C=
c WITH [i:=c`i+1,
k:=c`k+2]
L2: if(!(i<10)) goto L4;
L3: i++;
k+=2;
goto L2;
L4(c: C):C=
c WITH [j:=100,
k:=c`k+1]
L4: j=100;
k++;
}
5
A
Theorem Proving and Model Checking in PVS
Modeling Software with PVS
5. Combine transition functions using a program counter
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++;
}
PCt: TYPE =
{ L1, L2, L3, L4, END }
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
6
A
Theorem Proving and Model Checking in PVS
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)
7
A
Theorem Proving and Model Checking in PVS
Example I
1. Define Type for STATE
bool find_linear(unsigned size,
const int a[],
int x) {
unsigned i;
C: TYPE = [#
size: nat,
a: [nat -> integer],
x: integer,
i: nat,
result: bool,
PC: PCt
#]
for(i=0; i<size; i++)
if(a[i]==x)
return TRUE;
return FALSE;
}
8
A
Theorem Proving and Model Checking in PVS
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
9
A
Theorem Proving and Model Checking in PVS
Example III/IV
3. Partition your program into
basic blocks
4. Write transition function for
each basic block
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;
}
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]
10
A
Theorem Proving and Model Checking in PVS
Example V
5. Combine transition functions using a program counter
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;
}
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
11
A
Theorem Proving and Model Checking in PVS
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)
12
A
Theorem Proving and Model Checking in PVS
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!
13
A
Theorem Proving and Model Checking in PVS
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
14
A
Theorem Proving and Model Checking in PVS
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…
15
A
Theorem Proving and Model Checking in PVS
Loop Invariant
bool find_linear(unsigned size,
const int a[],
int x) {
unsigned i;
FORALL (j: below(c`i)):
c`a(j)/=c`x
for(i=0; i<size; i++)
if(a[i]==x)
return TRUE;
return FALSE;
}
16
A
Theorem Proving and Model Checking in PVS
The
Invariant
invar(c: C):bool=CASES c`PC OF
L1:
Beginning
% i=0;
of the Loop
L2:
% if(!(i<size)) goto L8;
L3:
% if(!(a[i]==x)) goto L6;
L4:
% result=TRUE;
L5:
% goto LEND;
L6:
End
% i++;
of the Loop
L7:
% goto L2;
L8:
% result=FALSE;
LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x
ENDCASES
17
A
Theorem Proving and Model Checking in PVS
The
Invariant
invar(c: C):bool=CASES c`PC OF
What here?
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
18
A
Theorem Proving and Model Checking in PVS
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:
Exiting
% if(!(a[i]==x)) goto L6;
the Loop
L4:
% result=TRUE;
L5:
% goto LEND;
L6:
% i++;
L7: FORALL (j: below(c`i)): c`a(j)/=c`x,
% goto L2;
L8:
Exiting
% result=FALSE;
the Loop
LEND: c`result <=> EXISTS (j: below(c`size)): c`a(j)=c`x
ENDCASES
19
A
Theorem Proving and Model Checking in PVS
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:
What here?
% 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
20
A
Theorem Proving and Model Checking in PVS
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:
What here?
% 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
21
A
Theorem Proving and Model Checking in PVS
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:
What here?
% 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
22
A
Theorem Proving and Model Checking in PVS
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
23
Theorem Proving and Model Checking in PVS
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?
24
A
Theorem Proving and Model Checking in PVS
The Gentzen Sequent
Conjunction
(Antecedents)

Disjunction
(Consequents)
{-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)
Or: Reset in cycles 0, 4 is on, and off in 1, 2.
Show that A and not B holds in cycle 2.
25
Theorem Proving and Model Checking in PVS
The Magic of (GRIND)
• Myth: Grind does it all…
• Reality:
“... frequently used to automatically
complete a proof branch…”
• Use it when:
– Case splitting, skolemization, expansion, and
trivial instantiations are left
• Does not do induction
• Does not apply lemmas
26
Theorem Proving and Model Checking in PVS
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.
27
Theorem Proving and Model Checking in PVS
NOW LET’S PROVE
THE INVARIANT
28
Theorem Proving and Model Checking in PVS
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
29
A
Theorem Proving and Model Checking in PVS
Modularization
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;
}
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
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
30
A
Theorem Proving and Model Checking in PVS
Modularization
find_linear(start: C): C=
c( epsilon! (T: nat): c(T, start)`PC=LEND
, start)
a T such that c(T, start)`PC=LEND
"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 WHAT
REQUIRES
TERMINATION
31
A
Theorem Proving and Model Checking in PVS
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
32
A
Theorem Proving and Model Checking in PVS
Modularization
find_linear(start: C): C=
c( epsilon! (T: nat): c(T, start)`PC=LEND
What to prove about it?
, start)
?
find_linear_correct: THEOREM
FORALL (c: C):
LET new=find_linear(c) IN
new=c WITH
[result:=correct_result(c)]
What is missing?
33
A
Theorem Proving and Model Checking in PVS
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.”
34
A
Theorem Proving and Model Checking in PVS
NOW LET’S PROVE
THE THEOREM
35