Conference PaperPDF Available

What, Again? Automatic Deductive Synthesis of the Unification Algorithm



We describe work in progress towards deriving a unification algorithm automatically from a declarative specification using deductive methods. The specification is phrased as a logical theorem and the program is extracted from the proof. The theorem is proved using Stickel's system SNARK, operating over a theory of expressions and substitutions. The theory has been formulated to allow a simpler specification of the algorithm, and the theorem prover has discovered novelties in the implementation. It is hoped that the same techniques may enable the discovery of previously unknown unification algorithms for specific theories.
What, Again? Automatic Deductive
Synthesis of the Unification Algorithm
Richard Waldinger, Artificial Intelligence Center, SRI International
Deductive program synthesis is an approach to automated programming in which the programming
task is regarded as a problem in mathematical theorem proving. A logical statement that specifies
the purpose of the desired program is treated as a theorem to be proved. The theorem expresses the
existence of an output entity that satisfies the specification. The proof is restricted to be sufficiently
constructive to indicate a method for finding that output, and a program that employs the method is
derived from the proof. The proof also constitutes a verification of the correctness of this program.
There are generally many proofs of the theorem and many corresponding programs.
The Earlier Specification
Unification [Herbrand 30] [Robinson 65] was an early target of program synthesis efforts, but the
results fell short of a fully automatic derivation, one in which the program was obtained from the
specification without human participation. [Manna and Waldinger 81] provided a derivation, but it
was purely manual. [Paulson 85] described an interactive verification using LCF, but took the
program as a given, so it could not be regarded as a synthesis. [Eriksson 84], [Nardi 89]
et al. 97] produced partial derivations interactively, not completely automatically. So, a fully
automatic synthesis of a unification algorithm can still be regarded as a research goal.
Although Robinson used the term “most-general unifier,” he never gave a specification for the
unification algorithm or defined what it meant for one unifier to be more general than another.
Since then, a theory of expressions and substitutions has been worked out (see, e.g., [Baader Snyder
01].) In [Manna and Waldinger 81] we defined a substitution 1 to be more general than 2 if, for
some substitution , 1 = 2, where is the composition operator. We started by specifying
that the unification algorithm should find a most-general unifier for the given two terms e1 and e2 if
the terms are unifiable; otherwise, it should return the special failure entity .
We found that the proof would not go through unless we (by hand) strengthened the specification
to require that the most-general unifier we find be
. (An idempotent substitution is one
such that = .) The strengthened specification gave us the benefit of a stronger induction
hypothesis. We observed that, in the case in which 1 is idempotent, the condition that 1 is more
general than 2 is equivalent to 1 2 = 2. We shall say that a substitution 1 is
idempotently more
than another substitution 2, denoted by 1 gen 2, if 1 2 = 2. In this case we shall also
say that 2 is an
of 1. For our synthesis work, we have found it convenient to use this
stronger notion of more-generality.
In [Waldinger 2020] we attempted to automate the derivation laid out in [Manna and Waldinger 81].
We simplified the specification by a change in nomenclature: we regarded the failure entity as an
substitution, with the property that, for any term e, e =
, where
a constant. As a consequence, the improper substitution “unifies” all expressions, but we don’t
regard two expressions as unifiable unless they have a
unifier, distinct from . (We say that
such a substitution satisfies is-subst().) It holds that = and hence that gen for all
substitutions . In other words, any substitution is idempotently more general than the failure
substitution. Also, a substitution is idempotent if and only if gen .
In the earlier paper, we took the specification for the unification algorithm to be the remarkably
unify(e1, e2) find such that mgiu(, e1, e2),
where mgiu(, e1, e2), that is a most-general idempotent unifier of e1 and e2, is taken to mean that
e1 = e2 and
(’) [if e1' = e2' and
then gen '].
In other words, is a unifier and is idempotently more general than any proper unifier. This implies
that the unifier is most general and idempotent. Note that, in the case in which e1 and e2 are not
unifiable, this specification requires that be the failure entity , because that is the only unifier of
non-unifiable terms. The fact that the specification does not treat non-unifiability as a special case
simplifies the proof and the program as well as the specification, enabling us to avoid several case
analyses. The theorem prover discovered a simpler program than the one we expected, and one that
was marginally more efficient because it avoided some conditional tests.
Introducing an Accumulator
The automation of the synthesis had not been completed when the work-in-progress was reported
at the Workshop on Logic and Practice of Programming (LPOP 2020). During the discussion,
however, the question came up whether the same techniques would allow the system to derive a
more efficient unification algorithm. Unless efficiency is specified, nothing guarantees that the
theorem prover will come up with an efficient algorithm. But one more efficient algorithm takes as
an additional input an initial substitution 0, which keeps track of the partial unifier discovered so
far in the unification process.
We assume that the initial (accumulator) substitution is idempotent
and require that the output most-general unifier be an extension of the accumulator. Our new
specification is
unify(0, e1, e2) find such that mgiu(0, , e1, e2),
where mgiu(0, , e1, e2) is taken to mean that
if 0 gen 0
then 0 gen and
e1 = e2 and
(’) [if e1' = e2' and
is-subst(') and
0 gen '
then gen '].
In other words, we seek a unifier that is an extension of the accumulator and that is idempotently
more general that any unifier that is an extension of the accumulator, assuming that the
accumulator is idempotent (i.e., 0 gen 0). Initially we take 0 to be the empty substitution {}.
Because {} is idempotent and is idempotently more general than any substitution, this specification
reduces to our original specification for the unification algorithm. But this seemingly more complex
and general specification leads to a simpler synthesis proof as well as a more efficient unification
Mathematical Induction for Program Synthesis
As we have said, in deductive program synthesis we regard programming as a task in theorem
proving. To construct a program that, for a given input a, returns an output z that satisfies a
specified input-output condition, we prove the existence of an output entity z that satisfies the
condition. In other words, given a specification of the form
f(a) find z such that Q[a, z],
we attempt to prove the theorem ( a)(∃ 𝑧)Q[a, z]. The proof is restricted to be sufficiently
constructive so that a program that satisfies the specification can be extracted.
This is analogous to a derivation of a program for exponentiation: instead of deriving a program to compute exp(a, b)
ab, we construct a more general program exp(c, a, b) c * ab. Here the accumulator c keeps track of intermediate values
of the computation. Initially, we take c to be 1, so the value will be the desired exponentiation. Accumulators have long
been employed in program transformation; e.g., see [Wegbreit 76] and [Burstall and Darlington 77]
The structure of the program reflects the structure of the proof from which it was extracted. A case
analysis in the proof may produce a conditional expression in the extracted program. The use of the
principle of mathematical induction in the proof may yield a recursive call in the program. A more
leisurely introduction to the introduction of recursion in program synthesis is given in [Manna and
Waldinger 81].
A well-founded relation is one that, like the natural numbers with <, admits no infinite decreasing
sequences. Our induction is
well-founded induction
: For a given input a, we try to find an entity z
that satisfies the input-output condition Q[a, z]. We may assume inductively that the program f we
are trying to construct will satisfy the input-output condition for all inputs that are less than the
given input a with respect to a well-founded relation w. In other words, we conduct the proof
with the help of the induction hypothesis
if x w a
then Q[x, f(x)].
For the unification algorithm, we assume the induction hypothesis
if 0', e1', e2' w 0, e1, e2
then mgiu(0', unify(' e1', e2'), e1', e2').
The well-founded relation w is not specified in advance; w is a variable that ranges over well-
founded relations. We actually prove a theorem of form (∃ 𝑤)( a)(∃ 𝑧)Q[a, z]. It is not realistic to
expect the theorem prover to guess the relation w until the proof is under way. Instead, we extract
the definition of the relation from the proof, by the same mechanism by which the program itself is
extracted. The proof is conducted in the context of the axiomatic theory of expressions and
substitutions. We provide several primitive well-founded relations, such as the size of a term and the
number of variables it contains; we expect the theorem prover to discover a lexicographic
combination of these relations that will allow the proof to go through, but this part of the proof has
not yet been automated. In our experiments, we have temporarily provided the actual
lexicographical combination of well-founded relations needed.
Our experiments are conducted using the theorem prover SNARK [Stickel et al. 00], a first-order
resolution theorem prover which contains advanced capabilities for extracting answers, programs,
and other information from proofs. Program synthesis is a challenging application, partly because it
requires us to deal with full (universal and existential) quantification and mathematical induction.
Typically, automatic theorem provers that focus on induction (e.g., ACL2) do not deal with
theorems with explicit existential quantifiers, while resolution theorem provers do not deal with
induction at all. Furthermore, interesting program synthesis requires case analysis---otherwise,
how else do we introduce conditional programs? But resolution theorem provers are not so good at
case analysis. Furthermore, our approach requires us to prove the existence of a suitable well-
founded relation, which would most easily be achieved in a higher-order-logic setting. But as far as
we can tell, existing automatic higher-order-logic theorem provers do not do program extraction at
all, let alone the formation of conditional programs.
To quantify over relations in a first-order setting, we
relations. In other words, when we mean
that, say, x w y, we actually write holds(w, x, y), where w is a variable that ranges over relations.
Our theory also contains functions over relations; in the synthesis proof, we use the lexicographic
function lex. If w1 and w2 are relations, their lexicographic combination lex(w1, w2) is defined so that x
lex(w1, w2) y if and only if
x w1 y or
(x w1 y and x w2 y).
If w1 and w2 are well-founded, lex(w1, w2) is also well-founded.
Extracted Program Fragments
In our experiments we have restricted our attention to symbolic expressions, like LISP S-
expressions, in which the only function is the cons function . (This is not a substantive
simplificationfor one thing, any functional term can be encoded as an S-expression.)
While the proof is not complete, we have extracted program fragments for particular subcases. For
instance, in the part of the base case in which e1 is a variable and both e1 and e2
0, we obtain
unify(0, e1, e2) if e1 e2
else if e1 = e2
then 0
else 0 {e1 e2}.
Here {e1 e2} is the
substitution, which replaces all occurrences of e1 with e2. The
e1 e2, that is, e1 is a proper-subexpression of e2 , has been introduced as a
result of a case analysis in the proof. (When we say e
, we mean e = e.) SNARK’s proof,
in clause form and with a more readable explanation, occurs at
In the non-atomic case, in which both e1 and e2 are conses, SNARK obtains the astonishingly simple
tail-recursive program
unify(0, e1, e2) unify(unify(0, left(e1), left(e2)),
right(e1), right(e2)).
Here, left and right decompose conses, i.e., left(e1 e2) = e1 and right(e1 e2) = e2. The proof from
which this program was extracted uses two instances of the induction hypothesis, one for each
recursive call. While we expected the program to require conditional expressions for the cases in
which the left halves or the right halves were not unifiable, SNARK observed that this was
While the theorem prover does not establish the complexity of the extracted program, by good luck
it has obtained a more efficient program than the one in LPOP 2020. That program computed
unifiers for the left and right subexpression of the arguments and then composed them, an
expensive operation. The only composition the new program does is 0 {e1 e2}, i.e., to post-
pend a single replacement to a given substitution---relatively cheap!
Concluding Remark
One might argue that synthesizing a unification algorithm is pointless, since the algorithm is already
known and, in fact, the theorem prover requires a unification algorithm to conduct the proof. But,
aside from its value as an exercise, developing a system that can synthesize unification algorithms
may enable us on the fly to construct algorithms for new special theories, for which the unification
problem is still unsolved. To do this, we would incorporate axioms for the new theory into our
theory of expressions and substitutions. And we could consider related problems, such as anti-
unification and matching. But first things first.
Acknowledgments: We are grateful for discussions with researchers from SRI International
(including the Artificial Intelligence Seminar, the Crazy Idea Seminar, and the Coffee @ 4 meeting),
the Kestrel Institute, and the LPOP 2020 workshop. We have benefited from suggestions from the
workshop referees, Y. Annie Liu, David S. Warren, Alessandro Coglio, and Karthik Nukala.
[Armando et al. 97]
Armando, A., Smaill, A, and Green, I. (1997).
Automatic synthesis of recursive programs: the
proof-planning paradigm.
Proceedings of the 12th IEEE International Conference on Automated
Software Engineering,
pp. 29. IEEE.
[Baader Snyder 01]
Baader, F, and Snyder, W. (2001). Unification Theory. In
Handbook of Automated Reasoning (1),
Robinson, J. A., and Voronkov, A. (eds.), pp. 447533. Elsevier Science Publishers.
[Burstall and Darlington 77]
Burstall, R. M., and Darlington, J. (1977, January). A Transformation System for Developing
Recursive Programs.
Journal of the Association for Computing Machinery (
24:1), pp 44-67. ACM.
[Eriksson 84]
Eriksson, L. H. (1984) . Synthesis of a unification algorithm in a logic programming calculus,
Journal of Logic Programming
(1:1), pp. 318.
[Herbrand 30]
Herbrand, J. (1930).
Recherches sur la thorie de la
PhD thesis, Universit de Paris.
[Manna and Waldinger 81]
Manna, Z, and Waldinger, R. (1981). Deductive synthesis of the unification algorithm.
Science of Computer Programming
(1) pp. 548.
[Nardi 89]
Nardi, D. (1989). Formal synthesis of a unification algorithm by the deductive-tableau method.
Journal of Logic Programming
(7:1), pp. 143.
[Paulson 85]
L. C. Paulson (1985). Verifying the unification algorithm in LCF.
Science of Computer
(5), pp. 143170.
[Robinson 65]
Robinson, J. A. (1965, January). A Machine-Oriented Logic Based on the Resolution Principle.
Journal of the Association for Computing Machinery
(12:1) pp. 2341. ACM.
[Stickel et al. 00]
Stickel, M., Waldinger, R. J., and Chaudhri, V. (2000
). A Guide to SNARK.
SRI International, Menlo
Park, California, USA.
[Waldinger 2020]
Waldinger, R. (2020). Deductive Synthesis of the Unification Algorithm: The Automa-
tion of Introspection. In
Proceedings of the 2nd Workshop on Logic and Practice of Programming
pp. 1221.
[Wegbreit 76]
Wegbreit, B. (1976, June). Goal-Directed Program Transformation
. IEEE Transactions on Software
(SE-2, 2) pp. 6980. IEEE.
ResearchGate has not been able to resolve any citations for this publication.
Full-text available
A system of rules for transforming programs is described, with the programs in the form of recursion equations. An initially very simple, lucid, and hopefully correct program is transformed into a more efficient one by altering the recursion structure. Illustrative examples of program transformations are given, and a tentative implementation is described. Alternative structures for programs are shown, and a possible initial phase for an automatic or semiautomatic program-manipulation system is indicated.
Manna and Waldinger's theory of substitutions and unification has been verified using the Cambridge LCF theorem prover. A proof of the monotonicity of substitutiion is presented in detail. as an example of interaction with LCF. Translating the theory into LCF's domain-theoretic logic is largely straightforward. Well-founded induction on a complex ordering is translated into nested structural inductions. Correctness of unification is expressed using predicates for such properties as idempotence and most-generality. The verification is presented as a series of lemmas. The LCF proofs are compared with the original ones, and with other approaches. It appears difficult to find a logic that is both simple and flexible, especially for conducting difficult proofs of termination.
A formal specification of unification is presented and a unification algorithm is synthesized from it. The synthesis is done by logical deduction within the logic programming calculus developed by Hansson and Tärnlund. First-order logic with identity is used as the specification language and extended Horn clause logic as the target language.
We present the formal derivation of a unification algorithm using the deductive-tableau method for program synthesis. The methodology is briefly described, with emphasis on the deduction rules used in the derivation. Starting from an input-output specification expressed in first-order logic, a unification algorithm is synthesized by proving the validity of the specification. The termination of the synthesized program is also proved.
Conference Paper
We describe a proof plan that characterises a family of proofs corresponding to the synthesis of recursive functional programs. This plan provides a significant degree of automation in the construction of recursive programs from specifications, together with correctness proofs. This plan makes use of meta-variables to allow successive refinement of the identity of unknowns, and so allows the program and the proof to be developed hand in hand. We illustrate the plan with parts of a substantial example-the synthesis of a unification algorithm
Program development often proceeds by transforming simple, clear programs into complex, involuted, but more efficient ones. This paper examines ways this process can be rendered more systematic. We show how analysis of program performance, partial evaluation of functions, and abstraction of recursive function definitions from recurring subgoals can be combined to yield many global transformations in a methodical fashion. Examples are drawn from compiler optimization, list processing, very high-evel languages, and APL execution.
A Guide to SNARK. SRI International
  • M Stickel
  • R J Waldinger
  • V Chaudhri
Stickel, M., Waldinger, R. J., and Chaudhri, V. (2000). A Guide to SNARK. SRI International, Menlo Park, California, USA. [Waldinger 2020]
Deductive Synthesis of the Unification Algorithm: The Automation of Introspection
  • R Waldinger
Waldinger, R. (2020). Deductive Synthesis of the Unification Algorithm: The Automation of Introspection. In Proceedings of the 2nd Workshop on Logic and Practice of Programming (LPOP), pp. 12-21.