Declarative View of Imperative Programs

By giving a declarative meaning to an imperative program, the verification of the imperative program is switched from the imperative paradigm to the declarative or logic paradigm where one can take advantage of, for example, referential transparency. Rather than 'compiling' an imperative program to a 'lower level' we 'inverse compile' the imperative program to the 'higher' declarative level. The declarative view of an imperative program is a predicate associated with the imperative program such that if this predicate satisfies the specification of the program then the imperative program is correct relative to the specification. In one sense the associated predicate gives a declarative meaning to the imperative program.


Introduction
In imperative programming, programs are implicitly state transformations.We want to abstract away from dealing with states and try to express programs within the "problem domain", that is, we want to give a declarative meaning to imperative programs.If we want to sort a list, our program for doing this should deal with lists and use the properties of lists.Logic/Functional programming and also programming with assertions allow us to do this abstraction.Imperative programs may have functional and relational features -functions and procedures -but they also contain constructs which deal only with state transformation e.g. the assignment statement.
"Not only goto statements are being questioned: we hear complaints about floating-point calculations, global variables, semaphores, pointer variables, and even assignment statements."D. Knuth [6] We are assuming a structured programming language without "goto" and the aim is to transform a structured program to a program without an assignment.We are not just complaining about the 'assignment statement', our aim is to show how it can be removed from programming.Without the assignment statement we gain the advantage of referential transparency ('substitution of equals for equals') which allows both for easier program verification and easier program construction.Also, by transforming a structured program to an 'assignment-less' program we indicate a non-operational declarative meaning to the program.

Associating a Predicate with an Imperative Program.
In the axiomatic semantics of Hoare/Dijkstra/Gries, a predicate pair gives the meaning of the imperative program and in this context a program is viewed as a predicate transformer, transforming a predicate to a predicate.For example, if we have a program, MOD, that calculates the 'integer modulo function '  where wp(S,Q) is the weakest precondition (wp) of program S with respect to the predicate Q. (See Appendix 1.) In determining wp(MOD, Post(z,a,b)) we are finding the wp of the program MOD relative to the particular postcondition, Post(z,a,b).We consider a more general use of wp that will give a declarative meaning to a program such as MOD.We consider the conditions where a program will halt.If the program halts then the output program variable, z, will have some value, which we can denote (using the convention of the Z notation) by z!.
If a program, PROG, halts i.e. wp(PROG,true) then wp(PROG,true) Our aim is to associate the predicate wp(PROG, z = z!) with the program PROG and show how, in particular, this gives an appropriate meaning to the program for proving the program correct.We first consider when the program, PROG, is just the assignment statement.

Assignment and Substitution
The Assignment statement x := e maps the state s to s †[x s(e)], where † is the function over-ride operator.In particular, s †[x s(e)](x) = s(e), i.e. the value of x in the new state is the value of e in the previous state.From this it can be shown, but not here, that wp(x := e, Q( False --a contradiction.
Using the Lambda Calculus formalism, from we cannot conclude (λx)(x+1 = x)(x+1) as the predicate z = x is not 'free for x', as we are replacing z by x+1 in which x occurs free but after replacement the x becomes bound by (λx).But we can change the bound variable x to x' so that from In an analogous way, using x', we get

wp as an Evaluating Mechanism
As a simple illustration, consider the simple program, Swap: x := a; y := b; t := x; x := y; y := t; We can use wp to find the values of x and y after Swap has been executed.Let x! and y! be the ('out') values of x and y after executing Swap.
By calculating wp for assignment and compostion (see Appendix 1) we find that wp(Swap, x = x! ∧ y = y!) = x! = b ∧ y! = a tf.(therefore) x! = b ∧ y! = a → wp(Swap, x = x! ∧ y = y!) Since x!, y! do not occur in Swap and Swap does not change the values of a,b, we get by "Substitution Capture Rule for wp" wp(Swap, x=b ∧ y=a).
As another example, using an conditional statement, consider MIN: Init: x:=a; y:=b; IF: if x < y then z:=x else z:=y fi To find the value of z after executing MIN we use wp(MIN, z = z!).wp In this example, it may be better to consider MIN declared as the procedure we can associate the predicate, p(x,y,z!) = wp( P(x,y,z), z = z!) with the procedure call, P(x,y,z).
i.e. the predicate, p(x,y,z!), which is defined as wp( P(x,y,z), z = z!) is associated with the procedure call, P(x,y,z).
We are using the following notation conventions, we use capitals for imperative programs and lower case for predicates, we are using x to stand for a sequence of variables.
Later, in discussing particular examples, we relax these conventions for convenience.

Extended example, z = m n
Consider the procedure declaration We associate the predicate p(m,n,z!) = wp(POWER(m,n,z), z = z!) with the procedure call POWER(m,n,z).
We consider this in more detail, in particular, we consider how to associate a predicate with a loop statement.

Associating a Predicate with a Loop
To associate a predicate with a loop statement consider the abstract form F: while B loop S Since F is a function on states we can write this as We associate with the procedure call, POWER(m, n, z) the predicate p(m,n,z!).

Program Verification
We can use the associated relation of an imperative program to prove it correct.For example, consider using this approach to verify a program MOD for calculating (a mod b) a,b ε Z (integers) which we define as r = a mod b iff (∃k: From this definition of mod, (a mod b) is defined only when b > 0 and when a ≥ 0, therefore we take a ≥ 0 ∧ b>0 as the precondition.
MOD(in A,B:integer; out Z:integer) is

The Invariant
In establishing the partial correctness of a loop statement we generally use an invariant, there may be more than one.Finding a suitable invariant for an arbitrary program is not easy and so we are encouraged to develop an invariant when constructing a program.We will now consider what, in a sense, is the invariant of a loop, which would be an integral part of the program development.We return to the MOD example to elaborate first what we mean by an invariant, then we discuss what we mean by the invariant.In the last section, in proving the MOD program correct, we showed by induction that We now show how we can use an invariant to establish a ≥ 0 ∧ b>0 ∧ z! = (a Mod b) → wp(MOD, z = z!) and so give an alternative way of proving this result.
Since wp(S, Q) = wlp(S, Q) ∧ wp(S, True), we show where wlp(S, Q) is the weakest liberal precondition of S with respect to predicate Q.
Since MOD contains a loop we consider the general problem of showing P → wlp(L, Q) where L: while B loop S i.e.L = (if B then S;L else SKIP fi).
To show this we will use the following theorem, which is usually called the Invariant Theorem [3].

Invariant Theorem
Let L: while B loop S.
Thus the predicate false is an Invariant of the loop and in a sense false is the 'strongest invariant' (it implies every other invariant).The predicate, false, is no use as an invariant as it can never be initially established.In addition, we can show that wp(L,Q), and similarly wlp(L,Q)), are also invariants because when L: while B loop S i.e.L = if B then S;L else SKIP end if 2) wp(L,Q) ∧ B = (B ∧ wp(S, wp(L,Q)) → wp(S,wp(L,Q)) → wlp(S,wp(L,Q)) Since any invariant P implies wlp(L,Q), we get that wlp(L,Q) is the 'weakest invariant' .
In program verification to show Pre → wp(Init;loop, Q) we need to find a predicate, P, which could be an invariant, such that Pre → wp(Init, P) and P → wp(loop,Q) i.e.P → wlp(loop,Q) ∧ wp(loop,true).
As was mentioned above, the invariant false is not appropriate as from Pre we cannot establish false using Init, as for all programs S, wp(S, false) = false.
The most appropriate invariant, and in a sense the invariant, if we could find it, would be wp(loop, Q) itself.Later we will consider the special case of finding wp(loop, z = z!) and how it relates to the fixpoint of the associated predicate of the loop.
We show that, the (least) fixpoint of this equation = wp(loop, z = z!).
The (least) fixpoint of G is given by where Z is the empty or abort relation.
From Dijkstra's semantics of the loop and letting R: z = z! we have We can show by induction on k, (see Appendix 4)
Having found wp(MOD, z = z!), we see that Since wp(loop, x=z!) is an invariant, we can regard the predicate as the invariant of the loop as it also gives the fixpoint meaning of the associated relation of the loop.

Examples
For the purpose of comparison, we can summarise our approach to program verification by verifying two standard programs for factorial.One version is a 'bottom up approach', calculating fact(x) before calculating fact(x+1).The other version, a 'top down approach', is based on the recursive property of factorial, that fact(x+1) = (x+1) * fact(x).

Note:
Since we are using the symbol '!' for the 'out' value of a variable, it precludes us from using N! for factorial N.

Example 1
We can calculate fact(N) = 1*2*.The in out variable is x and the out variable is y.We can regard N as a constant.We find that the associated predicate is We look for a suitable invariant F1(N,x,y,y!) from F(N,x,y,y!) such that In particular, let the invariant be F1(N, x, y, fact(N)), i.e. let y! be fact(N).
We can show INV is an invariant by showing it satisfies the conditions From 1), 2) and 3) we conclude N ≥ 0 → wlp(FACT, y = fact(N)).Using the variant or bound function, N-x, we also can show the program halts, tf.

Example 2
To calculate fact(N) we can also use the program Show N ≥ 0 → wp(FACT, y = fact(N)).
To show halting we can use the variant, x, as x decreases in the loop.We get N ≥ 0 → wp(FACT, y = fact(N)).
To indicate the usefulness of an invariant we consider showing N ≥ 0 → F(N,1,fact(N)) by induction on N.
From (1) we have in particular N > 0 ∧ F(N-1,N,fact(N)) → F(N,1,fact(N)) therefore ???... (proof breaks down) end Proof (attempt) To make the Induction work we should attempt to prove something weaker Show N ≥ 0 → F(N, y, y*fact(N)) therefore with y:=1 we get F(N, 1, fact(N)).This weakening of our Induction assumption is analogous to the Dijkstra/Gries method of finding an invariant by weakening the post-condition by introducing a variable for a constant.

Summary and Conclusion
In this article we have presented an alternative approach to verifying imperative programs which like the standard approach also uses the notion of weakest precondition.Using the standard approach [Dijkstra], to show {P} F {Q} one shows P → wp(F,Q).
Using conventions similar to those used in the verification of procedures [Gries] we can classify the variables in F into 'in' variables and 'out' variables.
Let x be the 'sequence' of 'in' variables and let z be the 'sequence' of 'out' variables.
Some variables, the 'in out' variables may appear in both 'sequences'.This proof involved using the properties of mod and the recursive definition for M(x,y,z!).While in this case it is straightforward, by inspection, to associate a relation with the imperative program, we showed in general, how we can, using the wp calculus, associate a relation with an imperative program.
Narrowing our focus to the loop statement, L: while B loop S, we can associate with the loop statement the predicate wp(L, z=z!).Let L(x, z!) = wp(L, z = z!) From the properties of the wp calculus, L(x,z!) = B ∧ z=z! ∨ ¬B ∧ wp(S, L(x, z!)) We can show that evaluating the least fixpoint of this equation is the same as evaluating wp(L, z = z!).Since wp(L, z = z!) is also an invariant of the loop, we can consider it the invariant of the loop.
In the MOD example we found that, wp(loop_mod, x = z!) = x ≥ y ∧ y>0 ∧ z! = (x mod y) ∨ x<y ∧ z! = x and we can consider this predicate as either being the invariant of the loop or the meaning of the loop.
To show P → wp(L, Q), we can avoid finding wp(L, Q) explicitly by using the Invariance Theorem.Having associated the relation L(x, z!) with the loop L, we can take advantage of the invariance theorem to show P → L(x, z!).
To show P → L(x, z!) find an invariant Inv such that, 1) Inv ∧ B → wp(S, Inv) 3) P → Inv Also we have to show, 4) P → Dom(L), where Dom(L) determines the domain of L, or in the wp calculus, Dom(L) = wp(L,True).
By enabling the verification of imperative programs to be carried out at the logic/functional level, this leads the way to formally developing imperative programs at the logic/functional level.
The translation from imperative programs to declarative programs is based directly on the weakest precondition predicate transformer.For 'loop type' programs we get tail recursive declarative programs but the technique can be applied to more general imperative programs that have, for example, recursive calls.Also, the technique can be adapted to non-deterministic programs constructed from the non-deterministic forms of the 'if' and 'do' statements.
The technique is quite mechanical and it may be possible to automate the process.As a first step, rather than translating a program directly to a declarative style, it could first be translated to a style of programming that would only have procedure and function calls.Traditionally, it was advised to remove the overhead of procedure and function calls, we are proposing the opposite in a effort to have a transition from structured 'goto-less' programs to declarative 'assignment-less' programs.
i.e. for deterministic S, wp(S,R) ∨ wp(S,R) = wp(S, Q ∨ R).In the context of this article, we assume that our programs are deterministic; for each input there is at most one ouput.

Equality of Programs
If for all predicates, Q we have that wp(S1, Q) = wp(S2, Q) then S1 = S2.S1 and S2 may be different algoritms but if they cannot be distinguished by wp the two programs have the same meaning.For example, all 'sorting' programs are the same, in the sense that they have the same specification.We also will make use of a 'one guard' if statement, if b → S fi.

Calculating wp for basic statements
wp(if b → S fi, Q) = b ∧ wp(S, Q) The iterative statement: while We restrict ourselves to a determistic form, 'while -loop -end' We can deifine wp(L, Q) where L is an iterative command but we may not be able to calculate it.

Conclusion
A more complete treatment of weakest precondition given in [Gries], [Hehner] and also in [Snepscheut].
then the predicate pair Pre(a,b): a ≥ 0 ∧ b > 0, Post(z,a,b): z = a mod b would give the meaning to the program, MOD.In Hoare triple form we have {Pre(a,b)} MOD {Post(z,a,b)}.In the notation of the Refinement Calculus [Morgan], we can write this as z:[Pre(a,b), Post(z,a,b)] MOD To prove the program, MOD, correct we would show that {Pre(a,b)} MOD {Post(z,a,b)} i.e.Pre(a,b) → wp(MOD, Post(z,a,b)).

2 . 3
MIN(in X,Y :integer; out Z :integer) is begin IF: if X < Y then Z := X else Z := Y fi end with the call MIN(a,b,z) equivalent to the program MIN above.In this case we associate with the procedure call, MIN(a,b,z), the predicate wp(MIN(a,b,z), z = z!) getting (a < b ∧ z! = a) ∨ (a ≥ b ∧ z! = b) The Associated Predicate of the Imperative Program, MIN.This approach gives us a way of associating a predicate with an imperative program.Given the procedure MIN(in X, Y:integer, out Z:integer) we can associate with the procedure call, MIN(x,y,z), the predicate/logic program, Min(x,y,z!),where Min(x,y,z!) = wp(IF, z=z!) --IF is the procedure body of MIN. and the query/call to the predicate program Min(a,b,z!) = wp(x := a; y := b, Min(x,y,z!))= wp(x := a; y := b; MIN(x,y,z), z = z!) = wp(MIN(a,b,z), z = z!) Since the predicate/logic program, Min(x,y,z!) = (x < y ∧ z! = x) ∨ (x ≥ y ∧ z! = y) we can write this in clause form as, Min(x,y,z!) ← x<y ∧ z! = x.Min(x,y,z!) ← x≥y ∧ z! = y.i.e.Min(x,y,x) ← x<y.Min(x,y,y) ← x≥y.More generally, let in X be the in (read-only) parameters, in out Y be the in out (read-write) parameters and out Z be the out (write) parameters then with the procedure declaration P(in X:Tx; in out Y:Ty; out Z:Tz) where x are the in variable and z are the out variables As an example let us consider the relation associated with the above program, Power, for finding m n .Find wp(POWER(m,n,z), z=z!).