Proving Array Reversal Algorithm Using PVS

Proving Array Reversal Algorithm Using PVS
April 25, 2008
Nilesh Mahajan,
[email protected]
Abdullah Alshalan,
[email protected]
Abbas Bawaadam,
[email protected]
1
Abstract
We describe our experience with using a formal verication system i.e. Prototype Verication System (PVS) to model and prove the
correctness of an Array Reversal algorithm. First, we explain the array reversal problem in terms of its algorithm and arguments for its
correctness. Next, we describe a verication of the Array Reversal algorithm that we performed using PVS. In the process, we encountered
some diculties which helped us derive some key requirements to accomplish the task of verication. Finally, we present future work ideas
and summarize our conclusions.
2
Contents
1 Introduction
5
2 Problem Statement
5
3 Formulating The Problem in PVS
6
3.1
Specication . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.2
Implementation . . . . . . . . . . . . . . . . . . . . . . . . . .
9
3.3
Correctness
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Proving the Theorem
10
12
4.1
Swap Lemmas . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4.2
Correctness Lemmas
. . . . . . . . . . . . . . . . . . . . . . .
12
4.3
No Side Eects Lemma . . . . . . . . . . . . . . . . . . . . . .
13
4.4
Post condition . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
5 Alternative Formulation of The Problem
5.1
14
PVS Formulation . . . . . . . . . . . . . . . . . . . . . . . . .
15
5.1.1
Specication . . . . . . . . . . . . . . . . . . . . . . . .
15
5.1.2
Implementation . . . . . . . . . . . . . . . . . . . . . .
16
5.1.3
Soundness Property . . . . . . . . . . . . . . . . . . . .
17
3
5.2
Proof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.2.1
Proving the TCCs
. . . . . . . . . . . . . . . . . . . .
18
5.2.2
Proving the Soundness Property . . . . . . . . . . . . .
19
6 Future Work
20
7 Conclusion
20
8 References
21
9 Appendices
22
9.1
The PVS Source File of The First Theorem
. . . . . . . . . .
22
9.2
The Proof Trees of the First Approach
. . . . . . . . . . . . .
24
9.3
The PVS Source File of The Alternative Theorem . . . . . . .
30
9.4
The Proof Tress of the Alternative Approach . . . . . . . . . .
31
4
1
Introduction
According to Owre et al. PVS is a comprehensive interactive tool for specication and verication combining an expressive specication language with
an integrated suite of tools for theorem proving and model checking [1]. We
used this interactive tool to model an Array Reversal problem and prove its
correctness i.e. to prove that the implementation satises the specication.
We rst start by describing our problem statement and the steps to formulate
the Array Reversal program in PVS.
Next, we dene the specication of an Array Reversal program written using
the PVS specication language which is then implemented and supported by
proving certain lemmas and propositions which help determine the correctness of our program i.e. to verify that the resulting array is indeed an exact
reverse of the original input array to the program.
Finally, we state an alternate implementation of the Array Reversal program
using some of the pre-dened types in PVS and the predicate subtyping
feature.
2
Problem Statement
The problem is to prove the correctness of a sequential program that reverses
an array. The algorithm that we are proving is shown below:
5
Algorithm 1 Array Reversal Algorithm
Reverse (a) {
i
= 0;
j
= a.length-1;
while
(i<=j) {
t = a[i];
a[i] = a[j];
a[j] = t;
i = i + 1;
j = j - 1;
}
}
3
Formulating The Problem in PVS
We are taking into account the built-in arrays provided by PVS. These builtin arrays are nothing but functions which map from a domain of indexes to
a range of values of some type.
What does it mean for an array to be in
reverse with some other array? The `other' array can be same as the rst
array. However, this leads to confusion while designing the reverse program.
Therefore, we will be talking about two distinct arrays.
Also, the built-in
arrays provided by PVS are innite. There is a lower bound namely 0 for
natural number indexes but there is no upper bound. We'll be restricting the
model to a range only. The specication, implementation, correctness will
be in a specied range.
6
The whole proof revolves around the idea of decreasing the 'range'the
distance between upper and lower boundsof array.
follows that approach.
induction.
This naturally leads to proofs that use measure-
We also restricted the range such that
proof easier.
The implementation
l ≤ u.
This makes the
It is also necessary to talk in terms of array segments as a
consequence of range restriction. Thus, our specication and implementation
take array segments as arguments.
In the upcoming sections following conventions are followed:
•
a, b - arrays
•
l,lb - lower bounds
•
(a,l,u) (b,lb,ub) - array segments
•
u,ub - upper bounds
•
i - a variable that ranges over
l...u
3.1 Specication
We dene what it means for two array segments to be in reverse. Let the
(a, l, u) and (b, l, u). Then these two arrays are in reverse i
∀(i | 0 ≤ i ∧ i ≤ (u − l)) : a(l + i) = b(u − i). Also the array lengths i.e. the
segments be
size of the two arrays should be same.
7
Figure 1: Two reversed arrays
This predicate is basically iterating over the two arrays in opposite directions
and checking pairs of elements. The comparison can be done in an alternative
way namely
a(l +i) = b(u−i)∧a(u−i) = b(l +i).
We did not see any obvious
advantages to this approach. Maybe there is some performance gain. But
we wanted to keep the denition simple and hence chose the rst approach.
Another equivalent formulation can be
∀(i|l ≤ i ∧ i ≤ u) : a(i) = b(u + l − i)
The reversed? predicate in our program represents this specication.
reversed?(a,l,u,b,lb,ub):bool =
u-l = ub-lb AND
forall( j:{i:nat | 0 <= i AND i <= (u-l)}):
8
a(l+j) = b(ub-j)
3.2 Implementation
We translated the sequential Reversal algorithm described above into a tailrecursive function as shown below:
Reverse(l:nat, u:nat, a): RECURSIVE ARRAY [nat -> int] =
IF l = u THEN a
ELSE
Reverse(l+1, u-1, a WITH [(l) := a(u), (u) := a(l)])
ENDIF
MEASURE u-l <
Figure 2: An invalid translation of the array reversal
algorithm in PVS
The recursive call takes an array with the boundary elements
swapped, and operates on the range
l + 1...u − 1.
a(l), a(u)
The terminating con-
dition occurs when the lower bound crosses the upper bound. In that case
the input array is returned as is.
It's not dicult to see why this works.
The idea is increasingly swapping
elements of the array until all the pairs are swapped.
The program will
terminate and after termination all the pairs are swapped and the resultant
array is in reverse of the original array.
However, the above implementation was found to be buggy. First, the terminating condition is coded wrongly
(l = u).
The program won't terminate
with that condition if the size of the array is even, because
equal to
u.
l
will never be
PVS cannot prove the type correctness conditions for this imple-
mentation automatically. Hence, we came to know that there was a problem
and corrected it by changing the terminating condition to be
9
l ≥ u,
and
u to be non-restricted natural number.
u in the event of reversing an array of
l
dene
This is to allow
to be greater
than
even number of elements and
then terminate.
Another important point that we came across is that using
measure u -
l led to an unproved TCC. We could not use the prover command measureinduct+ since the value to be measured should have a minimum threshold
and should also be monotonically decreasing. To overcome the above mentioned problem we modied the reverse function so that we could prove the
TCC's and also use measure-induct+ to prove the lemmas. This was corrected by taking the measure as
max(0, u − l).
The latter measure is a
monotonically decreasing function with a minimum value namely 0.
A correct translation of the Reverse algorithm is shown below:
Reverse(l:nat, u:nat, a): RECURSIVE ARRAY [nat -> int] =
IF l >= u THEN a
ELSE
Reverse(l+1, u-1, a WITH [(l) := a(u), (u) := a(l)])
ENDIF
MEASURE max(0,u-l)
Figure 3: A correct translation of the array reversal
algorithm in PVS
3.3 Correctness
The implementation is correct if it actually returns an array that is in reverse
with the original array. Therefore, the lemma is
10
Reverse_correct: LEMMA
FORALL (l:nat, u:{i:nat | l<=i}):
b = Reverse(l, u, a) IMPLIES reversed?(a,l,u,b,l,u)
To make proof simpler, we came with an equivalent formulation of this:
Reverse_correct_x: LEMMA
FORALL (l:nat, u:{i:nat | l<=i}):
b = Reverse(l, u, a) IMPLIES FORALL (i:{j:nat | (l <= j) AND (j
<= u)}): b(i) = a(u+l-i)
In the second case, we don't have to expand `reversed?' in the proof. As a
result, the proof is simplied. The implementation revolves around the idea
of swapping boundary elements of a range and then decreasing the range.
The proof should follow this line. Hence, measure-induct follows naturally
on the range
l...u.
We used the measure
u−l ≥ 0
: i : nat|l ≤ i.
u−l.
The measure-induct command
u, l.
requires us to prove that
for all
Consequently, we have a
constraint on u namely
This automatically satises the above
u dependent on l which is undesirable
in a sense. It makes u's type dependent on l. So u's value won't be available
1
at compile time as it is dependent on l. Other approach might be to use
‘max(0, u − l)0 as the measure. We took the rst approach.
goal generated by PVS. This also makes
We separated the `swap' idea in a dierent lemma that says that a swap
actually reverses the boundary segments, these segments being one element
wide.
This lemma can be useful in proving the correctness condition.
It
turns out that with the use of specialized PVS commands, there is no need
to factor out the swap lemma.
While proving correctness theorem, we needed to prove that the program
only acts on the specied range. All elements of the array that fall outside
this range are left unchanged by the program. If the program satises this
1 Thanks
to Michael Adams for pointing this out.
11
condition, it is said to generate no side eects. This is represented as a lemma
in our PVS le.
Reverse_no_side_effects: LEMMA
FORALL (l:nat, u:{i:nat | l <= i}):
FORALL (k:{i:nat | i<l OR u<i}): a(k) = Reverse(l, u, a)(k)
It is impressive the way PVS requires you to prove no side eects.
It can
really serve as a great debugging tool when writing programs. After the no
side eects lemma is proved, the remaining proof was easily completed.
4
Proving the Theorem
4.1 Swap Lemmas
The swap lemmas help to verify that for all operations of the form
and
a(l) = b(u)
with
a
and
b
b(l) = a(u)
l ≤ u it is always the
l and u of the two arrays
being the two arrays and
case that the resulting values stored at the indexes
are equal. To prove this lemma we need to skolemize the variables with new
skolem constants and apply the type constraints to these skolem constants
using typepred which can then be simplied using disjunctive simplication
using atten, applying the replace rule and nally simplifying, rewriting and
recording the decision procedures using assert.
4.2 Correctness Lemmas
The lemma is proved by invoking measure induction on the array range
(measure
− induct + “u − l00 (“l00 “u00 )).
This generates four sub-goals.
For
the rst sub-goal, if we look at the implementation, it's clear that we have
to consider two cases:
12
1. Base case
l ≥ u:
The terminating condition for the algorithm.
The
resultant array is same as input array and the proof is easy.
l < u: The recursive call comes into picture. If b =
Reverse(l + 1, u − 1, a with elements at u and l swapped), then b is the
resultant array. Let's call c = a with elements at u and l swapped. Thus,
b = Reverse(l + 1, u − 1, c).
2. Inductive case
F ORALL(l + 1) ≤ i ≤ (u − 1) : b(i) =
F ORALL(l + 1) ≤ i ≤ (u − 1) : b(i) =
By induction hypothesis, we get that
c(u + l + 1 − i). This gives us
a(u + l + 1 − i). The only question remains here is that of the boundary
elements a(l) and a(u). Obviously, they go as swapped elements in c. So
c(u) = a(l) and c(l) = a(u). So it must be the case that the whole array goes
reversed in b. However, PVS requires us to prove that all elements outside
the range
l + 1...u − 1
go unchanged from c to b or the program does not
change any element outside the range that it is operating on or the program
has no side eects. There comes the `no side eects' lemma.
Other 3 sub-goals can be proved by repeated instantiation, skolemization and
asserts.
4.3 No Side Eects Lemma
This lemma says that the Reverse function is free of any side eects i.e. it
does not aect any values which are outside the range of the array being
reversed i.e. any values which are below the lower bound
upper bound
”l”
and above the
”u”.
To start proving the lemma the rst step is to invoke measure induction on
the array range (measure − induct + “u − l
00
(“l00 “u00 )).
We then can prove the
resulting goal using the skolemization, instantiation, case splits, expanding
denitions and asserts.
13
4.4 Post condition
The post condition is
reversed?(a, 0, N, Reverse(0, N, a), 0, N ).
This means
that the input array and the output array(the array returned by Reverse function) satisfy the specication(reversed?). This lemma is a direct consequence
of the correctness lemmas. We just have to do repeated skolemizations.
5
Alternative Formulation of The Problem
In our alternative proof, we used some of the pre-dened types in PVS's
prelude.
below(nat), upto(nat), f inseq .
When a variable i is dened to be below(j), it means i < j . On the other
hand, if i is dened to be upto(j), it means i ≤ j . f inseq[T ] is a record
of two elds, length which is a number representing the length of the sequence and seq which represents a nite sequence dened as a function
below(length) → T . Notice that what is called ”array” in programming
languages is called ”f inseq” in PVS.
The types we are using for this proof are
We are also using a generic type
T
in our alternative theory instead of
int.
Notice that in our previous proof, we could have easily generalized the theory
to accept a generic type instead of only
integers.
This ease of generalization
of the theory stems from the fact that array reversal, unlike sorting, does not
depend on the type of the array elements.
We also used an interesting technique that PVS provides; predicate subtyping
[2]. Using this feature, we can impose a type condition on what our function
returns.
In this alternative approach we embed the loop invariant in the
denition of the function. This concept was new to us and thus we would
like to give a very simple example to illustrate this feature. Assume that we
dene:
14
sq(x) : real = x ∗ x
and then we prove the lemma
sq _nneg : LEM M A F ORALL(x : real) : sq(x) ≥ 0
sq(x) ≥ 0 , we have to explicitly use the
lemma sq _nneg , e.g., the expression sqrt(sq(x)) = x will generate a TCC,
which we have to prove by invoking sq _nneg . On the other hand if we
dene: sq(x) : nnreal = x ∗ x ,we prove the TCC once, and then PVS will
Whenever we need the property
automatically use the type when needed.
5.1 PVS Formulation
5.1.1 Specication
We dene two variables
a
and
b
to be of type
f inseq[T ].
Unlike in the
specication of the previous theory, we do not need an upper bound or lower
bound since we are dealing with nite sequences (f inseq ) that are bounded by
0 and the length of f inseq .
f inseq s to our predicate reversed?
and the two nseqs are reversed i they have the same length and a's elements
are in reverse with b's as shown in the following diagram.
We pass two
15
Figure 4: Two reversed arrays
The specication of the reversal algorithm is presented in our theorem as:
reversed?(a)(b) : bool =
a`length = b`length AND FORALL (i:below(a`length)) :
= b`seq(a`length-i-1)
a`seq(i)
5.1.2 Implementation
As we mentioned earlier, we embed our loop invariant in the denition of
our translation of the reversal algorithm in PVS. Our loop invariant here
combines the
theory.
no side eects lemma and the correctness lemma of the previous
It ensures that within a range
l...u,
the elements of
reverse, and they are equal outside that range.
Thus, the translation of the reversal algorithm is like this:
16
aand b
are in
reverse(a:finseq[T],l:nat,u:upto(a`length)) : RECURSIVE
{b |
a`length = b`length AND
FORALL (i:below(a`length)):
IF l <= i AND i < u THEN a`seq(i) = b`seq(u-i+l-1)
ELSE a`seq(i) = b`seq(i)
ENDIF } =
IF l >= u-1 THEN a
ELSE
reverse(a WITH [ `seq(l) := a`seq(u-1), `seq(u-1) := a`seq(l)
],l+1,u-1)
ENDIF
MEASURE max(0,u-l)
Figure 5: The other translation of the array reversal
algorithm in PVS
Of course by embedding our correctness conditions inside the function, there
is a price to pay. The function reverse generated several TCCs. PVS was
unable to prove one of them. PVS type checking is undecidable so there is
always a chance where PVS cannot prove a TCC using its proving strategies.
However, that does not mean that those TCCs are disproved. In fact, like in
our case a human intervention was needed to prove the unproved TCC.
5.1.3 Soundness Property
We are here verifying that our function
represented in the predicate
reversed?
reverse
satises the specication
Reverse_works : LEMMA reversed?(a)(reverse(a,0,a`length))
17
5.2 Proof
In order to prove our theorem, we had rst to prove one of the TCCs that
PVS could not prove. And then we proved both of the soundness properties.
5.2.1 Proving the TCCs
PVS automatically proved all the TCCs except for one. PVS generated the
following TCC and was unable to prove it.
reverse_TCC9: OBLIGATION
FORALL (a: nseq[T], l: nat, u: upto(a`length),
v: [d1: {z: [a: nseq[T], nat, upto(a`length)] | max(0, z`3 - z`2) < max(0, u - l)} ->
{b |
d1`1`length = b`length AND
(FORALL (i: below(d1`1`length)):
IF d1`2 <= i AND i < d1`3 THEN d1`1`seq(i) = b`seq(-1 - i + d1`2 + d1`3)
ELSE d1`1`seq(i) = b`seq(i) ENDIF)}]):
NOT l >= u - 1 IMPLIES a`length = v(a WITH [`seq(l) := a`seq(u - 1), `seq(u - 1) :=
a`seq(l)], l + 1, u - 1)`length AND
(FORALL (i: below(a`length)):
IF l <= i AND i < u THEN a`seq(i) = v(a WITH [`seq(l) := a`seq(u - 1), `seq(u - 1) :=
a`seq(l)], l + 1, u - 1)`seq (l + u - 1 - i)
ELSE a`seq(i) = v(a WITH [`seq(l) := a`seq(u - 1), `seq(u - 1) := a`seq(l)], l + 1, u - 1)`seq
(i) ENDIF);
We proved
reverse_TCC9
by rst skolemizing and adding the type con-
straints to the skolemized variables. This led to the following:
18
{-1} l!1 >= 0
{-2} u!1 <= a`length
|------{1} l!1 >= u!1 - 1
{2} a!1`length = v!1(a!1 WITH [`seq(l!1) := a!1`seq(u!1 - 1), `seq(u!1 1) := a!1`seq(l!1)], l!1 + 1, u!1 - 1)`length AND
(FORALL (i: below(a!1`length)):
IF l!1 <= i AND i < u!1 THEN a!1`seq(i) = v!1(a!1 WITH [`seq(l!1) :=
a!1`seq(u!1 - 1), `seq(u!1 - 1) := a!1`seq(l!1)], l !1+ 1, u!1 - 1)`seq
(l!1 + u!1 - 1 - i)
ELSE a!1`seq(i) = v!1(a!1 WITH [`seq(l!1) := a!1`seq(u!1 - 1), `seq(u!1 1) := a!1`seq(l!1)], l!1 + 1, u!1 - 1)`seq (i)
ENDIF)
We have to prove two things:
a!1‘length = ...and F ORALL(i : below(a!1‘length)) :
... Notice that v!1 is an "inductive" variable generated by PVS for the recursive function
reverse.
It represents the previous invocation of the recursive
" v!1(a!1 WITH
[`seq(l!1) := a!1`seq(u!1 - 1), `seq(u!1 - 1) := a!1`seq(l!1)], l!1 + 1, u!1 - 1)".
call. Thus, our next step was to add the type constraints of
This generated ve subgoals which all but the rst were discharged by either
grind
or
assert.
The rst subgoal though was discharged by a skolemiza-
tion, splitting, cases, attening and then a series of instantiations of the right
indexes.
5.2.2 Proving the Soundness Property
The rst property was proved easily by skolemization and adding the type
constraints of the function reverse and then expanding reversed? and asserting .
19
6
Future Work
This project can be extended to build an ADT similar to ArrayList class in
Java SDK. It contains common utility methods for arrays. Example methods
can be:
•
put(element, index, array)
•
get(index, array) which returns an element
•
length(array) returns nat
•
reverse(array) returns the reversed array
•
sort(array) returns the sorted array
This implementation can be extracted out in a theory. All the utility methods
can be proved. So anybody working with arrays in PVS will have a veried
theory of arrays. Hopefully their job will be simpler.
7
Conclusion
A major roadblock in proving the correctness of a program in PVS is to
correctly model it using the expressive specication language provided by
PVS and then understand what lemmas and propositions need to be proved
as a part of proving the nal goal. One of the lessons that we learned is that
not all the lemmas are provable at rst and one may have to add and prove
certain other lemmas which act as prerequisites to the lemma being proved.
Our alternate approach also helped us exploit the built-in features of PVS
that unquestionably demonstrate that PVS is a tool with a lot to oer.
20
8
References
[1] Sam Owre, John Rushby, N. Shankar; PVS: An Experience Report:
(1998).
[2] John Rushby, Sam Owre, N. Shankar; Subtypes for Specications: Predicate Subtyping in PVS; Software Engineering, IEEE Transactions on Volume
24, Issue 9, Sep 1998 Page(s):709 - 720
21
9
Appendices
9.1 The PVS Source File of The First Theorem
reverse_program:
a, b:
THEORY BEGIN
VAR ARRAY [nat -> int]
l,u,lp,up:
VAR nat % These are always used for upper and lower array
bounds
reversed?
(a,l,u,b,lp,up):bool =
u-l = up-lp AND forall( j:{i:nat | 0 <= i AND i <= (u-l)}): a(l+j) =
b(up-j)
N:
nat
%%
The implementation
Reverse
( l:nat, u:nat, a): RECURSIVE ARRAY [nat -> int] =
IF l >= u THEN a
ELSE Reverse(l+1, u-1, a WITH [(l) := a(u), (u) := a(l)])
ENDIF
MEASURE
max(0,u-l)
22
%%
swap lemmas
swap_lemma:
LEMMA FORALL (l:nat, u:{i:nat | l<=i}): b = a WITH
[(l) := a(u), (u) := a(l)] IMPLIES b(l) = a(u) AND a(l) = b(u)
%%
Swap reverses segments
swap_lemma_x:
LEMMA FORALL (l:nat, u:{i:nat | l<=i}):
b = a
WITH [(l) := a(u), (u) := a(l)] IMPLIES reversed?(a,u,u,b,l,l) AND
reversed?(a,l,l,b,u,u)
%%
This lemma says that the Reverse function is free of side eects. It does
not change any value outside the specied range.
Reverse_no_side_eects:
LEMMA FORALL (l:nat, u:{i:nat | l <= i}):
FORALL (k:{i:nat | i<l OR u<i}): a(k) = Reverse(l, u, a)(k)
%%
Correctness lemmas
Reverse_correct_x:
LEMMA FORALL (l:nat, u:{i:nat | l<=i}):
b =
Reverse(l, u, a) IMPLIES FORALL (i:{j:nat | (l <= j) AND (j <=
u)}): b(i) = a(u+l-i)
Reverse_correct:
LEMMA FORALL (l:nat, u:{i:nat | l<=i}): b = Re-
verse(l, u, a) IMPLIES reversed?(a,l,u,b,l,u)
%%
Post condition
post_condition:
END
PROPOSITION reversed?(a, 0, N, Reverse(0,N,a), 0, N)
reverse_program
23
9.2 The Proof Trees of the First Approach
(skolem-typepred)
(flatten)
(replace*)
(assert ...)
(lift-if :updates? t)
(assert ...)
24
Figure 6: Proof tree of swap_lemma
(skolem 1 ("A" "B" "L" "U"))
(flatten)
(expand "reversed?")
(replace -1 1)
(simplify)
(skolem 1 "J")
(lift-if)
(assert)
Figure 7: Proof tree of swap_lemma_x
25
(measure-induct+ "u-l" ("l" "u"))
(skolem 1 "A")
(skolem 1 "K")
(expand "Reverse" 1)
(case "x!1 >= x!2")
(simplify)
(assert)
(assert)
(inst -1 "x!1 + 1" "x!2 - 1")
(inst ...)
(ground)
(assert)
(typepred "K")
(inst -1 "K")
(split -1)
(replace -1 2 rl)
(typepred "K")
(assert)
(expand "Reverse")
(typepred "K")
(ground)
(expand "Reverse")
(assert)
(split -1)
(assert)
(propax)
(assert)
Figure 8: Proof tree of Reverse_no_side_eects
26
(lemma "Reverse_correct_x")
(auto-rewrite "reversed?")
(assert)
(skolem!)
(typepred "l!1")
(typepred "u!1")
(flatten)
(skolem!)
(typepred "j!1")
(replace -5 1)
(inst?)
(replace -5 -4)
(inst?)
(replace -4 1)
(assert)
Figure 9: Proof tree of Proof tree of Reverse_correct
27
(measure-induct+ "u-l" ("l" "u"))
(skolem 1 ("A" "B"))
(inst?)
(flatten 1)
(skolem!)
(skolem 1 "K")
(inst?)
(expand "Reverse" -2)
(skolem!)
(case "x!1 >= x!2")
(assert)
(assert)
(assert)
(inst -1 "1+x!1" "x!2-1")
(inst ...)
(auto-rewrite "Reverse")
(typepred "K")
(assert)
(split -3)
(replace -1)
(lemma "Reverse_no_side_effects")
(propax)
(assert)
(inst ...)
(lift-if)
(replace -5 -1 rl)
(bddsimp)
(auto-rewrite "Reverse")
(simplify)
(replace -5 2)
(simplify)
(assert)
(bddsimp)
(replace -5 -1)
(replace -4 -1)
(replace -4)
(assert)
(replace -5 -2)
(replace -4 4)
(simplify)
(simplify)
(simplify)
(inst?)
(inst? -2)
(inst?)
(lift-if)
(lift-if)
(lift-if)
(assert)
(simplify)
(simplify)
(bddsimp)
(bddsimp)
(bddsimp)
(replace -2 3)
(replace -1 -2)
(replace -2 -5)
(simplify)
(assert)
(replace -1 -2)
(replace -1 -2)
(assert)
(lift-if)
(replace -2 -5)
(replace -1 -3)
(replace -1 -3)
(replace 5 -1)
(replace -1 3)
(replace -1 -3)
(replace -1 -4)
(replace -1 -4)
(assert)
(replace -1 -5)
(replace -1 2)
(replace -2 -5)
(replace -2 -5)
(replace -1 -2)
(replace -2 4)
(replace -1 1)
(replace -1 1)
(simplify)
(replace -1 4)
(replace -2 3)
(replace -1 2)
(replace -2 3)
(simplify)
(replace -1 3)
(replace -2 4)
(simplify)
(replace -2 4)
(simplify)
(replace -1 4)
(assert)
(assert)
(replace -2 3)
(simplify)
(assert)
(assert)
(assert)
(assert)
Figure 10: Proof tree of Reverse_correct_x
28
(assert)
(assert)
(lemma "Reverse_correct")
(skolem 1 "A")
(inst ...)
1
Figure 11: Proof tree of post_condition
29
9.3 The PVS Source File of The Alternative Theorem
reverse_program[T:TYPE]
a,b
: THEORY BEGIN
: VAR nseq[T]
reversed?(a)(b)
:
bool
=
a`length
=
b`length
AND
FORALL
(i:below(a`length)) : a`seq(i) = b`seq(a`length-i-1)
reverse
{b
(a:nseq[T], l:nat, u:upto(a`length)) : RECURSIVE
|
a`length = b`length AND
FORALL
( i:below(a`length)):
IF l <= i AND i < u THEN a`seq(i) = b`seq(u-i+l-1)
ELSE a`seq(i) = b`seq(i)
ENDIF}
=
IF l >= u-1 THEN a
ELSE reverse(a WITH
[ `seq(l) := a`seq(u-1), `seq(u-1) := a`seq(l)
],l+1,u-1)
ENDIF
MEASURE
max(0,u-l)
reverse_works
END
: LEMMA reversed?(a)(reverse(a,0,a`length))
reverse_program
30
9.4 The Proof Tress of the Alternative Approach
(skolem-typepred)
(typepred ...)
(prop)
(assert)
(skolem-typepred)
(grind)
(split)
(case ...)
(flatten)
(inst -7 "i!1")
(assert)
(assert)
(split 1)
(case-replace "i!1=l!1")
(assert)
(assert)
(assert)
(assert)
(grind)
(inst -3 "l!1")
(inst -4 "u!1-1")
(assert)
(assert)
(assert)
(flatten)
(grind)
31
Figure 12: Proof tree of reverse_TCC9
(assert)
(assert)
(assert)
(skosimp)
(typepred ...)
(expand "reversed?")
(assert)
Figure 13: Proof tree of reverse_works
32