ResearchPDF Available

A brief Introduction to First-Order Logic Unification at the example of Corbin and Bidoit’s variation of Robinson’s Unification Algorithm

Authors:

Abstract and Figures

Automated reasoning and deduction have interested computer scientists and logicians since the earliest days of modern information technology. One of the fundamental processes of this field is unification, meaning the automated solving of equations containing symbolic expressions. This paper revisits the 1965 Robinson Unification algorithm, which is now recognized as being the first machine-oriented unification algorithm for first-order logic. The primary criticism to be brought against this algorithm is its exponential space complexity. Corbin and Bidoit proposed a revised version of the algorithm that aims to address this problem in 1983, which is discussed here as well.
Content may be subject to copyright.
A brief Introduction to First-Order Logic
Unification at the example of Corbin and Bidoit’s
variation of Robinson’s Unification Algorithm
J. Sprinz
16.09.2021
Abstract
Automated reasoning and deduction have interested computer scientists
and logicians since the earliest days of modern information technology.
One of the fundamental processes of this field is unification, meaning the
automated solving of equations containing symbolic expressions. This
paper revisits the 1965 Robinson Unification algorithm, which is now
recognized as being the first machine-oriented unification algorithm for
first-order logic. The primary criticism to be brought against this algorithm
is its exponential space complexity. Corbin and Bidoit proposed a revised
version of the algorithm that aims to address this problem in 1983, which
is discussed here as well.
Ludwig-Maximilians-Universität München
Master Seminar “Unification”
lead by Prof. Dr. François Bry and Dipl.-Ing. Thomas Prokosch
Summer term 2021
1
Motivation and Structure
Motivation
Unification algorithms enable automated solving of equations containing symbolic
expressions. In computer science, the unification of first-order logic terms is one
of the fundamental processes of automated reasoning and deduction. Practical
applications include logic programming and programming language type systems.
Herbrand (1930) first established the theoretical groundwork for unification.
However, the first known machine-oriented unification algorithm can be at-
tributed to Robinson (1965). This prompted researchers to explore different
approaches for more efficient unification algorithms and eliminate flaws in exist-
ing algorithms. This paper explores Corbin and Bidoit (1983)‘s variation of the
Robinson (1965) unification algorithm, demonstrating how the choice of data
structure can significantly influence an algorithms’ performance.
Structure
The subsequent sections are structured as follows. First, a brief introduction
to the unification of first-order logic expressions is presented. Next, Robinson
(1965)’s original Unification Algorithm is described. Particular attention will be
paid to its exponential space complexity. Building on that, the enhancements
proposed by Corbin and Bidoit (1983) are discussed, which use a different data
structure to achieve better behavior. Finally, the paper closes by summarizing
the observations.
Introduction
First-Order Logic, Terms
First-order logic
expands propositional logic, such that the terms are predicates
asserting relationships among elements of a set. The universal quantifier (
) and
existential quantifier (
) operators describe whether a predicate should hold for
all or just some elements of that set.
The definition of first-order logic
terms
used here is taken from Corbin and
Bidoit (1983). Let
F
be a countable set of constants and function symbols with
non-negative arity and
V
be a countable set of variables. The set
T
of valid
first-order logic terms is then recursively defined by:
tTiff tV∨ ∃fF, t1, ..., tnTso that t=f(t1, ..., tn)
In plain English: A term is either a variable or a function call, where every
argument is itself a term (cf. Corbin and Bidoit 1983, 909).
Substitutions and Replacements
A
substitution σ
is a mapping
VT
. It can be described as a finite set of
pairs of variables and terms called
replacements
. A substitution is written as
σ
=
{
[
ti\xi
]
, ...}
, which means that when applying the substitution
σ
to a term
2
t
, the resulting term
σ
(
t
)has all its instances of the term
ti
replaced with the
variable xi(cf. Corbin and Bidoit 1983, 909).
Example
Let
u, v, x, y
be variables,
f
a binary function,
σ
=
{
[
f
(
x, x
)
\u
]
,
[
y\v
]
}
a
substitution, and
t
=
f
(
y, f
(
x, x
)) a term. The substitution
σ
can then be
applied to the term tas follows: σ(t) = f(v, u).
Cascading substitutions
To emulate the behavior of applying multiple substitutions in sequence, they can
be
cascaded
to a single one. The goal is to find for two substitutions
σ1, σ2
a
cascaded substitution
σ
=
σ1
+
σ2
, so that
tT
:
σ
(
t
) =
σ2
(
σ1
(
t
)). Cascaded
substitutions are defined in set notations as follows:
σ1+σ2=σ={[s\σ2(r)]|[s\r]σ1}∪{[s\r]|[s\r]σ2∧∀[s1\r1]σ1:s6=s1}
In plain English: The cascaded substitution of two substitutions contains all
replacements from the first substitution with the second substitution applied to
each replacement term, as well as all replacements from the second substitution
that replace terms not replaced by the first substitution.
Example
Let
u, v, w, x, y , z
be variables,
f
an unary function,
g
a ternary function, and
σ1
=
{
[
u\x
]
,
[
v\y
]
}
,
σ2
=
{
[
y\z
]
,
[
f
(
w
)
\x
]
,
[
u\z
]
}
be substitutions. Applying
σ2
to every replacement term in
σ1
results in the set
{
[
u\x
]
,
[
v\z
]
} ⊆ σ
. Since
u
is already replaced,
σ23
[
u\z
]
/σ
. The full cascaded substitution
σ
is
consequently σ={[u\x],[v\z],[y\z],[f(w)\x]}.
Now let
t
=
g
(
u, v, g
(
f
(
w
)
, y, f
(
u
))) be a term. Applying the cascaded substitu-
tion to tresults in the same term as applying both substitutions in sequence:
σ1(t) = g(x, y, g(f(w), y , f(x)))
σ2(σ1(t)) = σ2(g(x, y, g(f(w), y , f(x)))) = g(x, z , g(x, z, f (x)))
σ(t) = g(x, z, g(x, z, f (x))) = σ2(σ1(t))
Unification, Unifier, MGU
Unification
is the process of determining whether or not two expressions can
be unified, that is made identical by applying appropriate substitutions to their
terms (cf. Robinson 1965, 31).
A substitution
σ
is called a
unifier
of two expressions
ϕ1
and
ϕ2
iff
σ
(
ϕ1
) =
σ
(
ϕ2
)
(cf. Corbin and Bidoit 1983, 909). Two expressions for which a unifier exists are
called unifiable. A unifier
σ1
is as general as or more general than a unifier
σ2
iff
σ3
:
σ2
=
σ3
(
σ1
). If two terms are unifiable, there must exist a most general
unifier (
MGU
) which is as general as or more general than every other unifier
(cf. Corbin and Bidoit 1983, 909). The goal of unification algorithms is to find
this MGU, if it exists.
3
Robinson’s Unification Algorithm
The following is a recursive version of the original Robinson (1965) unification
algorithm used by Corbin and Bidoit (1983).
Algorithm ROBINSON_TREE :unify(t1, t2)
Input Output
Two first-order logic terms,
t1
and
t2 A tuple (unifiable,unifier),
where unifiable is a boolean value
indicating whether or not the two
terms can be unified. If
unifiable
is
true,unifier is an MGU of t1 and
t2.
1FUNCTION unify(t1,t2)
2IF one of the terms,x,is a variable,let t be the other
3THEN
4IF x=t
5THEN unifiable := true; unifier := {};
6ELSE
7IF the variable x occurs in the term t
8THEN unifiable := false;
9ELSE unifiable := true; unifier := {[t\x]};
10 FI
11 FI
12 ELSE let t1=f(x1,... ,xn),t2=g(y1,... ,ym);
13 IF f!= g
14 THEN unifiable := false;
15 ELSE k:= 0;unifiable := true; unifier := {};
16 WHILE k<mAND unifiable
17 DO k := k+1;
18 (unifiable,subunifier) := unify(unifier(x[k],y[k]));
19 IF unifiable
20 THEN
21 unifier := subunifier +unifier;
22 FI
23 OD
24 FI
25 FI
26 RETURN (unifiable,unifier)
The
ROBINSON_TREE
algorithm consists of two main branches, the first of which
- lines 2 through 11 - handles cases where one of the terms is a variable. If both
terms are variables and identical, the terms are already unified, and an empty
unifier is returned (line 5). Otherwise, the so-called occurs-check is performed,
determining whether the variable occurs in the term (line 7). Only if the occurs-
check returns false are the two input terms unifiable, and a substitution replacing
4
the term with the variable is added to the unifier (line 9).
The second main branch - lines 12 through 25 - addresses the case where both
input terms are function calls. Calls to different functions are never unifiable
and terminate the algorithm (line 13). Otherwise, a while-loop (line 16) iterates
over each term’s arguments. A recursive call to
unify()
is executed for every
pair of arguments (line 18). The resulting substitution is cascaded with the
unifier (line 21), as long as the arguments themselves were unifiable (line 19).
Tree- and Graph Representation
The data structure used by
ROBINSON_TREE
to represent the terms is a tree. For
example, the two terms
t1
=
f
(
x, g
(
x, y
)) and
t2
=
f
(
g
(
y, z
)
, g
(
g
(
h
(
u
)
, y
)
, h
(
u
)))
would be represented as shown in Figures 1 and 2.
Figure 1: Tree representation of
t1
=
f
(
x, g
(
x, y
)) (cf. Corbin and Bidoit 1983,
910). Circled nodes represent function symbols, leaves represent variables.
Figure 2: Tree representation of
t2
=
f
(
g
(
y, z
)
, g
(
g
(
h
(
u
)
, y
)
, h
(
u
))) (cf. Corbin
and Bidoit 1983, 910). Circled nodes represent function symbols, leaves represent
variables.
5
The problem with this approach is that it does not allow structure sharing across
recursion steps (cf. Corbin and Bidoit 1983, 913; cf. Boyer and Moore 1972).
Consequentially, new graphs have to be constructed and stored for every recursive
call to
unify()
in line 18 of the
ROBINSON_TREE
algorithm. This is the primary
reason for the observed exponential space complexity of the
ROBINSON_TREE
algorithm. Corbin and Bidoit (1983) address this problem by representing the
terms not as two separate trees but as a single “finite directed acyclic graph”
(Corbin and Bidoit 1983, 910). Figure 3 shows how the previously defined terms
t1
and
t2
can be represented in a single graph, illustrating the savings potential
of this approach.
Figure 3: Graph representation of the previously defined terms
t1
and
t2
(cf. Corbin and Bidoit 1983, 912). Circled nodes represent function symbols,
leaves represent variables. Observe how every variable node is stored only once.
Algorithm ROBINSON_GRAPH :unify(v1, v2)
The following is the final revised version of the original Robinson (1965) unifica-
tion algorithm proposed by Corbin and Bidoit (1983) on page 912. The below
pseudocode makes use of the following helper functions to aid readability:
replace(v1, v2)
: redirect all edges pointing to
v1
to
v2
, thus replacing
v1 with v2 in the graph
term(v): return corresponding the term for a given verticy v
label(v): returns the function label for a given verticy v
successors(v): return the number of successors for a given verticy v
succ(v, k): return the kth successor node for a given verticy v
6
Input Output
Two nodes v1 and v2 in the graph
representing the two first-order logic
terms to unify
A tuple (unifiable,unifier),
where unifiable is a boolean value
indicating whether or not the two
terms can be unified. If
unifiable
is
true,unifier is an MGU of
term(v1) and term(v2).
1FUNCTION unify(v1,v2)
2IF one of the vertices,v,is a variable node,let w be the other
3THEN
4IF the variable v occurs in the term w
5THEN unifiable := false;
6ELSE
7unifiable := true;
8unifier := {[term(w)\term(x)]};
9replace(v,w);
10 FI
11 ELSE
12 IF label(v1) != label(v2)
13 THEN unifiable := false;
14 ELSE n := successors(v1);k:=0;unifiable := true; unifier := {};
15 WHILE k<nAND unifiable
16 DO k := k+1;
17 IF succ(v1,k) != succ(v2,k)
18 THEN (unifiable,subunifier) := unify(succ(v1,k),succ(v2,k));
19 IF unifiable THEN unifier := subunifier +unifier;FI
20 FI
21 OD
22 IF unifiable THEN replace(v1,v2);FI
23 FI
24 FI
25 RETURN (unifiable,unifier)
The
ROBINSON_GRAPH
algorithm is structurally very similar to
ROBINSON_TREE
.
The main difference is that substitutions are also applied to the shared data
structure using the
replace()
helper function (lines 9 and 22). Since variable
nodes in the graph are always unique (see Figure 3), the equality of the variables
does not have to be checked for in the first main branch. The second branch
optimizes the number of recursion steps by skipping identical nodes (line 17).
Due to the shared data structure, identical nodes imply that a substitution has
already occurred in a previous recursion step.
Discussion
The advantage in space complexity gained through structure sharing in
ROBINSON_GRAPH
over redundant data copies in
ROBINSON_TREE
seems obvious.
However, it should be noted that the real-world impact on computation
time will depend heavily on how this data structure is implemented, as the
7
helper functions used to handle replacements on the graph might harbor
significant inherent complexity. This behavior is influenced by the high-level
implementation itself and the design of the chosen programming language and
compiler. The platform the program will run on will further impact the result,
as different operating systems will impose different constraints on memory
management. Last but not least, modern processor features in representing
complex data structures might further influence performance.
Corbin and Bidoit (1983) measured computation times of LISP implementations
of different algorithms using the same input. The algorithms compared were the
original Robinson (1965) algorithm, Corbin and Bidoit (1983)‘s two proposed
optimizations thereof, as well as the Martelli and Montanari (1982) algorithm,
which represented a contemporary approach at the time. In this experiment,
Corbin and Bidoit (1983)’s final proposed revision managed to outperform
the other algorithms - hence their claim to “rehabilitate Robinson’s algorithm”
(Corbin and Bidoit 1983, 941) with their work. Repeating such an experiment
with the technology available today might provide some insight into how al-
most four decades of advancements in fields like programming language theory
and processor architecture impact these algorithms’ real-world performance.
Particular attention should be paid to how a modern low-level language like
Rust
1
compares to a high-level language like Python
2
. This comparison might
yield remarkable results, as both languages have seen significant development
over the last decade but represent fundamentally different paradigms in modern
programming language theory.
Conclusion
The goal of this paper was to provide a brief introduction to algorithmic first-
order logic unification. First, the formal concepts of first-order logic have been
introduced, and the unification process has been described. This served to
prepare the reader to revisit the earliest machine-oriented Unification algorithm,
published initially by Robinson (1965). The origins of it’s exponential complexity
have been explored by looking at optimizations proposed by Corbin and Bidoit
(1983). Particular attention has been paid to their use of structure sharing,
which was made possible by representing the data as a graph rather than a forest
of trees. Finally, an experimental comparison of the discussed algorithms has
been proposed to investigate the performance impact of recent advancements in
different fields of computer science.
Even though no significant original work has been conducted in the context of
this paper, it is provided in hopes that it helps readers new to first-order logic
unification approach the topic.
1https://www.rust-lang.org/
2https://www.python.org/
8
Bibliography
Boyer, R. S., and J. S. Moore. 1972. “The Sharing of Structure in Theorem-
Proving Programs. Machine Intel ligence 7: 101–16.
Corbin, Jacques, and Michel Bidoit. 1983. “A REHABILITATION OF ROBIN-
SON’S UNIFICATION ALGORITHM.” In Proceedings of the IFIP 9th World
Computer Congress, 909–14. Paris, France.
Herbrand, Jacques. 1930. “Recherches sur la théorie de la démonstration. PhD
thesis, Paris, France: FACULTÉ DES SCIENCES DE PARIS.
Martelli, Alberto, and Ugo Montanari. 1982. “An Efficient Unification Al-
gorithm.ACM Transactions on Programming Languages and Systems 4 (2):
258–82. https://doi.org/10.1145/357162.357169.
Robinson, J. A. 1965. “A Machine-Oriented Logic Based on the Resolution
Principle.Journal of the ACM 12 (1): 23–41. https://doi.org/10.1145/321250.
321253.
9
ResearchGate has not been able to resolve any citations for this publication.
Article
Full-text available
The unification problem in f'mst-order predicate calculus is described in general terms as the solution of a system of equations, and a nondeterministic algorithm is given. A new unification algorithm, characterized by having the acyclicity test efficiently embedded into it, is derived from the nondeterministic one, and a PASCAL implementation is given. A comparison with other well-known unification algorithms shows that the algorithm described here performs well in all cases.