Studies in Automatic Programming Logic
Studies in Automatic Programming Logic
Studies in Automatic
Programming Logic
Zohar Manna
Richard Waldinger
with contributions by
Shmuel Katz and Karl Levitt
https://archive.org/details/studiesinautomatOOOOmann
Studies in Automatic
Programming Logic
V_ )
THE COMPUTER SCIENCE LIBRARY
Artificial Intelligence Series
NILS. J. NILSSON, Editor
with contributions by
Shmuel Katz and Karl Levitt
NORTH-HOLLANDNEW YORK
NEW YORK • AMSTERDAM • OXFORD
Q
Manna, Zohar.
Studies in automatic programming logic.
(Artificial intelligence series) (The
computer science library)
Bibliography: p.
Includes index.
1. Electronic digital computers—Programming.
2. Computer programs. I. Waldinger, Richard,
joint author. II. Title.
QA76.6.M357 001.6’42 77-5765
ISBN 0-444-00224-3
ISBN 0-444-00225-1 pbk.
Preface vii
Chapter 1 Reasoning about Programs 1
R. Waidinger and K. Levitt
1. Introduction and Background 1
2. The Method 3
3. The Language 11
4. Examples 20
5. Conclusion 35
6. Appendix: Annotated Listing of the Deductive
System 37
7. Appendix: Traces of Solutions 69
v
Sa57197
VI CONTENTS
Postscript 179
References 181
Index 186
Preface
vii
viii PREFACE
Z. M. and R. W.
Chapter 1
Reasoning About Programs
Richard Waldinger and Karl Levitt
Problems worthy
of attack
Prove their worth
by hitting back.
Piet Hein
This is a revised version of a previously published article by the same name which ap¬
peared in Artificial Intelligence, vol 5, pp. 235-316. Copyright 1974 by North-Holland
Publishing Company, Amsterdam. Reprinted here by permission of publisher.
2 REASONING ABOUT PROGRAMS
2. The Method
Perhaps not all readers are familiar with the method of proving
statements about programs that we have followed in our work. Our
method is a natural technique introduced independently by Floyd
(1967) and Naur (1966) and formalized by Hoare (1969). Knuth
(1968, pp 17-18) traces the germ of the idea back to von Neumann
and Goldstine (1963). An other presentation of the same idea
appears in a lecture by Turing (1950). Although we cannot give a
thorough introduction to the technique here, we provide below an
example of its application to convey the flavor of the approach.
Figure 1.3.
idea of the subject domain of the inference system and of the sort
of reasoning it has to do.
Suppose we are given the annotated program shown in Figure 1.4
to compute the largest element in an array and its location. This
program searches through the array, keeping track of the largest
element it has seen so far and the location of this element. The
intermediate assertion1 at C says that MAX is the largest element
in the array between 0 and I and that LOC is the index for MAX.
Although our assertion language does not permit the ellipsis notation
we have introduced some suitable analogues, which are
discussed later.
To prove assertions about a complex program, the system decom¬
poses it into simple paths. This program can be decomposed into
four simple paths:
Notice that the author of this program has put assertions not only
at the START and HALT nodes of the program, but also at the
intermediate point C. He has done this so that the proof of the pro¬
gram can be reduced to proving straight-line paths in the same way
that the simple program of the previous section was verified. For
instance, the path that begins at C, travels around the loop through
E, and returns to C can be regarded as a simple, straight-line program
with the assertion at C as both its start assertion and its halt asser¬
tion. The assertion at C has been cleverly chosen to be true when the
loop is entered and to remain true whenever control travels around
the loop and returns to C, and to allow the assertion at D to be
proved when control leaves the loop and the program halts. The
choice of suitable internal assertions can be an intellectually exacting
1 In this program, and in examples throughout the paper, when we list several statements
in an assertion, we mean the implicit conjunction of those statements. We will often also
refer to each conjunct as an “assertion”.
The Method 7
Figure 1.4.
task; some heuristic methods have been proposed that will work in
this and many other examples (Elspas, 1974; Wegbreit, 1974;
German and Wegbreit, 1975; Katz and Manna, 1976).
If all the straight-line paths of the program are shown to be cor¬
rectly described by the given assertions, and if the program can be
shown to terminate (this must be done separately), then we can
conclude that the program is indeed correct, at least with respect
to the programmer’s final assertion.
Although there are many paths in the decomposition of a pro¬
gram, typically most of the paths are easy to verify. For this
program, we examine two of the paths.
C will still be true if control passes around the loop and returns again
to C. We will restrict our attention to the more interesting case, in
which the test MAX < A[I] ? is true; in this case, control passes
through E. Furthermore, we will try to prove only that the second
conjunct of the assertion at C remains true. Our verification
condition generator gives us the following statement to prove:
n (N < I + 1) A (1.4)
This statement is
must have been true. Passing the assertion back before the test gives
the implication
MAX < A [ I ] D A[0] < A[I], A[l] <A[I], ..., A[I] < A[I].
(E12)
If this implication is true before the test (1.11), the assertion (1.10)
will be true after the test. To travel around the loop at all, the result
of the test
N < I? (1.13)
must have been false. Passing the assertion (1.12) back over the test
(1.13) gives
n (N < I) A MAX < A [ I ]
I^I+l (1.15)
gives
(1.16)
i (N < I + 1) A
from goals. Both of these proofs are typical of the behavior of the
system at large in their use of the properties of equality and the
ordering relations.
In reading the QA4 listing of the theorem prover (Section 6),
one is struck by the absence of any general deductive mechanisms
outside of the language processor itself. The QA4 system incorpor¬
ates enough of the common techniques of theorem proving and
problem solving that our inference system needs no general problem¬
solving knowledge, but only some knowledge about numbers, arrays,
and other structures. The following sections show how the QA4
language allows that knowledge to be represented.
3. The Language
has pattern (TUPLE <~X «-Y) and body (TUPLE $Y $X). The symbol
“TUPLE” is treated as a constant, and can only be matched against
itself. The prefix means that the variable is to be given a new
12 REASONING ABOUT PROGRAMS
binding. The prefix “$” means that the variable’s old binding is to be
used. When REVTUP is applied to (TUPLE A B), the pattern
(TUPLE <-X <-Y) is matched against (TUPLE A B). The match is
seen to be successful, the variable X is bound to A and the variable Y
is bound to B. The body (TUPLE $Y $X) is evaluated with respect to
these bindings, giving (TUPLE B A).
On the other hand, if a function is applied to an argument and the
pattern of that function does not match the argument, a condition
known as failure occurs. At many points in the execution of a pro¬
gram, the system makes an arbitrary choice between alternatives.
Failure initiates a backing up to the most recent choice and the
selection of another alternative, if one exists. The mismatching of
patterns is only one of the ways in which failure can occur in a
program.
We have yet to explain how a program stands forward when it is
relevant. In the above example, the function was called by name,
much as it is in a conventional programming language. But it is
also possible to make an argument available to any applicable pro¬
gram in a specified class. This is done by means of the goal mecha¬
nism.
When we say (GOAL (goalclass) (argument)), where the goal class
is a tuple of names of functions, we first check to see whether the
argument is known to be true, in which case the statement succeeds.
Otherwise that argument becomes available to the entire goal class.
The pattern of each of those functions is matched in turn against the
argument. If the match is successful, the function is applied to that
argument. If the function returns a value, that value is returned as
the value of the goal statement. On the other hand, if the match of
the pattern fails, or if a failure occurs in evaluating the function,
backtracking takes place, the next function in the goal class is tried,
and the process is repeated. If none of the functions in the goal class
succeed, the entire goal statement fails.
For example, in our deductive system, one of the goal classes is
called EQRULES, the rules used for proving equalities. One of these
rules is
EQTIMESDIVIDE =
(LAMBDA (EQ ^W (TIMES (DIVIDE ^X «-Y) «-Z))
(GOAL SEQRULES
(EQ (TIMES $Y $W)(TIMES $X $Z)»).
The Language 13
3.3. Demons
instance, one demon watches for statements of the form X > Y and
makes the statement Y < X. The user of the system can create his
own demons. Demons are a tool for reasoning forward from an
antecedent. In particular, we use demons to drive antecedents into
a canonical form. For example, we drive all inequality expressions
with integer arguments into an assertion of the form X < Y.
3.4. Representations
The logical function AND has the property that, for instance,
(AND A A B) = (AND A B). The number of occurrences of an
argument does not affect its value. Consequently, AND takes a
set as its argument. Since (SET A A B) and (SET A B) are indis¬
tinguishable, (AND A A B) and (AND A B) are identical, and a
statement of their equality is unnecessary. Some functions that
take sets as arguments are AND, OR, EQ, and GCD (greatest
common divisor).
When a new fact is asserted to our system, the value TRUE is
placed on the property list of that fact. If at some later time we
want to know if that fact is true, we simply look on its property
list.
However, certain facts are given special handling in addition. For
example, if we tell the system that certain expressions are equal,
we form a set of those expressions. On the property list of each
expression, we place a pointer to that set. For instance, if we assert
(EQ A B C), the system stores the following:
ABC
(SET ABC)
A B C D
If we then ask the system if A is less than C, it will search along the
pointers in the appropriate way to answer affirmatively. The transi¬
tive law is built into this representation.
The system knows about LT (<), GT (>), LTQ (<), GTQ (>),
EQ (=), NEQ (A), and how these relations interact. For example, if
we assert X> Y,Y>Z, and X < Z, the system will know X = Y = Z
and that (F X A) = (F Y A) for any function symbol F and argument
A. Or if we assert X > Y and X A Y, the system will know X > Y.
3.5. Contexts
3.7. Notation
Let X be a set or bag, X = (SET X1, ..., Xn), or X = (BAG Xx, ...,
Xn). Then (LTQ (STRIP X) Y) means X1 < Y and ... and Xn < Y.
For instance, to state that MAX is greater than or equal to any
element in an array A between I and J, we assert
is
(BAG A B C D).
2 They are actually called c and a (“contents” and “assign”) in that paper. We follow
King (1969), who inadvertently reversed the roles of the initials.
20 REASONING ABOUT PROGRAMS
4. Examples
hypotheses:
0<P, (1.22)
P<Q, (1-23)
A = Q*Y, (1-24)
P< A + B. (1.29)
var(X) is true,
const(A) is true,
var(A) is false,
var((X Y)) is false.
((X • A) (Y • (G B))),
and e is
(F X A (Y B)),
then varsubst(s, e) is
(F A A ((G B) B)).
The LISP functions car, cdr, list, and atom can be used to manipulate
expressions. The empty substitution is denoted by EMPTY and has
no effect on an expression. An operation called compose, the com¬
position of substitutions, defined by Robinson (1965), has the
following property:
varsubst(compose(s \, s2), e) = varsubst(s 1, varsubst{s2, e)).
The problem of pattern matching is defined as follows: Given two
expressions called the pattern and the argument, try to find a sub¬
stitution for the variables of the pattern that makes it identical to the
argument. We call such a substitution a match. For example, if the
24 REASONING ABOUT PROGRAMS
pattern pat is
(X (Y AB) X),
constexp(arg). (1.34)
We have verified one condition for the longest path of match with
respect to these assertions. This path is followed when the pattern
and the argument are both nonatomic and when the recursive calls
on match successfully return a substitution. In writing our verifica¬
tion condition, we use the same abbreviations the program does, i.e.,
m 1 = match(car{pat), car(arg)) (1.35)
and
m2 = match(varsubst(m 1, cdr(pat)), cdr(arg)).
In proving a property of a recursively defined program, we follow
Manna and Pnueli (1970) and assume that property about the re¬
cursive call to the program. Thus, for this program we have the
inductive hypotheses
constexp(cariarg)) Ami A NOMATCH D
varsubst(m 1, car(pat)) = car(arg)
(the program works for the car of the pattern) and
constexp(cdr(arg)) A m2 NOMATCH Z>
varsubst(m2, varsubst(m 1, cdr(pat))) = cdriarg) (1.36)
(the program works for the instantiated cdr of the pattern).3 The
verification condition generator would split both of these hypotheses
into three cases; we will consider only the case in which the anteced¬
ents of both implications are true. Hence, we assume that both the
recursive calls to the pattern matcher succeed in finding matches.
3 Actually, in order to assume the inductive hypotheses we must ensure that the input
assertion is satisfied for the recursive calls, in other words, that constexp(car(arg)) and
constexp{cdr{arg)). This follows immediately from the input assertion for the entire
program, constexp(arg).
26 REASONING ABOUT PROGRAMS
Since arg contains no variables, neither does car(arg). Thus, the goal
simplifies to
car(arg) = car(arg).
varsubst(compose(m2,7721), cdr(pat))
simplifies to
1 <F <NN,
A = AP,
1<M<F<N<NN
(STRIP (BAGA A 1 M— 1)) < (STRIP (BAGA A M NN))
(STRIP (BAGA A 1 N)) < STRIP (BAGA A N+l NN))
(BAGA A 1 NN) = (BAGA AP 1 NN).
31
32 REASONING ABOUT PROGRAMS
The assertion q2 is
1<M<F<N<NN
(STRIP (BAGA A 1 M—1)) < (STRIP (BAGA A M NN))
(STRIP (BAGA A 1 N)) < (STRIP (BAGA A N+l NN))
M<I
J<N
(STRIP (BAGA A 1 I- 1)) < R < (STRIP (BAGA A J+l NN))
(BAGA A 1 NN) = (BAGA AP 1 NN).
The assertion q3 is the same as the assertion q2, with the addi¬
tional conjunct
R < A[I].
4.4.2 The Proof
All but one of the verification conditions for this program were
proved fairly easily. The one difficult condition corresponds to the
path beginning at q3 that follows the heavy line and finally ends at
qx. The verification-condition generator supplied us with the following
hypotheses:
I<J, (1.52)
-|(I+1 < J—1), (1.53)
F<J-h (1.54)
(STRIP (BAGA A' 1 J— 1)) < (STRIP (BAGA A' (J—1)+1 NN)),
(1.55)
Examples 33
where
A' = (EXCHANGE A I J),
the array that results when elements A[ 1 ] and A[J] are interchanged
in A.
The proof sketched below roughly parallels the proof produced by
the inference system. Portions of the trace are shown in Section 7.
The (J-D+l term in the goal (1.55) is simplified to J, giving the
goal
(STRIP (BAGA A' 1 J—1)) < (STRIP (BAGA A' J NN)). (1.56)
The difficulty in the proof arises from the uncertainty about whether
J < I. We are reasoning about an array segment, and it is not clear
whether that segment is affected by the exchange or not. Hand
analysis of the hypotheses (1.52) and (1.53) reveals that I = J or I =
J-l. The value of a term like (BAGA (EXCHANGE A I J) 1 J—1)
depends on which possibility is actually the case.
The system “simplifies” the term into
Intuitively, if J < I, then both I and J are outside the bounds of the
array segment, whereas if I < J, then the array segment loses A[I]
but gains A[J].
Similarly, the term
is “simplified” into
(1.61)
Since I = J, (1.60) follows from (1.48) and (1.49), and (1.61) follows
from (1.48) alone.
Work on the goal (1.59) proceeds in the second context, in which
I< J. Since J-l < 1+1 (1.53), we know (BAGA A 1+1 J-l) is empty.
Conclusion 35
The goal (1.62) follows from the hypotheses (1.48) and (1.49). The
goal (1.63) follows from (1.48). The goal (1.64) follows from (1.49)
and (1.51). The goal (1.65) follows from (1.51) and (1.48). This
completes the proof.
This proof is the most complex achieved by our deductive system
so far.
5. Conclusion
The deductive system has the overall structure shown in Figure 1.7. The
names on the chart are either function names or goal classes. Only important
substructures and relationships are included.
• The rule ANDSPLIT takes a goal that is a conjunction of two or more expres¬
sions 5 and tries to prove each conjunct independently.
4 Bullets are used to indicate the beginning of the description of a new function.
5 Variables with double prefixes, or respectively match or evaluate to a
sequence of terms rather than a single term. In the rule, for example, Y can be bound to
a set of terms, including the empty set.
6 The right bracket represents a string of right parentheses long enough to balance the
expression.
7 The ATTEMPT statement is a conditional expression that tests for failure rather than
falsehood, and has the additional power to restrict and control the effects of backtracking.
For instance, suppose an expression of the form (ATTEMPT P THEN Q ELSE R) is being
evaluated. If the evaluation of P is completed successfully, then Q is evaluated. On the
other hand, if the evaluation of P results in a failure, then R is evaluated. A failure in P
cannot cause the ATTEMPT statement to fail. A failure in Q or R, however, will cause the
ATTEMPT statement to fail as usual.
8 The ANDSPLIT rule occurs in several goal classes. The variable GOALCLASS that
occurs in ANDSPLIT is bound by the system to whatever goal class was in effect when
ANDSPLIT was invoked. Thus, ANDSPLIT applies to each conjunct the same goal class
that was applied to the entire conjunction.
Appendix: Annotated Listing of the Deductive System 39
will be generated. However, (AND) is an assertion in the data base, and so the
rule will then succeed.
ORSPLITMANY =
(LAMBDA (OR «-X «-Y ^W)
(ATTEMPT (GOAL SGOALCLASS $X)
ELSE
(GOAL SGOALCLASS (OR $Y $Z $$W)
PROOFSWITCH=
(LAMBDA (<-F <-X)
(PROG (DECLARE)
(IF (EQUAL $F (QUOTE EQ))
THEN
(GOAL SEQRULES ($F $X))
ELSE
(GOAL SINEQUALITIES ($F $X)))
(ASSERT ($F $X))
(RETURN ($F $X]
6.1. Equalities
EQRULES=
(TUPLE ANDSPLIT ORSPLIT ORSPLITMANY RELCHECK EQTIMESDIVIDE
EQSUBST LEIBT LEIBF LEIBB LEIBS EQSIMP PROOFLEIB)
• The rule RELCHECK merely checks the property lists of the expressions to
see if they are already known to be equal:
• To prove /(x) = f(y), try to prove x = y: this form of Leibniz’s law for func¬
tion applications is expressed by the rule LEIBF. The analogous rules for tuples,
sets, and bags are expressed by LEIBT, LEIBS, and LEIBB respectively.
The LEIBF rule asks the user if he wants that rule to be applied. The function
ASK that performs the interaction is described in the section on utility functions.
• EQSIMP and PROOFLEIB are very time-consuming but also very powerful.
EQSIMP says: to prove x = y, simplify x and try to prove that the simplified x
is equal to y.
Since the program uses the BACKTRACK option, and since EQ implicitly
takes a set as its argument, EQSIMP can work on y as well as on x. In other
words, if it fails to simplify x, it will go ahead and try to simplify y.
6.2. Inequalities
INEQUALITIES =
(TUPLE ANDSPLIT RELCHECK ORSPLIT ORSPLITMANY PROOFSIMP
INEQIFTHENELSE INEQSTR1PBAG INEQSTRIPSTRIP
INEQSTRIPTRAN GTQLTQ LTQMANY FSUBSTRACT1
FSUBTRACT2 INEQTIMESDIVIDE EQINEQMONOTONE LTQPLUS
PROOFLEIB INEQLEIB)
42 REASONING ABOUT PROGRAMS
X1 <x2< <Xn,
INEQIFTHENELSE=(LAMBDA
(«-F ^wi (IFTHENELSE ^X <~Y <~Z) *+W2)
(PROG (DECLARE VER1CON)
(ATTEMPT (SETQ +-VERICON
(CONTEXT PUSH LOCAL))
(ASSERT $X WRT SVERICON)
THEN
(GOAL SINEQUALITIES
($F $$W1 $Y $$W2)
WRT SVERICON))
(ATTEMPT (SETQ <~VERICON
(CONTEXT PUSH LOCAL))
(DENY $X WRT SVERICON)
THEN
(GOAL SINEQUALITIES
($F SSWl $Z $$W2)
WRT SVERICON)
ELSE
(RETURN (SUCCESS WITH
INEQIFTHENELSE]
For example, suppose the goal is (IF x THEN y ELSE z) < w. This rule
establishes two subcontexts of the local context. In one of these contexts, x is
true; in the other, x is false. In the first context, the rule tries to prove y < w,
whereas in the second, it tries to prove z < w. Note that the subsystem that
stores equalities and inequalities will cause a failure if an assertion (or a denial)
would lead it to contradict what it knows. In that case the goal is considered to be
achieved.
succeeds vacuously with any inequality relation where one of the arguments is
(STRIP (BAG)).
6.3. Deduce
DEDUCE=
(TUPLE RELCHECK ANDSPLIT ORSPLIT ORSPLITMANY LTPLUS
FSUBTRACT1 FSUBTRACT2 LTQPLUS NOTATOM CONSTCAR
CONSTCDR)
6.4. Simplification
• The top-level simplification function is SIMPONE. This function does not try
to simplify its argument completely. It will find a partial simplification; repeated
applications, if necessary, will completely simplify the expression.
The simplification rules may, of course, be added by the user. We expect that
each simplification rule should make the expression simpler in some sense.
Otherwise, the program may loop interminably.
being completely simplified. It asks the user for permission to go ahead. It tries
a goal class, TOPRULES, on the expression.
• TOPRULES is a set of rules that work on the top level of the expression:
TOPRULES=
(TUPLE HASSIMP FAILINTODOWNRULES PLUSOP TIMESOP MINUSOP
FIFTHENELSE BAGAOP SUBSTOP EXPZERO EXPEXP SUBPLUS
SUBNUM GCDEQ ACCH CONSD1FF DIFDIF D1FFCONS DIFFONE
MAXPLUS MAXONE BAGSTRIP ACCEX EQNUMB)
If any of these rules apply, SIMPONE returns the simplified expression as its
value. Otherwise, it tries to simplify some subexpression of the given expression:
• SIMPONE puts the simplified expression on the property list of the original
expression. In this way, if it ever comes across the original expression again, one
of the TOPRULES, HASSIMP, will immediately know what simplification was
found before.
FAILINTODOWNRULES=(LAMBDA «-X
(IF (IN (STYPE $X)
(TUPLE TUPLE SET BAG))
THEN
(FAIL GOAL)
ELSE
(FAIL]
SIMPONE will then apply the DOWNRULES to the argument to see if any of
its subexpressions can be simplified.
• One of the most general TOPRULES is EQNUMB, which replaces any ex¬
pression by the “smallest” known equal expression:
translates into
IF w THEN/(x) ELSE/(v).
Appendix: Annotated Listing of the Deductive System 47
Some inequality rules that know about numbers are presented below.
• LTQPLUS says that to prove i< j+k, one should prove i </ and 0 < k:
First, the rule attempts to prove that i < / and 0 < k. If either of these proofs
is unsuccessful, then the backtracking mechanism will interchange the bindings
of the arguments of LTQPLUS. This then leads to an attempt to prove i < k
and 0 </.
It means: to prove i < j+k, prove i < j and 0 < k. It can backtrack to reverse the
roles of / and k.
• FSUBTRACT1 and FSUBTRACT2 allow us to remove subtraction from the
goal; for example, to prove x-y < z, try to prove x <x+z-
• EQINEQMONOTONE says: to prove w+x < y+z, prove w < y and x < z or
w <z and x
EQINEQMONOTONE= (LAMBDA («-L (PLUS <-X)
(PLUS «-Y <-Z))
(PROG (DECLARE)
($ASK PROVE ('($L $W $Y))
AND
('($L $X $Z))
?)
(GOAL SGOALCLASS
(AND ($L $W $Y)
($L $X $Z]
BACKTRACK]
This rule says: to prove w < (x/y)*z, say, in the case that 0 <y, try to prove
w*y <x*z.
These demons make their assertions with respect to the current context,
VERICON.
• Whenever x+y <x+z is asserted, we want to conclude thaty <z:
• Whenever w—x < y is asserted, assert w < x+y, simplifying the right side if
possible.
(WHEN EXP (LTQ (SUBTRACT MV <~X)
MO
INDICATOR MODELVALUE THEN
(PROG (DECLARE RTSIDE)
(SETQ MfTSIDE
(STRYALL SPLUSRULES
(' (PLUS $Y $X]
(ASSERT (LTQ $W SRTSIDE)
WRT SVERICON))))
(STRYALL SPLUSRULES
('(PLUS $Y $X
(MINUS 1))))
(DENY (LTQ $W SRTSIDE)
WRT SVERICON]
Much of the knowledge the system has about numbers is embedded in the
simplifier. For efficiency, these rules have been arranged hierarchically. For
example, only one rule, PLUSOP, in TOPRULES deals with sums.9
Flowever, this one rule coordinates a multitude of other rules. All the rules that
operate on plus expressions are in the goal class PLUSRULES.
The strategy PLUSOP uses is to apply all the PLUSRULES to its argument until
no further simplification is possible. (The function TRYALLFAIL, that expresses
this strategy, is described among the utility functions.) If PLUSOP can find no
simplification at all, it fails.
Most of the PLUSRULES are quite simple.
(i.e., +x = x).
• x+0 = +x:
9 A pattern (PAND pat\ pat2) will match an argument if and only if pat\ and pat2
both match that argument.
Appendix: Annotated Listing of the Deductive System 51
0 + x = +x,
x + 0+y=x+y,
x+y + 0 + z= x+y+z,
• ((xi+X2+...)+yi+y2+-) = (xi+x2+...+);i+y2+-):
• x+(—x)+y = +y:
• x+(y—z)+w = x+y+w+(—z):
• x+x+y = 2 *x+y:
TIMESRULES =
(TUPLE TIMESEMPTY TIMESSINGLE TIMESZERO TIMESONE TIMESPLUS
TIMESTIMES CANCEL SQRULE TIMESEXP TIMESDIVIDEONE)
TIMESEMPTY=(LAMBDA (TIMES) 1)
• 0*j = 0:
TIMESZERO=(LAMBDA (TIMES 0 <-*-Y) 0)
• 1 *x = x:
x*0*y*z = 0,
and so forth.
• x*(y/x)*z = y*z:
• x*x*y - x2* y:
• x*xn*y = xn + 1 *y~.
• To the reader who has gotten this far, MINUSOP will be self-explanatory:
MINUSOP=
(LAMBDA (MINUS <-X)
(GOAL (TUPLE MINUSZERO MINUSMINUS MINUSPLUS)
(MINUS $X]
54 REASONING ABOUT PROGRAMS
Note that MINUSOP, unlike PLUSOP and TIMESOP, does not apply all
the rules to the expression, but will return the value of the first rule that does
not fail.
• -0 = 0:
MINUSZERO=(LAMBDA (MINUS 0) 0)
• -(-*) = *:
• -(x+y) - (-x)+(-^):
At present there are only two subtraction rules, and so we do not combine
them into one operator:
• x-y=x+(-y):
• If x and y are both numbers and not variables, SUBNUM actually evaluates
x-y:
The “=” sign forces the system to evaluate what it would otherwise merely
instantiate. INSIST is another utility function. Two more rules about expo¬
nentiation are given below.
• x° = 1:
• (xyy =xy**:
EXPEXP=(LAMBDA (EXP (EXP «-X <-Y) ^Z)
(STRYSUB STIMESRULE ON ('(TIMES $Y $Z))
IN
('(EXP $X (TIMES $Y $Z]
Appendix: Annotated Listing of the Deductive System 55
• (ACCESS (CHANGE A I T) I) = T,
I J D (ACCESS (CHANGE A I T) J) = (ACCESS A J ):
ACCH is one of the TOPRULES, as are the rules below, ACCEX, MAXONE,
MAX, and MAXPLUS.
• If
(MAXA A I J)<A[J+1],
then
(MAXA A I J) >A[J+1],
then
MAXPLUS=(LAMBDA
(MAXA <-l (PLUS 1))
(PROG (DECLARE)
(ATTEMPT (GOAL SDEDUCE (LTQ (MAXA $A $1 SJ)
(ACCESS $A (PLUS $J 1]
THEN
(RETURN (ACCESS $A (PLUS $J 1))))
(GOAL SDEDUCE (LT (ACCESS $A (PLUS $J 1))
(MAXA $A SI $J))
(RETURN (MAXA $A $1 $ J ]
• Recall that (BAGA A I J) is (BAG A[I], A[I+1], ..., A[J]). Because of the
crucial part this function plays in assertions about sortlike programs, we have
many rules for it.
Appendix: Annotated Listing of the Deductive System 57
BAGARULES=
(TUPLE BAGAPLUS BAGAEMPTY BAGAII ARGSIMP BACH BAGEX BAGEX1
BAGAMINUS BAGALOWERPLUS BAGEXCOMPLICATED)
• These rules are controlled by the rule BAGAOP, one of the TOPRULES:
• If I < J+l, then (BAGA A I J+l) = (BAG A[J+1] (STRIP (BAGA A I J))):
• IfL<M, then
BAGALOWERPLUS=
(LAMBDA (BAGA SARNAME -HM)
(PROG (DECLARE F LOWER UPPER W)
(EXISTS (<-F (STRIP (BAGA SARNAME SLOWER
SUPPER))
*~-W))
(GOAL SDEDUCE (EQ SLOWER (PLUS 1 $L)))
(RETURN (BAG (ACCESS SARNAME $L)
(STRIP (BAGA SARNAME (PLUS 1 $L)
$M]
(BAGA (CHANGE A J T) I K) =
(The notation ~ means the difference between two bags.) In other words,
making an assignment to an array element whose index is outside the bounds
of a segment does not affect the segment. However, if the index is within
bounds of the segment, then the corresponding bag will lose the old value of the
array element but gain the new value:
BACH=
(LAMBDA
(BAGA (CHANGE <~A <KT <-T) «-I «-K)
(PROG
^DECLARE)
(ATTEMPT
(GOAL SDEDUCE (LTQ $1 $J $K))
THEN
(RETURN
(=
($TRY
SDIFFRULES
Appendix: Annotated Listing of the Deductive System 59
(STRYSUB
(TUPLE ACCH ACCEX)
ON
(' (ACCESS $A $J))
IN
(STRYSUB SBAGARULES ON ('(BAGA $A $1 $K))
IN
(' (DIFFERENCE (BAG $T
(STRIP (BAGA $A $1 $K)))
(BAG (ACCESS $A $J))))))))))
(GOAL SDEDUCE (OR (LT $J $I)(LT $K $J)))
(RETURN (BAGA $A $1 $K]
The rule BACH contains many recommendations about possible future sim¬
plifications. These recommendations are included to promote efficiency; the
simplifier would eventually try the recommended rules even if the advice were
omitted. The advice-giving functions TRY and TRYSUB are described in the
section on utility functions.
• If elements A[I] and A[J] are exchanged, and if J is in the array segment and
I is not, or if I is in the segment and J is not, then the corresponding bag is
indeed affected by the exchange operation. For instance, in the case in which J
60 REASONING ABOUT PROGRAMS
is in the segment and I is not, if the segment is bounded by L and M, the new
bag is
(BAG (STRIP (BAGA ALJ-1)
A [I]
(STRIP (BAGA A J +1M))):
BAGEX1=
(LAMBDA
(BAGA (EXCHANGE <~A «-I «-J) <-M)
(PROG (DECLARE)
(GOAL $DEDUCE (LTQ $1 $J))
(ATTEMPT (GOAL SDEDUCE (AND (LT $1 $L)
(LTQ $L $J)
(LTQ $J $M)))
THEN
(RETURN (BAG (STRIP (BAGA $A $L (SUBTRACT $J 1)))
(ACCESS $A $1)
(STRIP (BAGA $A (PLUS 1 $J) $M))))
(ATTEMPT (GOAL SDEDUCE (AND (LT $M $J)
(LTQ $L $1)
(LTQ $1 $M»)
THEN
(RETURN (BAG (STRIP (BAGA $A $L (SUBTRACT $1 1)))
(ACCESS $A $J)
(STRIP (BAGA $A (PLUS 1 $1) $M»»
ELSE
(FAIL]
BAGEXCOMPLICATED=
(LAMBDA
(BAGA (EXCHANGE <-A <-I «-J) <~h «-M)
(PROG
Appendix: Annotated Listing of the Deductive System 61
(DECLARE)
(GOAL SDEDUCE (LTQ $1 $J))
(ATTEMPT (GOAL SDEDUCE (AND (LTQ $L $1)
(LTQ $M $J)))
THEN
(RETURN (IFTHENELSE
(LT $M $1)
(BAGA $A $L $M)
(BAG (STRIP (BAGA $A $L (SUBTRACT $1 1)))
(ACCESS $A $J)
(STRIP (BAGA $A (PLUS 1 $1) $M))))))
(ATTEMPT (GOAL SDEDUCE (AND (LTQ $J $M)
(LTQ $L $J)»
THEN
(RETURN (IFTHENELSE
(LTQ $L $1)
(BAGA $A $L $M)
(BAG (STRIP (BAGA $A $L (SUBTRACT $J 1)))
(ACCESS $A $1)
(STRIP (BAGA $A (PLUS 1 $J) $M)))))
ELSE
(FAIL]
• To prove that every element in an array segment is less than (or less than or
equal to) some quantity C, find an array segment that properly contains the
given segment such that every element in the larger segment is less than some
element D that is, in turn, less than or equal to C:
INEQSTRIPTRAN=
(LAMBDA (-HF (STRIP (BAGA ^ARNAME <-L <-M))<-C)
(PROG (DECLARE LOWER UPPER D)
(EXISTS ($F (STRIP (BAGA SARNAME SLOWER
•HJPPER)) -HD))
(GOAL SDEDUCE (AND (LTQ SLOWER $L)
(LTQ $M SUPPER)
(LTQ $D SC]
• To prove some ordering relation < or < between all the elements of two array
segments, Sx and S2, find relations of the same sense involving Si' and C, and
62 REASONING ABOUT PROGRAMS
INEQSTRIPSTRIP=
(LAMBDA (<-F (STRIP (BAGA ^A <~1 <-]))
(STRIP (BAGA ^A <-L)))
(PROG (DECLARE LOWER 1 UPPER 1 LOWER2 UPPER2 C D)
(ATTEMPT (EXISTS ($F (STRIP (BAGA $A SLOWER 1
<-UPPERl))
<-C))
(EXISTS ($F -<-D
(STRIP (BAGA $A ^LOWER2
^UPPER2))))
(GOAL SDEDUCE (AND (LTQ SLOWER] $1)
(LTQ $J SUPPER 1)
(LTQ SLOWER2 $K)
(LTQ $L SUPPER2)
(LTQ $C SD)))
ELSE
(FAIL]
We have accumulated a number of rules about bags. Many of these rules have
set-theoretic counterparts, which could have been included, but we have needed
only bags in our proofs.
We use the QA4 function DIFFERENCE to mean the difference between
bags, written informally as
• (BAG xj>)~(BAG x) = (BAG_y):
• (x ~_y) ~ z - x ~_y ~ z:
• consix, y) ~ (BAG x) ~ u = y ~ u:
The rules in this section were added to prove assertions about the pattern
matcher and the unification algorithm.
• If an expression is made of constants, so is the car and the cdr of the expres¬
sion:
varsubst(s, x) = y:
• Similarly, to prove
varsubst(s, x) = y:
• To prove
varsubst(s, x) = y,
where x and y are nonatomic, prove
SUBSTCONS=
(LAMBDA (EQ (VARSUBST +-S1 <-X) <-Y)
(PROG (DECLARE)
(GOAL SDEDUCE (NOT (ATOM $X)))
(GOAL SDEDUCE (NOT (ATOM $Y)))
Appendix: Annotated Listing of the Deductive System 65
EQSUBSTRULES=
(TUPLE SUBSTCAR SUBSTCDR SUBSTCARCDR SUBSTCONS)
Note that SUBSTCONS removes EQSUBST from the EQRULES. This avoids
the loop that would occur if SUBSTCAR were applied after SUBSTCONS.
• To prove
varsubst(s, u) = varsubst(s, v),
• If v is a variable,
varsubst(((wy)), v)-y:
66 REASONING ABOUT PROGRAMS
SUBSTRULES=
(TUPLE SUBSTEMPTY SUBSTLIST SUBSTCOMPOSE SUBSTCONST)
• TRY is like a GOAL statement that will not fail if none of the goal class
applies but instead returns its argument.
• TRY ALL will try a goal class on an expression. If any member of the goal
class applies, it will apply the same goal class to the resulting expression, and so
on, until no rule applies. TRYALL returns the last expression it has derived,
which may be the same as the first expression; TRYALL will not fail:
TRYALL=
(LAMBDA (TUPLE ^GOALCLASSl -‘KjOALI)
(PROG (DECLARE)
TOP (ATTEMPT (SETQ ^GOALl (GOAL SGOALCLASS1
SGOALl))
THEN
(GO TOP))
(RETURN SGOALl ]
Appendix: Annotated Listing of the Deductive System 67
• TRYALLFAIL is like TRYALL, except it will fail if none of the goal class
applies to the argument.
ASK=(LAMBDA *~X
(IF (LISP ASK $X)
ELSE
(FAIL]
It types two expressions, the first a QA4 expression and the second an atom
(e.g., PROVE? or SIMPLIFY?). If the user types YES, TRUE, OK, Y, or T,
ASK returns TRUE; otherwise ASK fails. ASK uses a LISP function of the same
name.
• SHORTEST computes the “smallest” element of a set, bag, or tuple:
SHORTEST=
(LAMBDA <~X
(PROG (DECLARE BEST BESTCOUNT TEMPCOUNT)
(SETQ +-BESTCOUNT 2000)
(MAPC $X (QUOTE (LAMBDA ^Y
(IF (OR (LT (SETQ ^TEMPCOUNT
(LISP QA4COUNT $Y))
68 REASONING ABOUT PROGRAMS
TABLE 1.1
Index of Functions and Goal Classes
0 Goal class.
Appendix: Traces of Solutions 69
SBESTCOUNT)
(EQUAL (STYPE $Y)
NUMBER))
THEN
(SETQ *-BEST $Y)
(SETQ ^BESTCOUNT STEMPCOUNT)))))
$BEST]
1 (CONTEXT (1 0) 1 0)
2 (ASSERT (EQ MAX (ACCESS A LOC)) WRT SVERICON)
3 TRUE
4 (ASSERT (LTQ (STRIP (BAGA A 0 I)) MAX) WRT SVERICON)
5 TRUE
6 (ASSERT (LTQ 0 LOC) WRT SVERICON)
7 TRUE
8 (ASSERT (LTQ LOC I) WRT SVERICON)
9 TRUE
10 (ASSERT (LTQ I N) WRT SVERICON)
11 TRUE
12 (DENY (LT N (PLUS 1 I)) WRT SVERICON)
13 FALSE
14 (DENY (LT MAX (ACCESS A (PLUS 1 I))) WRT SVERICON)
15 FALSE
70 REASONING ABOUT PROGRAMS
We said yes.
35 (FAIL)
36 (GOAL SDOWNRULES (GOAL1)
37 LAMBDA ARGSIMP (STRIP (BAGA A 0 (PLUS 1 I)))
38 LAMBDA SIMPONE (BAGA A 0 (PLUS 1 1))
(BAGA A 0 (PLUS 1 I))
SIMPLIFY?
:Y
In this case, the system knew that 0 < by performing the corresponding
LISP evaluation.
57 ANDSPLIT = TRUE
58 LTQPLUS = TRUE
59 BAGAPLUS = (BAG (ACCESS A (PLUS 1 I)) (STRIP
(BAGA A 0 I)))
72 REASONING ABOUT PROGRAMS
to
(BAG (ACCESS A (PLUS 1 I)) (STRIP (BAGA A 0 I))).
(STRIP (BAG (ACCESS A (PLUS 1 I)) (STRIP (BAGA A 0 I)))) < MAX:
and
(STRIP (BAGA A 0 I)) < MAX from (4),
the proof is complete:
81 PROOFSIMP = TRUE
82 (ASSERT ($F $X))
83 PROOFSWITCH = (LTQ (STRIP (BAGA A 0 (PLUS 1 I))) MAX)
84 (LTQ (STRIP (BAGA A 0 (PLUS 1 I))) MAX)
The following is the trace of the proof for another verification condition
for the program that computes the maximal element of an array. This verifica¬
tion condition is derived from the halt path of the program.
1 (CONTEXT (1 0) 1 0)
2 (ASSERT (EQ MAX (ACCESS A LOC)) WRT SVERICON)
3 TRUE
4 (ASSERT (LTQ (STRIP (BAGA A 0 I)) MAX) WRT SVERICON)
5 TRUE
6 (ASSERT (LTQ 0 LOC) WRT $VERICON)
7 TRUE
8 (ASSERT (LTQ LOC I) WRT SVERICON
9 TRUE
10 (ASSERT (LTQ I N) WRT SVERICON)
1 1 TRUE
12 (ASSERT (LT N (PLUS 1 I)) WRT SVERICON)
The system now knows N+l < 1+1. This assertion wakes up another demon,
which asserts that N < I:
Since I < N has also been asserted (10), the mechanism for storing ordering
relations silently tells the system that I = N.
74 REASONING ABOUT PROGRAMS
The system searches the data base for an assertion of the form (LTQ <-Y),
i.e., the gross form of the goal we are trying to prove. It finds one [assertion
(4)] and asks us if it should try to prove that the argument of the assertion
it has found is equal to the argument of the goal:
The two tuples were found to be equal because N = I (from 10 and 14), and
MAX = A[LOC]. The proof is complete.
The following is the complete trace of the proof included in the body of the
text:
1 (CONTEXT (1 0) 1 0)
Appendix: Traces of Solutions 75
27 (FAIL)
28 LAMBDA ASK (TUPLE (EQ (TUPLE PP (PLUS (TIMES QQ YY)
(TIMES QQ (DIVIDES DD 2))))
(TUPLE PP (PLUS AA BB))) PROVE?)
(EQ (TUPLE PP (PLUS (TIMES QQ YY) (TIMES QQ (DIVIDES DD 2))))
(TUPLE PP (PLUS AA BB)))
PROVE?
:NO
29 (FAIL)
30 (LAMBDA INEQLEIB (LT PP (PLUS (TIMES QQ YY) (TIMES QQ
(DIVIDES DD 2))))
31 (EXISTS ($L (TUPLE SLOWER ^UPPER)))
32 LAMBDA ASK (TUPLE PROVE (LTQ PP PP) AND (LTQ (PLUS
(TIMES QQ YY) (TIMES QQ DD))
(PLUS (TIMES QQ YY) (TIMES
QQ (DIVIDES DD 2))))?)
PROVE
(LTQ PP PP)
AND
(LTQ (PLUS (TIMES QQ YY) (TIMES QQ DD)) (PLUS (TIMES QQ YY)
(TIMES QQ (DIVIDES DD 2))))
?
:NO
33 (FAIL)
After several false starts, the system uses hypothesis (10), to generate two sub¬
goals: PP < PP and AA + BB < QQ*YY + QQ*(DD/2). We give our approval of
this tactic:
YES
35 ASK = TRUE
It divides the second subgoal into two sub-subgoals: AA < QQ*YY and BB
QQ*(DD/2):
: YES
50 ASK = TRUE
51 (GOAL SGOALCLASS (AND ($F (TUPLE $W $Y)) ($F (TUPLE $X
$Z))))
52 LAMBDA ANDSPLIT (AND (LTQ AA (TIMES QQ YY)) (LTQ BB
(TIMES QQ (DIVIDES DD 2))))
53 (GOAL SGOALCLASS $X)
54 LAMBDA RELCHECK (LTQ AA (TIMES QQ YY))
55 RELCHECK = TRUE
Checking that 2 > 0, the system multiplies out the second subgoal into 2*BB <
QQ*DD. This follows from assertion (4). The proof is complete:
67 INEQTIMESDIVIDE = TRUE
68 (GOAL SGOALCLASS (AND $$Y))
69 ANDSPLIT = (AND)
70 ANDSPLIT = (AND)
71 INEQMONOTONE=(AND)
72 (GOAL SGOALCLASS (AND $$Y))
73 ANDSPLIT = (AND)
74 ANDSPLIT = (AND)
75 INEQLEIB = (AND)
76 (ASSERT ($F $X))
77 (RETURN ($F $X))
78 PROOFSWITCH = (LT PP (PLUS (TIMES QQ YY) (TIMES QQ (DIVIDES
DD 2))))
79 (LT PP (PLUS (TIMES QQ YY) (TIMES QQ (DIVIDES DD 2))))
As an abbreviation, let
ml = match(car(pat), cariarg j)
and
and that
Reasoning that pat is not an atom because it is neither a variable nor a constant,
the system breaks the goal into two subgoals:
We give the system our permission to simplify the left side of the first subgoal,
The system has succeeded in simplifying the left half of the goal into
It now tries to prove this new expression equal to car(arg). In sympathy with
our conscientious readers, we omit portions of the remainder of the trace.
:Y
80 (GOAL STOPRULES SGOALl)
81 LAMBDA HASSIMP (VARSUBST (MATCH (CAR PAT)
(CAR ARG)) (CAR PAT))
82 (FAIL)
82 REASONING ABOUT PROGRAMS
106 (FAIL)
107 LAMBDA SUBSTOP (VARSUBST (MATCH (VARSUBST
(MATCH (CAR PAT) (CAR ARG)) (CDR PAT)) (CDR
ARG)) (CAR ARG))
108 (GOAL SSUBSTRULES $Y)
109 LAMBDA SUBSTCONST (VARSUBST (MATCH
(VARSUBST (MATCH (CAR PAT) (CAR ARG)) (CDR
PAT)) (CDR ARG)) (CAR ARG))
110 (GOAL SDEDUCE (CONSTEXP $Y))
11 1 LAMBDA RELCHECK (CONSTEXP (CAR ARG))
1 12 LAMBDA CONSTCAR (CONSTEXP (CAR ARG))
113 (EXISTS (CONSTEXP $X))
114 CONSTCAR = (CONSTEXP ARG)
115 SUBSTCONST = (CAR ARG)
1 16 SUBSTOP = (CAR ARG)
117 (RETURN SSIMPGOAL)
118 SIMPONE = (CAR ARG)
Only a selection from the trace for the interesting verification condition of
FIND is presented here because the entire trace was more than 500 lines long.
We will focus on the use of the case analysis during the proof.
The antecedent hypotheses for this condition are
1 <M < F < NN
M<I
J<N
(STRIP (BAGA A I M— 1)) < (STRIP (BAGA A M NN))
A[J] <R
R< A[I]
I<J
J-l <1+1
F< J-l
A [J ]
(STRIP (BAGA A 1+1 J-l)))))
Since the left side of the goal has an IF-THEN-ELSE form, it causes the rule
INEQIFTHENELSE to be applied. This rule sets VERICON to be a new lower
context and asserts
J-l <1
with respect to the new VERICON. This question triggers off a demon:
The new assertion triggers off another demon, which makes still another asser¬
tion with respect to VERICON:
J<I.
(Later in the proof, another context will be established; J-l < I will be denied
with respect to the new context.)
The THEN clause of the IF-THEN-ELSE expression must now be proved less
than or equal to the right side of the goal:
This goal is attempted with respect to the new context VERICON. In other
words, we are trying to prove
Since the right side of the inequality is still in IF-THEN-ELSE form, the rule
INEQIFTHENELSE applies again. A new context VERICON, even lower than
the last, is established, and the (redundant) statement
J<I
The simplifier is invoked. We will omit some steps from the trace here and
mention only that the rule BAGALOWERPLUS played an important part in the
simplification of the second element of the tuple.
INEQSTRIPBAG breaks up the goal into two subgoals. The first of these goals is
This goal invokes the rule INEQSTRIPTRAN. We will examine the operation
of this rule in detail:
The system is testing whether the array segment between 1 and I—1 includes the
Appendix: Traces of Solutions 89
That goal was established by the rule INEQIFTHENELSE. This rule asserted
J < I with respect to a lower context and set up the goal with respect to that
context. The rule now attempts to deny J < I with respect to another context
and to establish a new goal with respect to the new context.
However, J < I was also asserted with respect to a higher context in line 6.
Therefore, denying J < I contradicts this assertion, causing the denial to fail.
Since the situation is contradictory and could not arise, it is unnecessary to
achieve the goal, and the call to INEQIFTHENELSE from line 9 returns
successfully:
The goal established in line 7 has been achieved. This goal was set up by an
earlier call to INEQIFTHENELSE (line 3) with respect to a context in which
J—1 < I was asserted (line 4). It is now necessary to set up a new goal with
respect to a new context; in this new context, J—1 < I is denied:
J<I:
A [J ]
Again the rule creates two contexts: In one context J < I is asserted, and in the
other J < I is denied. However, since J < I was denied in a higher context (line
199), the assertion of J < I fails; this contradictory case can safely be ignored,
and attention focuses on the second context:
The goal is established using the ELSE clause of the previous goal,
A[J]
(STRIP (BAGA A 1+1 J-l))))
The proof from this point will only be summarized, since it is lengthy but
uneventful. The goal is divided into nine subgoals by successive applications
of INEQSTRIPBAG. Each of these goals turns out to be easily proved, and the
proof ends successfully.
Acknowledgments
The work on program verification was done in close collaboration with
Bernie Elspas. The work on QA4 was done with Jeff Rulifson and Jan Derksen.
Irene Greif wrote the first version of the simplifier and participated in the con¬
ceptualization of the pattern matcher and unification proofs. Jeff Rulifson en¬
couraged us to write this paper and suggested its format. Rich Fikes has
helped with design modification and debugging of QA4. Bert Raphael read the
manuscript and suggested many improvements. Tony Hoare read and com¬
mented on the entire final draft; much of his advice was incorporated in the
published paper. This work has benefitted from our conversations with Cordell
Green, Peter Neumann, Larry Robinson, Earl Sacerdoti, Rene Reboh, Mark
Stickel, Steve Crocker, and John McCarthy. Many members of the Artificial
Intelligence Center and the Computer Science Group at SRI helped with support
and criticism.
The research reported herein was supported in part by the National Science
Foundation under Grant GJ-36146 and in part by the Advanced Research Pro¬
jects Agency under Contract DAHC04-72-C-0008 and by the National Aeronau¬
tics Space Administration under Contract NASW-2086.
Chapter 2
Logical Analysis of Programs
Shmuel Katz and Zohar Manna
1. Introduction
93
94 LOGICAL ANALYSIS OF PROGRAMS
2. Preliminaries
and for proving termination. They will be used both to denote rela¬
tions among the number of times various paths have been executed
and to help express the values assumed by the program variables. It
should be noted that it is unnecessary to add the counters physically
to the body of the program. Their location can merely be indicated,
since their behavior is already fixed.
It is sometimes convenient to add auxiliary cutpoints at the en¬
trance and exit of a block. In addition, we always add a special cut-
point on each arc immediately preceding a HALT statement. Such
cutpoints will be called haltpoints of the program.
A typical situation is shown in Figure 2.1. There is an inner block
with cutpoint M and counter m, and an outer block with a cutpoint
TV and counter n. The outer block also has auxiliary cutpoints L and
K at the entrance and exit of the block, respectively.
Our first task is to attach an appropriate invariant qfx, y) to each
cutpoint i. We first define our terms.
A predicate qfx, y) is said to be an invariant at cutpoint i w.r.t.
fix) if for every input a such that f(a) is true, whenever we reach
point i with y = b, then qfa, b) is true. An invariant at i is thus
some statement about the variables which is true for the current
values of the variables each time i is reached during execution.
For a path a from cutpoint i to cutpoint /, we define Ra(x, y)
as the condition for the path a to be traversed, and ra(x, y) as
the transformation in the y values which occurs on path a. A set
S of points of a program P is said to be complete if, for each cut-
point i in S, all the cutpoints on any path from START to i are
also in S. For example, if L is the entrance to the program in Figure
2T, {L}, {L, M, TV} and {L, M, TV, K} are all complete sets of cut-
points; {I, TV} is not.
We shall use the following sufficient condition [proven in Manna
(1969)] for showing that assertions (“candidate invariants”) are
actually invariants.
v
i-1
i n <-0 i
\/x[f(x)/\Ra(x) D qj(x,ra(x))],
Intuitively, condition (a) implies that qx(x, y) holds the first time
the cutpoint 1 is reached, while the first formula of (b) states that if
qx(x, y) holds at the cutpoint, it is still true after the loop is execu¬
ted. Thus, by induction it follows that qx(x, y) holds whenever cut-
point 1 is reached, i.e., it is an invariant at 1. The second formula of
(b) states that if qx(x, y) holds at cutpoint 1, then q2(x, y) holds at
cutpoint 2. Thus, since qx(x, y) is an invariant at 1, q2(x, y) is an
invariant at 2.
Note thft the input predicate fix), which depends only on 3c
(variables not changed during execution), is automatically an in¬
variant of any cutpoint of the program, and does not need any
further justification.
Lemma A is slightly misleading, because it implies that a full-
fledged set of assertions is provided at a complete set of the cut-
points and that these are checked simultaneously. In practice,
the invariants will be added one after another until the needs of the
logical analysis have been met. At every stage of the invariant gen¬
erating process, a situation as in Figure 2.3 will apply for each block.
At cutpoints L, N, and M, invariants p(x, y), q(x, y), and s(3c, y),
respectively will already have been proven. However, we also will
1 Note that the y values are not defined at the START statement, and that they are
initialized by constants or functions of x along a path from START. Thus, Ra and r
for such a path are really only functions of x, and not of y.
Preliminaries 99
START
c
rx
1 inpu* specification i
d>(*)
i_I,_i
r- q(i)
i' ►
_'
assertion n—n*l •
'__ J
——f
y — Mx.y) y — f (x,y )
-f
~li
|-^ --“-I
, assertion
! q2(i.y) J
have promising candidate invariants p'(x, y), q'(x, y) and s'(x, y),
which we have so far been unable to prove invariant. These can¬
didates could originate as comments given by the user or, as in the
case of s'(x, y), from the output specification, which we automatically
designate as a candidate at the haltpoints. As indicated in Section 4,
additional candidates may be generated during this process.
For a block of the form given in Figure 2.3, we concentrate on
developing invariants at cutpoint N on the loop. For the auxiliary
cutpoint M, the invariants are generated by “pushing forward” any
invariant obtained at N. Thus, if at any stage an invariant q(x, y)
has been established at N, we automatically can take as an invariant
at M any s(5c, y) satisfying
candidate p’(*,y)i
1 L
y- g(*.y)
I n -^o I
I_, J
invaricnt q(* ,y)]
candidate q'(*,y)
1-
t(i \_F
then the next values of y at the outpoint [i.e., y(n)] will be the result
of applying ra to y(n - 1).
In practice, if there is only a single path around the loop such as in
the block of Figure 2.3, it usually suffices to ignore the path condi¬
tion Ra, and find invariants which satisfy the stronger condition
y(n) = ra(x,y(n — 1)) for n> 1. (2.2)
Considering (2.2) for each component of y, we have a set of
recurrence equations, one for each yj. We now attempt to express
as many as possible of these equations in iterative form, e.g., as
"_ n
2 Si(x,y(i- 1)) and 2 gk(x,y(i- 1)),
1=1 /=i
or between
then we can use this to connect yt(ji) and yh{ri). Once we have rela¬
tions which are true for all n > 0, with all variables in the form y^n),
we can simplify by replacing each yt{n) by jq, obtaining an in¬
variant which may still contain occurrences ofy,(0).
Whenever possible, known information from the entry invariant
p(x, y) may be used to obtain y(0). When the variables are initialized
immediately before entering the loop, p(x, y) will indicate the exact
values of y(0). However, even when this is not the case, p(x, y) may
often contain valuable information about y(0).
It is important to note that any predicate obtained as above,
say from (a') or (V), is not simply a candidate for an invariant, but
is actually an invariant. This is because substituting the correct initial
value in place of y(0) ensures that the relation obtained is true the
tirst time the cutpoint is reached, and the use of ra(x, y) in obtaining
the recurrence equations ensures that the relation is true at sub¬
sequent times the cutpoint is reached.
Recall that the transformation from the recurrence equation (2.1)
to (2.2) was made under the assumption that there was a single path
around the loop as in Figure 2.3. The above discussion can easily
be extended to the case of a loop with several possible paths—by
using if-then-else expressions. For example, considering the loop of
Figure 2.4, with two paths around the loop, Equation (2.1) expands
to two equations:
Since tx{x, y) controls the exit from the block, and does not
affect the choice between the two paths around the loop, it can
be ignored, as before, giving the stronger condition
invOr'iant p(*,y)
candidate p' (* ,y)! L
11
y — q( * .y)
n —0
invarlont q(*,y ) j
condidate q' (i , y) i.r
T-\ MT'yW r n-«-n ♦
T A _ F
y — h(*,y) \ >2 (»■ y)y
>1- i M t
>J } y — fi(*.y) j y— G i *. y) ii
i
±
Figure 2.4. A Block Containing a Loop with Two Paths.
Equations of this form can then be put in iterative form, and treated
just like equations of form (2.2).
Right path:
^ [yi(n)=y1(n-\) A
y2(n)=y2(n-\)/2 A
yz(n)=yz{n-\)!2 A
y*(n)=y4(n-l)].
Left path:
D [ v 1 {n) =y1(n - 1) + y2 (n - 1) A
y2(n) =y2(n - 1 )/2 A
This program is based on Wensley’s (1958) division algorithm. Note that we use a
vector assignment notation, where, for example, (y1} y4) <- (yx +V2’V4+T3/2) means that
y 1 *~y 1 + y2 and*4 <~y4 + y3/2 simultaneously.
106 LOGICAL ANALYSIS OF PROGRAMS
START
r
1 input specification i
i 0 « < *2 A 0 < *3 I
J
1
iy, . y2 ’ ^3 '*4 ) (0 .*2 . 1 >0 ) j
/X/
i n —0 i
N
,__
*3 ) i-"•*-1
output
T
specification
v y3S
:7 .
i n —n »I i
_i
*i< y\*y2
X
y4 s K, /*2
L
(y, .y4^Wi+y2.y4<-y3/2)
IX
HALT
(y2.y;) — (y2/2,y3/2)
(Al) y2 =x2/2n at N,
Generation of Invariants: Algorithmic Approach 107
and
(A2) y 3 = 1/2" at N.
(A3) y2 = x2-y3 at N.
y4(n) =y ( ) +
4 0 2 tif <yi(i - O +y2(i -
X1 0
!=1 then 0
else y O' - l)/2].
3
factoring out x2, and dividing by 2 inside the summation and multi¬
plying by outside, we obtain
2
We now turn to Equation (2.4), using the tests of the loop to gen¬
erate additional invariants. We have the fact
n = 0
V [y3(n - 1) > x3 A *i < y±(n - 1) +y2(n - 1)1 (right path)
V [y3(n - 1) > x3 /\x1 > y1(n — 1) + y2(n - 1)] (left path).
For each path, we now use the equations for y(n) obtained from
(2.1) to express y(n — 1) in terms of y{ri). For the right path we
will use the fact that yx(n) = yx{n - 1), y2(n) = y2(n - l)/2, and
y3(w) = y3(n — l)/2, while for the left path we will use the fact that
Ti(«) = yi(n - 1) + y2(n - 1) and y3(n) = y3(n — l)/2. These
substitutions will yield.
n~ 0
This first possibility is, just as above, the weakest possible assertion
which satisfies (2.5), while the second is the strongest possible. A
very useful third alternative to the above suggestions takes advantage
of the transitivity of certain inequality or equality relations. For
example, if we need a q such that
q /\B<C A A<C
where A, B, and C are any terms, then the relation A < B is a natural
candidate for q'.
Any candidate for q\x, y) obtained from Equation (2.5) must be
checked. Unfortunately, there are no clear-cut criteria for finding a
q\x, y) which will be easy to prove. If we fail to show some candi¬
date q'(x, y) an invariant at TV, some weaker version may nevertheless
succeed. On the other hand, because of the “induction phenomenon”,
mentioned after Lemma A, it is quite possible that a stronger candi¬
date q'(x, y) actually could be more easily proven.
The above equation ensures that the first time TV is reached, q'ix, y)
is true. Of course, in order to complete the proof that q'ix, y) is an
invariant, the corresponding formula for the path around the loop
must be considered.
Note that immediately after every assignment yt «-/(x, y) where
fix, y) does not include yt itself, we know that yt = fix, y) is an
invariant. Also, after every text t(x, y) we can add the invariant
t(x, y) on theT-branch, and ~t(x, y)on the F-branch. Such invariants
can also be pushed forward to generate useful candidates at the
cutpoints.
terms of constant expressions with respect to the block. That is, the
bounds contain only constants, input variables, or other program
variables which are unchanged inside the loop of the block.
Suppose that by considering f(x, y) and the invariant q(x, y) at
N, we are able to identify a variable yj which never decreases along
the path around the loop. Now, if we can infer from p(x, y ) an initial
value yj(0) = E for y}- at N, where E is a constant expression with
respect to the block, then we can conclude that y} > E is an invariant
at N. Similarly, if y} never increases, then ys < E is invariant.
A similar heuristic tries to establish that the variables maintain
some data type, such as integer or real, during execution.
We will first illustrate the application of the heuristics in obtain¬
ing some additional invariants for the program of Example A, and
then present a new example which will illustrate the possible inter¬
play between the algorithmic and heuristic techniques.
Since these conditions are all true, we have shown that the second
alternative is also an invariant, i.e.,
( START )
; *| , *2 «{'Regers)
I
(y, ,y2 ,y3.y4 ) — *2 .' ,0)1
vToX
oN
-L-,
n♦1 . F fy
' m
i___j
0
y3) — (2y2.2y3)
t
T > F
!—yf - y2 1-
i—
m I
i_
(y, .y4)- vy, - y2 y«*y3>
m *
_L_
i y3
i- T i
i output specification >
!(y2,y3)^(y2/2.y3/2)
* < =y-* • * 2 *- y. *
0 < y, < x 2 a
y, , y4 « (integers}
halt
can when the second block is first reached. Then we will employ the
algorithmic techniques to generate invariants at M. Finally, we use
heuristic techniques based on the invariants at L and M and the can¬
didates implied by the output specification at H to generate addi¬
tional invariants at M. We will not go into the problem of which
heuristic rule to use first, but simply indicate how some candidates.
Generation of Invariants: Heuristic Approach 115
Using the bounding variables rule of Section 4.5, we note thatp2 an^
y3 are always increasing around the loop and, since y2(^) ~ x2 ar)d
p3(0) = 1 at N, we obtain the invariants
Note that (B4) could also be obtained directly from (Bl) using the
implicit invariant n > 0.
Using the T-branch of the test yx < y2 and pushing forward to L
the invariants at N, we have the invariants
y2(m)=y2(0)/2m at M,
L3O0 = y3(0)/2m at M.
Using the invariants y2 = x2-2n and y3 = 2n from (B5) to establish
y2(0) andy3(0) at M, we obtain the invariants
Using the same technique for y1 and y4, we obtain the recurrence
relations
in
Li(0) = A y4 (0) = 0 at M.
Generation of Invariants: Heuristic Approach 117
Substituting both possibilities for y1 (0) and y4(0) into the above
equation (2.6), we obtain in both cases yx{m) — xx = — x2’y4(m).
Thus we have the invariant
yi(m)=y1(m - 1)
y2(m)=y2(m - l)/2 (right path).
y3(m)=y3(m - l)/2
m = 0
V [2y3(m) 1 Ayx (m) > 0] (left path)
(B8) 2y3 1 at M.
(B11) y3 > 1 at M.
(B13) y3 = 1 A y2 = x2 A n = m A x4 = y4-x2 + yx A
3 Note that from its definition mf(x, y) always exists as a predicate; for our purposes it
is irrelevant how this predicate is expressed.
Correctness and Incorrectness 121
TABLE 2.1
Applications of the Invariants {q ,-(x, y)}
Lemma B. P terminates over 0 if and only if Lemma B'. P does not terminate over 0
VqVx3h3y[qh(x,y)]. if and only if
3q3x\/hVy[~qh(x, y)].
Lemma C. P is partially correct w.r.t. 0 and Lemma C'. P is not partially correct w.r.t.
0 if and only if 0 and 0 if and only if
3qVxVhVy[qh(x, y) O 0(x, y)). Vq3.x3h3y[qh(5c,y) A ~0(x,y)] •
Lemma D. P is (totally) correct w.r.t. 0 and Lemma D'. P is incorrect w.r.t. 0 and 0
0 if and only if if and only if
\/qVx3h3y [qh(x, y) A 0(x, y)]. 3q3x\/h\/y[qh(x, y) D ~0(x, y)].
i.e., for some input 3c, either the program does not terminate or the
final result is incorrect.
We first illustrate the use of Lemma C for proving partial cor¬
rectness.
V*[0'(x) D 0(3c)] A
3x<j)'(x) A
3q\/x\Jh\/y[(l)\x) A qh(x, y) D ~0(3c, y)].
In general, a proof which establishes incorrectness for a large set
Correctness and Incorrectness 123
of input values is also more useful for the diagnosis and correction
of the logical errors than an incorrectness proof for a single input
value (see Section 6).
We will develop candidates for 0'(x) by starting with 0(x) and add¬
ing conjuncts (restrictions) to 0(x) one after another as the need
arises. Thus 0'(x)D0(x) will be guaranteed true. In case there are
several alternative restrictions at some stage of the process, we prefer
adding the weakest possible, so that 0'(x) will allow maximal free¬
dom in choosing additional restrictions later. At each stage, of
course, it is necessary to demonstrate that 0'(x) is satisfiable.
Note that all invariants which have been proven for 0(3c) will
remain true for any 0'(x) specifying a subset of 0(x). Moreover,
at each stage of the process we now may discover additional invar¬
iants which are true for every x satisfying 0'(x) but are not neces¬
sarily true for every x satisfying 0(x).
Recall that we have not yet provided a practical method for prov¬
ing termination. The difficulty arose from the fact that Lemma B of
Table 2.1 requires proving a “Vq formula”. Therefore we clearly
need a special method for proving termination.
The traditional method suggested by Floyd (1967) involved
choosing a well-founded set (W, >), where > is a partial ordering hav¬
ing the property that there is no infinitely descending chain of ele¬
ments wl > w2 > ••• from W. For every cutpoint i, one must find a
partial function u^x, y) which maps the elements of the variables’
domain into W, and an invariant q{(x, y) which serves to restrict the
domain of ut. A proof of termination requires showing that each
time control moves from cutpoint i to cutpoint / (along a path which
includes no other cutpoints and which is a part of some loop),
ui(x, y) > Uj(x, y). Intuitively, since by definition there is no in¬
finitely decreasing chain of elements in any well-founded set, the
proot implies that no execution path of the program can be infinitely
long.
The use ot Floyd s method entails choosing the appropriate well-
founded set (IF, >), the functions {u^x, y)}, and the invariants
{Qi(x, y)}. We will suggest an alternative method for proving termi¬
nation which will be strongly oriented toward the use of invariants,
so that we may take advantage of the techniques of Sections 3 and 4.
We present the method briefly.
As explained in the Preliminaries section, it is assumed that we can
divide the given program into blocks in such a way that every block
has only one top-level loop (in addition to possible “lower-level”
loops already contained in inner blocks). We treat the inner-most
blocks first, and work outwards. Thus, for each block we can consider
only its top-level loop (with a unique cutpoint), assuming its inner
blocks are known to terminate.
Correctness and Incorrectness 125
The reader should not be misled into assuming that proving termi¬
nation is always as trivial as it seems here. The method of Lemma E
is examined in greater detail (and presented with some nontrivial
examples) in Katz and Manna (1975).
Note that the method of Lemma E, as well as Floyd’s original
method, is useful only for showing termination. If we want to prove
nontermination, both methods are inapplicable (again, all possible
qt s must be checked). Thus Lemma B' should be used.
Another important side benefit of using counters lies in the infor¬
mation provided on the time complexity of the given program. By
analyzing the invariants at the cutpoints, upper bounds may be
obtained on the number of times the loops can be executed. It is
sometimes feasible also to discover an invariant of the form r < n at
a point immediately after the exit from the loop, thus yielding a
lower bound on the number of times the loop will be executed.
are satisfied, and the exact number of executions of the loop can be
computed as a function of the input. a
are satisfied.
Since n = m at H by (B13), it follows that the second loop is ex¬
ecuted the same number of times as the first. a
6. Automatic Debugging
4 The possibility that the program is partially correct but nonterminating will not be
treated in our discussion; actually it would lead to a correcting process similar to that
described here.
130 LOGICAL ANALYSIS OF PROGRAMS
We have thus found a place to “hang” the candidate on the tree, and
now must adjust the ancestors of (All) [i.e., (A3), (A4), or (A7)] so
that (All*) will be derived instead. By examining Equation (2.10), it
is not difficult to see that two of the most direct modifications
Automatic Debugging 133
or
(b) leave (A7) unchanged, but change
(A3) y2 =x2-y3 to (A3') 2y2 = x2-y3
and
(A4) yx =2x2-y4 to (A4') yx = x2-y4.
(ii) y1(n)=y1(n- 1)
(from the fact thaty! is unchanged along the right path),
(from the test 2xx < yx +y2 , using the left path),
These clearly combine to yield 2xx >yx(n), so that h(x, y) is 2xx >
yi, and we have the invariant
(A9') y4 <xx/x2 at N.
and does not disturb any other aspect of the proof of correctness,
i.e., the modified program is guaranteed correct. In Figure 2.8 we
show the invariant tree at N of the modified program, which is totally
correct. Thus, to summarize:
Possibility (b) for achieving the goal (All*) will now be considered,
i.e. we would like to replace (A3) and (A4) by (A3') and (A4'),
respectively (again referring to the original invariant tree of Figure
2.7). We immediately note that since (A3) is an ancestor of (A4),
any change in (A3) will influence (A4). The invariant (A4) was
obtained by bringing two summations involving if-then-else to an
identical form, so that yx and y4 could be connected. If during
the manipulations of the relations, 2y2 = x2 'y3 is used for substitu¬
tion instead ofy 2 = *2 ’T3, the new (A4) becomes exactly yx = x2 74,
i.e., the (A4') we require. Thus if we can change (A3) to (A3'), we
“automatically” have changed (A4) to (A4').
Examining the invariant tree, it is clear that we may achieve (A3')
by changing either (A 1) or (A2), i.e., either
rin
I A\ I
correctness'
i Partial
i
correctness;
ipar*iai
Termination |
W t—
L~ J
7. Conclusion
Acknowledgment
1. Introduction
This is a revised version of a previously published article by the same name which ap¬
peared in Artificial Intelligence, vol. 6, pp. 175-208. Copyright 1975 by North-Holland
Publishing Company, Amsterdam. Reprinted by permission of publisher.
141
142 PROGRAM SYNTHESIS
2. Fundamental Reasoning
{* I P(x)}
for “the set of all x such thatP(x)”. As we introduce an example we
will describe features of the language that apply to that example.
Since the specification language is extendible, we can introduce
new constructs at any time.
We use a separate language to express the system’s knowledge and
reasoning tactics. In the paper, these will be expressed in the form
of rules written in English. In our implementation, the same rules are
represented as programs in the qlisp programming language. When a
problem or goal is presented to the system, the appropriate rules
are summoned by “pattern-directed function invocation” (Hewitt,
1971). In other words, the form of the goal determines which rules
are applied.
In the following two sections we will use a single example, the
synthesis of the set-theoretic union program to illustrate the for¬
mation both of conditionals and of loops. The problem here is to
compute the union of two finite sets, where sets are represented as
lists with no repeated elements.
Given two sets, 5 and t, we want to express
union(s t) = {x \ x E s or x €= t]
in a lisp-like language. We expect the output of the synthesized pro¬
gram to be a set itself. Thus
union((A B) (B C)) - (ABC).
We do not regard the expression {x | x G s or x £ t) itsell as a proper
144 PROGRAM SYNTHESIS
rf , \r if p is false,
(it p then q else r) = I
[ q otherwise.
1 Since sets are represented as lists, head and tail may be applied to sets as well as lists.
Their value then depends on our actual choice of representation.
Fundamental Reasoning 145
{x UGioriGf}
therefore reduces to
(x | false orxGf},
unionis t) = if empty(s)
then t
else. .
where the else clause will be whatever program segment we construct
for the case in which s is not empty.
(x | x G 5 or x G t)
in the case in which s is not empty. Applying rule (2) to the sub¬
expression s, we can expand our expression to
If we observe that
{x | x £ tail(s) orx £ t]
is an instance of the top-level subgoal, we can reduce it to
union(tail(s) t).
union(s t) = if empty(s)
then t
else add(head(s) union(tail(s) t)).
that
2(1 + 2w) = (1 + w) + 2.
This strategy leads us to a solution.
Of course, the method of generalization does not apply to all
conjunctive-goal problems. For instance, the synthesis of an integer
square-root program has specifications
Achieve P.
Achieve x = y.
the program constructed would return the value of y, but would not
change the value of x ory.
Many of the techniques we used in the synthesis of lisp-like
programs also apply to the construction of programs with side effects.
In particular, we can use pattern-directed function invocation to re¬
trieve tactical knowledge. The synthesis of the program in the follow¬
ing example has the same flavor as our earlier union example, but
involves the introduction of side effects.
The program sort(x y) to be constructed is to sort the values of
two variables x and y. For simplicity we will allow the use of the
statement interchangeix y) to exchange the values of x and y, instead
of the usual sequence of assignment statements. Our specification
will be simply
Achievex <y.
x
’1
*- y
1'
interchange (x y)
2
Fundamental Reasoning 153
Q if P
(i.e., P D Q) is true at Point 1. In order to determine if R is true at
Point 3, it suffices to check whether
R if
(i.e., ~P 2) R) is true at Point 1.
Suppose two control paths join in the program being constructed:
y < z if x < y
T F
3 x < z
y « z-'2 interchange (x y)
4 --y < z
5 -y < z
Figure 3.1.
Achieve x = 2 and y = 3,
the two goals x = 2 and y = 3 are completely independent. In this
section, however, we will be concerned with the more complex case
in which P and Q interact. In such a case we may make P false in the
course of achieving Q.
Consider for example the problem of sorting three variables
x, y, and z. We will assume that the only instruction we can use is
the subroutine sort(u v), described in the previous section, which
sorts two variables. Our goal is then
sortix y)
sortiy z).
However, this program has a bug in that sorting y and z may disrupt
the relation x < y: if z is initially the smallest of the three, in inter¬
changing y and z we make y less than x. Reversing the order in which
the conjuncts are achieved does not solve the problem.
There are a number of ways in which this problem may be re¬
solved. One of them involves the notion of program modification
[cf. Sussman (1975)]. The general strategy is as follows: to achieve
P and Q simultaneously, first write a program to achieve P; then
modify that program to achieve Q as well. The essence of this strat¬
egy, then, lies in a technique of program modification.
Let us see how this strategy applies to the simple sort problem.
The specification is
|
3I
sort (y z)
sort (x y)
We still need to achieve goal (ii) at Point 2; we can achieve this goal
simply by inserting the instruction sortix z) before Point 2.
This modification will not effect Relation O'), “y < z if jc < y”,
which is protected at Point 2, because after executing sortiy z)
and sort(x z), the value of z will be the largest of the three. Thus the
desired program is
sort(y z)
sort(x z)
sort{x y).
3.1.1. Expressions
Expressions are atoms or nested lists of atoms; e.g., (A B (X C) D) is
an expression. An atom may be either a variable or a constant. (In
our examples we will use A, B, C, . . . for constants and U, V, W, . . .
for variables.) We have basic predicates atom, var, and const to
distinguish these objects:
atom(l) = / is an atom,
var(l) = l is a variable,
const(l) = / is a constant.
Thus
head(((A (X) B) C (D X))) = (A (X) B),
tail«(A (X) B) C (D X))) = (C (D X)).
We will abbreviate head(l) as lh and tail(l) as /f.
To construct expressions we have the function: if / is any
expression and m is a nonatomic expression, l * m is the expression
formed by inserting / before the first element of m. For example,
A • (B CD) = (A B CD),
(A (X) B) • (C (D X)) = (C4 (X) B) C (D X)).
The predicate occursin(x l) is true if x is an atom that occurs
in expression / at any level, e.g.,
occursin(A (C (B (A) B) C)) is true,
but
occursin{X Y) is false.
Finally, we will introduce the predicate constexp(l), which is true
if / is made up entirely of constants. Thus
constexp((A (B) C (D E))) is true.
but
constexp(X) is false.
Note that constexp differs from const in that constexp may be true
for nonatomic expressions.
3.1.2. Substitutions
«X (A B)) (Y (C n»
is a substitution.
The instantiation function inst(s l) applies the substitution s to the
expression /. For example, if
where “Find z such that P(z) else Q(z)” means construct an output z
satisfying P(z) if one exists; otherwise, find a z such that Q(z).
The above specifications do not completely capture our inten¬
tions; for instance, if
pat is (X Y) and arg is (A B),
then the substitution
z = ((X A) (Y B) (Z C>)
will satisfy our specifications as well as
z = ((XA) <YB».
Program Synthesis: The Pattern Matcher 161
match(pat arg) =
if constexp(pat)
then if pat = arg
then any
else NOMATCH
else if var(pat)
then pairipat arg)
else ... .
Rule 4. u = uh • ut if ~atom{u).
~atom(pat).
arg = u • v
for any z. Hence, our goal is unachievable in this case, and we can
return NOMATCH.
The program so far is
match(pat arg) =
if constexpipat)
then if pat = arg
then any
else NOMATCH
else if var(pat)
then pair{pat arg)
else if atom(arg)
then NOMATCH
else... .
For the as yet untreated case neither pat nor arg is atomic. Hence¬
forth using Rule 4 we assume that pat is path * patt and arg is
argh • argt.
Find z such that inst(z path) = argh and inst(z patt) = argf.
Goal 8. Find zx such that inst(zx path) = argh else Q(zx), and
~Q(z1)-
zx = match(path argh).
Henceforth we will use zx as an abbreviation for match{path argh).
Termination is easily shown, because both path and argh are proper
subexpressions of pat and arg, respectively. It remains to show,
according to Rule 7, that zx =£ NOMATCH. This causes another
hypothetical world split: in the case zx = NOMATCH (i.e., no
substitution can cause path and argh to match)5 we can show that
no substitution can cause pat and arg to match either, and hence
can take z = NOMATCH.
Program Synthesis: The Pattern Matcher 167
zx match(path argh)
if zx = NOMATCH
then NOMATCH
else. . .
i.e.,
inst(zi ° z2 path) = argh
for any substitution z2. Thus having one substitution zx that satisfies
Goal 6, we have an entire class of substitutions, of form zx 0 z2,
each of which satisfies Goal 6. These substitutions may be considered
to be “extensions” of zx ; although zx itself may not satisfy Goal 7,
perhaps some extension of zx will.
The above reasoning is straightforward enough to justify, but
further work is needed to motivate a machine to pursue it.
It remains now to find a single z2 such that zx ° z2 satisfies Goal
168 PROGRAM SYNTHESIS
7, i.e.,
Goal 10. Find z2 such that inst(z2 inst{z1 patt)) = argt else Q(z2),
and ~0(z2).
~Q(z2),
i.e.,
z2 =£ NOMATCH.
We cannot prove this: it is true for some examples and false for
others. Therefore we split on this condition.
In the case z2 A NOMATCH Goal 10 is satisfied. Thus z2 also
satisfies Goal 9, and z = z1 ° z2 satisfies Goal 7.
Our program so far is
matchipat arg) =
if constexp(pat)
then if pat = arg
then any
else NOMATCH
else if var(pat)
then pair(pat arg)
else if atom(arg)
then NOMATCH
else z1 •*- match(path argh)
if Zj = NOMATCH
Program Synthesis: The Pattern Matcher 169
then NOMATCH
else z2«- match(inst(z1 patt) argt)
ifz2 = NOMATCH
then...
else z1 ° z2.
We have gone this far through the synthesis using the weak specifi¬
cations, i.e., without requiring that the match found be most
general. In fact, the match found may or may not be most general,
depending on the value taken for the unspecified substitution “any”
produced in the very first case. The synthesis is nearly complete.
However, we will be unable to continue it without strengthening
the specifications and modifying the program accordingly. We now
have only one case left to consider. This is the case in which
z2 = NOMATCH,
i.e.,
match{inst(zx patt) argt) = NOMATCH.
This means that no substitution w satisfies
inst(w inst(zx patt)) = argt,
or, equivalently,
matchijpat arg) =
if constexp(pat)
then if pat = arg
then A
else NOMATCH
else if var(pat)
then pair(pat arg)
else if atom(arg)
then NOMATCH
elsez! <- match(path argh)
if zx = NOMATCH
Program Modification: The Unification Algorithm 171
then NOMATCH
elsez2 ynatch{inst{zx patt)argt)
if z2 = NOMATCH
then NOMATCH
else z1 ° z2.
to both pat and arg, will yield identical expressions. For instance, if
pat = (X A)
and
arg = (B Y),
unify{pat arg) =
if constexp(pat)
then if pat = arg
then A
else match{arg pat)
Discussion 175
else if var(pat)
then if occursin{pat arg)
then NOUNIFY
else pair(pat arg)
else if atom(arg)
then unify{arg pat)
else Zi <- unify{path argh)
if zx = NOUNIFY
then NOUNIFY
else z2 unify{inst{z1 patt) inst(zx argt))
if z2 = NOUNIFY
then NOUNIFY
else zx ° z2.
Recall that occursin(pat arg) means that pat occurs in arg as a sub¬
expression.
The termination of this program is considerably more difficult
to prove than was the termination of the pattern matcher. However,
the construction of the unification algorithm from the pattern
matcher is much easier than the initial synthesis of the pattern
matcher itself.
Note that the program we have constructed contains a redundant
branch. The expression
if pat = arg
then A
else match(arg pat)
could be reduced to
match(arg pat).
Such improvements would not be made until a later optimization
phase.
5. Discussion
5.1. Implementation
Implementation of the techniques presented in this paper is under¬
way. Some of them have already been implemented. Others will
require further development before an implementation will be
possible.
176 PROGRAM SYNTHESIS
Acknowledgments
Program Verification
Analysis of Programs
Much work has also been done related to the topic of the second
paper, “Logical Analysis of Programs.” German and Wegbreit (1975)
have implemented some heuristic approaches for generating invariant
assertions. The counters approach to proving program termination
has been incorporated into the program verification system of Luck-
ham and Suzuki (1975). A system to analyze the running time of
programs has been implemented by Wegbreit (1975). Efforts have
been made to use such analyses as a basis for the optimization of
programs and as a guide for their synthesis.
179
180 POSTSCRIPT
Program Synthesis
Boyer, R. S., and J S. Moore (Jan. 1975). Proving theorems about LISP func¬
tions. JACM, 22(1): 129-144.
181
182 REFERENCES
Green, C. (Oct. 1976). The design of PSI program synthesis system. In Proc¬
eedings of Second International Conference on Software Engineering.
San Francisco, Ca., pp. 4- 18.
Katz, S. M., and Z. Manna (Aug. 1973). A heuristic approach to program verifi¬
cation. In Proceedings of the Third International Conference on Artificial
Intelligence, Stanford University, Stanford, Ca., pp. 143-155.
REFERENCES 183
Katz, S. M., and Z. Manna (1975). A closer look at termination. Acta Infor-
matica, 5 (4): 333-352.
Katz, S. M., and Z. Manna (Apr. 1976). Logical analysis of programs. CACM,
19 (4): 188-206. (The second paper in this collection.)
Manna, Z., and R. Waldinger (March 1971). Toward automatic program syn¬
thesis. CACM, 14(3): 151-165.
Manna, Z., and R. Waldinger (1975). Knowledge and reasoning in program syn¬
thesis. Artificial Intelligence, 6 (2): 175-208. (The third paper in this
collection.)
von Neumann, J., and H. H. Goldstine (1963). Planning and coding problems
for an electronic computer instrument, Part 2. In Collected Works of John
von Neumann, vol. 5, New York: Macmillan, pp. 91-99.
Waldinger, R. J. (1977). Achieving several goals simultaneously. In Machine
Intelligence 8: Machine Representations of Knowledge (E. W. Elcock
and D. Michie, eds.). New York: John Wiley and Sons, Inc.
Waldinger, R. J., and R. C. T. Lee (May 1969). PROW: A step toward automatic
program writing, In Proceedings of International Joint Conference on
Artificial Intelligence, Washington, D.C., pp. 241-252.
Pnueli, A., 25
German, S.M.,7,179
Goldstine, H.H.,3
Good, D.I.,93,179 Reboh, R.,36
Green, C., 176,177 Robinson, J.A.,22,23,157,171
Greif, I., 139 Rulifson, J.F., 2,38,176
187
188 NAME INDEX
189
190 SUBJECT INDEX
identity, 50, 52
nontermination of programs, 94, 120ff.
incorrectness (of programs), 37, 93ff, See also termination.
119ff, 138, 140
induction (mathematical), 27, 100, 147
inequalities. See ordering relations, optimization (of programs), 94, 175,
instantiation function, 23, 63ff, 158f 177,179
interaction, 18,41,67, 179 ordering relations, 8, 15f, 19, 22, 28ff,
INTERLISP (programming language), 35,37, 39ff,47ff, 61
2, 36 or function, 16, 39
SUBJECT INDEX
191
partial correctness (of programs), 93, recursion,formation of, 142, 146ff, 165,
119f 176f, 180
PASCAL (programming language), 1 recursive programs, verification of,
passing backward. See pushing back¬ 22ff
ward. reflexivity, 18
path (in program), 6ff representation of concepts, 15ff
pattern and (in QA4), 50 resolution theorem proving 1, 176
pattern-directed function invocation reversing a list (example), 148
12ff, 143 running time (of programs), 126f, 130,
pattern matcher (example), 22ff, 35, 179
63ff, 78ff, 142, 149, 157ff, 172f,
176f
sets, 143ff
pattern matching (in QA4), 1 Iff
in QA4, 15f, 18,45
percentiles (example), 28ff
side-effects, 142, 150ff, 177
permutation property (of sort pro¬
simplification, 1, 13f, 27, 37, 4Iff,
gram), 18
49 ff
PLANNER (programming language),
simultaneous goals, 142, 153ff, 176,
142, 176
180. (See also conjunctive goals.)
plus function, 14, 15, 37, 42, 47ff
sort programs (example), 18, 28ff, 36,
procedural representation (of lan¬
56 ff
guages), 141
exchange, 36
product function. See times function,
three-variable, 154ff
program verifier. See verification sys¬
two-variable, 151 ff, 176
tems.
specification language, 18ff, 142ff
property lists, 15f, 40, 45
square-root, integer (example), 150
protection (in program modification),
straight-line programs, 3ff
15 5ff
strengthening. See generalization,
pushing backward
strip operator, 19
in generating verification condi¬
structural representation of knowl¬
tions, 9
edge, 141
invariant generation rule, 11 Of, 139
structured programming, 95
in synthesis, 152ff
substitutions, 22ff, 63ff, 78ff, 157ff,
pushing forward (invariant generation
17 Iff
rule), 111
subtract function. See minus function,
symmetry, 16
QA4 (programming language), 2, 3, synthesis (of programs), 37, 140, 14Iff,
11 ff, 22, 36, 176 179f
QLISP (programming language), 36,
142f, 176 termination (of programs), 7, 93f,
quotient program, integer (example),
119ff, 124ff, 146, 175, 179
35 tests, in generating verification condi¬
quotient program, real number (exam¬ tions, 9. (See also conditional
ple), 20ff, 35 expressions.)
times function, 12f, 15, 37, 47f, 52f
recurrence equations, 102ff, 139 total correctness (of programs), 119ff
192 SUBJECT INDEX
, A,
%
/ f i: •' '- •> Q
-•»
OCT SO 1991
MOV
iJJV 1? ?
£
QA 76.6 .M357
Manna, Zohar. 010101 000
Studies in automatic programmi
63 0 26483 8
TRENT UNIVERSITY
QA76.6 .M357
Hanna, Zohar
Studies in automatic
programming logic
%&7l(?y
Other outstanding series in
0 444 00224-3
- -