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
© Copyright 2026 Paperzz