In logic and computer science, specifically automated reasoning, unification is an algorithmic process of solving equations between symbolic expressions, each of the form Left-hand side = Right-hand side. For example, using x,y,z as variables, and taking f to be an uninterpreted function, the singleton equation set is a syntactic first-order unification problem that has the substitution as its only solution.
Conventions differ on what values variables may assume and which expressions are considered equivalent. In first-order syntactic unification, variables range over first-order terms and equivalence is syntactic. This version of unification has a unique "best" answer and is used in logic programming and programming language type system implementation, especially in Hindley–Milner based type inference algorithms. In higher-order unification, possibly restricted to higher-order pattern unification, terms may include lambda expressions, and equivalence is up to beta-reduction. This version is used in proof assistants and higher-order logic programming, for example Isabelle, Twelf, and lambdaProlog. Finally, in semantic unification or E-unification, equality is subject to background knowledge and variables range over a variety of domains. This version is used in SMT solvers, term rewriting algorithms, and cryptographic protocol analysis.
A unification problem is a finite set of equations to solve, where are in the set
T
If the right side of each equation is closed (no free variables), the problem is called (pattern) matching. The left side (with variables) of each equation is called the pattern.[1]
Formally, a unification approach presupposes
V
V
T
V\subseteqT
T
T
vars\colonT →
P
(V)
t
vars(t)\subsetneqV
t
\equiv
T
\equiv
⊕
t\equivu
u
t
⊕
t\equivu
t
u
As an example of how the set of terms and theory affects the set of solutions, the syntactic first-order unification problem has no solution over the set of finite terms. However, it has the single solution over the set of infinite tree terms. Similarly, the semantic first-order unification problem has each substitution of the form as a solution in a semigroup, i.e. if (⋅) is considered associative. But the same problem, viewed in an abelian group, where (⋅) is considered also commutative, has any substitution at all as a solution.
As an example of higher-order unification, the singleton set is a syntactic second-order unification problem, since y is a function variable. One solution is ; another one is .
See main article: Substitution (logic). A substitution is a mapping
\sigma:V → T
\{x1\mapstot1,...,xk\mapstotk\}
xi
ti
i=1,...,k
xi
t
t\{x1\mapstot1,...,xk\mapstotk\}
xi
t
ti
t\tau
\tau
t
t
f( | bf{x} | ,a,g( | bf{z} | ),y) | ||
yields | ||||||
f( | bf{h}(bf{a},bf{y}) | ,a,g( | bf{b} | ),y). |
If a term
t
u
t\sigma\equivu
\sigma
t
u
u
t
x ⊕ a
a ⊕ b
(x ⊕ a)\{x\mapstob\}=b ⊕ a\equiva ⊕ b
If ≡ is literal (syntactic) identity of terms, a term may be both more general and more special than another one only if both terms differ just in their variable names, not in their syntactic structure; such terms are called variants, or renamings of each other.For example,
f(x1,a,g(z1),y1)
f(x2,a,g(z2),y2)
f(x1,a,g(z1),y1)
f(x2,a,g(x2),x2)
For arbitrary
\equiv
x ⊕ x\equivx
x ⊕ y
z
x ⊕ y
z
A substitution
\sigma
\tau
t\sigma
t\tau
t
\tau
\sigma
V
li
eq |
ri
V
\sigma
\tau
\theta
X\notinV
X\sigma\equivX\tau\theta
\{x\mapstoa,y\mapstoa\}
\tau=\{x\mapstoy\}
\theta=\{y\mapstoa\}
\sigma=\{x\mapstoa\}
\tau=\{x\mapstoy\}
f(x,y)\sigma=f(a,y)
f(x,y)\tau=f(y,y)
A substitution σ is a solution of the unification problem E if for
i=1,...,n
For a given unification problem E, a set S of unifiers is called complete if each solution substitution is subsumed by some substitution in S. A complete substitution set always exists (e.g. the set of all solutions), but in some frameworks (such as unrestricted higher-order unification) the problem of determining whether any solution exists (i.e., whether the complete substitution set is nonempty) is undecidable.
The set S is called minimal if none of its members subsumes another one. Depending on the framework, a complete and minimal substitution set may have zero, one, finitely many, or infinitely many members, or may not exist at all due to an infinite chain of redundant members.[6] Thus, in general, unification algorithms compute a finite approximation of the complete set, which may or may not be minimal, although most algorithms avoid redundant unifiers when possible. For first-order syntactical unification, Martelli and Montanari[7] gave an algorithm that reports unsolvability or computes a single unifier that by itself forms a complete and minimal substitution set, called the most general unifier.
Syntactic unification of first-order terms is the most widely used unification framework.It is based on T being the set of first-order terms (over some given set V of variables, C of constants and Fn of n-ary function symbols) and on ≡ being syntactic equality.In this framework, each solvable unification problem has a complete, and obviously minimal, singleton solution set .Its member is called the most general unifier (mgu) of the problem.The terms on the left and the right hand side of each potential equation become syntactically equal when the mgu is applied i.e. .Any unifier of the problem is subsumed[8] by the mgu .The mgu is unique up to variants: if S1 and S2 are both complete and minimal solution sets of the same syntactical unification problem, then S1 = and S2 = for some substitutions and and is a variant of for each variable x occurring in the problem.
For example, the unification problem has a unifier, because
x | = | z | = | z | , and | |||
y | = | f(z) | = | f(x) | . |
This is also the most general unifier.Other unifiers for the same problem are e.g.,, and so on; there are infinitely many similar unifiers.
As another example, the problem g(x,x) ≐ f(y) has no solution with respect to ≡ being literal identity, since any substitution applied to the left and right hand side will keep the outermost g and f, respectively, and terms with different outermost function symbols are syntactically different.
Jacques Herbrand discussed the basic concepts of unification and sketched an algorithm in 1930.[9] [10] [11] But most authors attribute the first unification algorithm to John Alan Robinson (cf. box).[12] [13] Robinson's algorithm had worst-case exponential behavior in both time and space.[11] [14] Numerous authors have proposed more efficient unification algorithms.[15] Algorithms with worst-case linear-time behavior were discovered independently by and uses a similar technique as Paterson-Wegman, hence is linear,[16] but like most linear-time unification algorithms is slower than the Robinson version on small sized inputs due to the overhead of preprocessing the inputs and postprocessing of the output, such as construction of a DAG representation. is also of linear complexity in the input size but is competitive with the Robinson algorithm on small size inputs. The speedup is obtained by using an object-oriented representation of the predicate calculus that avoids the need for pre- and post-processing, instead making variable objects responsible for creating a substitution and for dealing with aliasing. de Champeaux claims that the ability to add functionality to predicate calculus represented as programmatic objects provides opportunities for optimizing other logic operations as well.[14]
The following algorithm is commonly presented and originates from .[17] Given a finite set
G=\{s1
eq |
t1,...,sn
eq |
tn\}
G\cup\{t
t\} | ⇒ | G | delete | |||||||
G\cup\{f(s0,...,sk)
f(t0,...,tk)\} | ⇒ | G\cup\{s0
t0,...,sk
tk\} | decompose | |||||||
G\cup\{f(s0,\ldots,sk)
g(t0,...,tm)\} | ⇒ | \bot | if f ≠ g k ≠ m | conflict | ||||||
G\cup\{f(s0,...,sk)
x\} | ⇒ | G\cup\{x
f(s0,...,sk)\} | swap | |||||||
G\cup\{x
t\} | ⇒ | G\{x\mapstot\}\cup\{x
t\} | if x\not\invars(t) x\invars(G) | eliminate[18] | ||||||
G\cup\{x
f(s0,...,sk)\} | ⇒ | \bot | if x\invars(f(s0,...,sk)) | check |
See main article: Occurs check. An attempt to unify a variable x with a term containing x as a strict subterm x ≐ f(..., x, ...) would lead to an infinite term as solution for x, since x would occur as a subterm of itself.In the set of (finite) first-order terms as defined above, the equation x ≐ f(..., x, ...) has no solution; hence the eliminate rule may only be applied if x ∉ vars(t).Since that additional check, called occurs check, slows down the algorithm, it is omitted e.g. in most Prolog systems.From a theoretical point of view, omitting the check amounts to solving equations over infinite trees, see
For the proof of termination of the algorithm consider a triple
\langlenvar,nlhs,neqn\rangle
\langlenvar,nlhs,neqn\rangle
Conor McBride observes[19] that "by expressing the structure which unification exploits" in a dependently typed language such as Epigram, Robinson's unification algorithm can be made recursive on the number of variables, in which case a separate termination proof becomes unnecessary.
In the Prolog syntactical convention a symbol starting with an upper case letter is a variable name; a symbol that starts with a lowercase letter is a function symbol; the comma is used as the logical and operator.For mathematical notation, x,y,z are used as variables, f,g as function symbols, and a,b as constants.
Prolog notation | Mathematical notation | Unifying substitution | Explanation | |
---|---|---|---|---|
a = a | Succeeds. (tautology) | |||
a = b | ⊥ | a and b do not match | ||
X = X | Succeeds. (tautology) | |||
a = X | x is unified with the constant a | |||
X = Y | x and y are aliased | |||
f(a,X) = f(a,b) | function and constant symbols match, x is unified with the constant b | |||
f(a) = g(a) | ⊥ | f and g do not match | ||
f(X) = f(Y) | x and y are aliased | |||
f(X) = g(Y) | ⊥ | f and g do not match | ||
f(X) = f(Y,Z) | ⊥ | Fails. The f function symbols have different arity | ||
f(g(X)) = f(Y) | Unifies y with the term | |||
f(g(X),X) = f(Y,a) | Unifies x with constant a, and y with the term | |||
X = f(X) | should be ⊥ | Returns ⊥ in first-order logic and many modern Prolog dialects (enforced by the occurs check).Succeeds in traditional Prolog and in Prolog II, unifying x with infinite term x=f(f(f(f(...)))) . | ||
X = Y, Y = a | Both x and y are unified with the constant a | |||
a = Y, X = Y | As above (order of equations in set doesn't matter) | |||
X = a, b = X | ⊥ | Fails. a and b do not match, so x can't be unified with both |
The most general unifier of a syntactic first-order unification problem of size may have a size of . For example, the problem has the most general unifier, cf. picture. In order to avoid exponential time complexity caused by such blow-up, advanced unification algorithms work on directed acyclic graphs (dags) rather than trees.
The concept of unification is one of the main ideas behind logic programming. Specifically, unification is a basic building block of resolution, a rule of inference for determining formula satisfiability. In Prolog, the equality symbol =
implies first-order syntactic unification. It represents the mechanism of binding the contents of variables and can be viewed as a kind of one-time assignment.
In Prolog:
+
, -
, *
, /
, are not evaluated by =
. So for example 1+2 = 3
is not satisfiable because they are syntactically different. The use of integer arithmetic constraints #=
introduces a form of E-unification for which these operations are interpreted and evaluated.[20]Type inference algorithms are typically based on unification, particularly Hindley-Milner type inference which is used by the functional languages Haskell and ML. For example, when attempting to infer the type of the Haskell expression True : ['x']
, the compiler will use the type a -> [a] -> [a]
of the list construction function (:)
, the type Bool
of the first argument True
, and the type [Char]
of the second argument ['x']
. The polymorphic type variable a
will be unified with Bool
and the second argument [a]
will be unified with [Char]
. a
cannot be both Bool
and Char
at the same time, therefore this expression is not correctly typed.
Like for Prolog, an algorithm for type inference can be given:
See also: Feature structure.
Unification has been used in different research areas of computational linguistics.[21] [22]
Order-sorted logic allows one to assign a sort, or type, to each term, and to declare a sort s1 a subsort of another sort s2, commonly written as s1 ⊆ s2. For example, when reаsoning about biological creatures, it is useful to declare a sort dog to be a subsort of a sort animal. Wherever a term of some sort s is required, a term of any subsort of s may be supplied instead.For example, assuming a function declaration mother: animal → animal, and a constant declaration lassie: dog, the term mother(lassie) is perfectly valid and has the sort animal. In order to supply the information that the mother of a dog is a dog in turn, another declaration mother: dog → dog may be issued; this is called function overloading, similar to overloading in programming languages.
Walther gave a unification algorithm for terms in order-sorted logic, requiring for any two declared sorts s1, s2 their intersection s1 ∩ s2 to be declared, too: if x1 and x2 is a variable of sort s1 and s2, respectively, the equation x1 ≐ x2 has the solution, where x: s1 ∩ s2.[23] After incorporating this algorithm into a clause-based automated theorem prover, he could solve a benchmark problem by translating it into order-sorted logic, thereby boiling it down an order of magnitude, as many unary predicates turned into sorts.
Smolka generalized order-sorted logic to allow for parametric polymorphism.[24] In his framework, subsort declarations are propagated to complex type expressions.As a programming example, a parametric sort list(X) may be declared (with X being a type parameter as in a C++ template), and from a subsort declaration int ⊆ float the relation list(int) ⊆ list(float) is automatically inferred, meaning that each list of integers is also a list of floats.
Schmidt-Schauß generalized order-sorted logic to allow for term declarations.[25] As an example, assuming subsort declarations even ⊆ int and odd ⊆ int, a term declaration like ∀ i : int. (i + i) : even allows to declare a property of integer addition that could not be expressed by ordinary overloading.
Background on infinite trees:
Unification algorithm, Prolog II:
Applications:
E-unification is the problem of finding solutions to a given set of equations,taking into account some equational background knowledge E.The latter is given as a set of universal equalities.For some particular sets E, equation solving algorithms (a.k.a. E-unification algorithms) have been devised;for others it has been proven that no such algorithms can exist.
For example, if and are distinct constants,the equation has no solutionwith respect to purely syntactic unification,where nothing is known about the operator .However, if the is known to be commutative,then the substitution solves the above equation,since
by substitution application | ||||
by commutativity of | ||||
by (converse) substitution application |
Associativity of | ||||||
= | Commutativity of | |||||
Left distributivity of over | ||||||
Right distributivity of over | ||||||
Idempotence of | ||||||
Left neutral element with respect to | ||||||
Right neutral element with respect to |
It is said that unification is decidable for a theory, if a unification algorithm has been devised for it that terminates for any input problem.It is said that unification is semi-decidable for a theory, if a unification algorithm has been devised for it that terminates for any solvable input problem, but may keep searching forever for solutions of an unsolvable input problem.
Unification is decidable for the following theories:
Unification is semi-decidable for the following theories:
If there is a convergent term rewriting system R available for E,the one-sided paramodulation algorithm[39] can be used to enumerate all solutions of given equations.
G ∪ |
| ⇒ | G ∪ |
| decompose | ||
G ∪ |
| ⇒ | G |
| if the variable x doesn't occur in t | eliminate | |
G ∪ |
| ⇒ | G ∪ |
| if f(u1,...,un) → r is a rule from R | mutate | |
G ∪ |
| ⇒ | G ∪ |
| if y1,...,yn are new variables | imitate |
Starting with G being the unification problem to be solved and S being the identity substitution, rules are applied nondeterministically until the empty set appears as the actual G, in which case the actual S is a unifying substitution. Depending on the order the paramodulation rules are applied, on the choice of the actual equation from G, and on the choice of Rs rules in mutate, different computations paths are possible. Only some lead to a solution, while others end at a G ≠ where no further rule is applicable (e.g. G =).
1 | app(nil,z) | → z | |
2 | app(x.y,z) | → x.app(y,z) |
For an example, a term rewrite system R is used defining the append operator of lists built from cons and nil; where cons(x,y) is written in infix notation as x.y for brevity; e.g. app(a.b.nil,c.d.nil) → a.app(b.nil,c.d.nil) → a.b.app(nil,c.d.nil) → a.b.c.d.nil demonstrates the concatenation of the lists a.b.nil and c.d.nil, employing the rewrite rule 2,2, and 1. The equational theory E corresponding to R is the congruence closure of R, both viewed as binary relations on terms.For example, app(a.b.nil,c.d.nil) ≡ a.b.c.d.nil ≡ app(a.b.c.d.nil,nil). The paramodulation algorithm enumerates solutions to equations with respect to that E when fed with the example R.
A successful example computation path for the unification problem is shown below. To avoid variable name clashes, rewrite rules are consistently renamed each time before their use by rule mutate; v2, v3, ... are computer-generated variable names for this purpose. In each line, the chosen equation from G is highlighted in red. Each time the mutate rule is applied, the chosen rewrite rule (1 or 2) is indicated in parentheses. From the last line, the unifying substitution S = can be obtained. In fact,app(x,app(y,x)) = app(a.nil,app(nil,a.nil)) ≡ app(a.nil,a.nil) ≡ a.app(nil,a.nil) ≡ a.a.nil solves the given problem.A second successful computation path, obtainable by choosing "mutate(1), mutate(2), mutate(2), mutate(1)" leads to the substitution S = ; it is not shown here. No other path leads to a success.
Used rule | G | S | ||
---|---|---|---|---|
mutate(2) | ⇒ | |||
decompose | ⇒ | |||
eliminate | ⇒ | |||
eliminate | ⇒ | |||
mutate(1) | ⇒ | |||
eliminate | ⇒ | |||
eliminate | ⇒ | |||
mutate(1) | ⇒ | |||
eliminate | ⇒ | |||
eliminate | ⇒ | |||
eliminate | ⇒ | |||
decompose | ⇒ | |||
decompose | ⇒ | |||
decompose | ⇒ |
If R is a convergent term rewriting system for E,an approach alternative to the previous section consists in successive application of "narrowing steps";this will eventually enumerate all solutions of a given equation.A narrowing step (cf. picture) consists in
Formally, if is a renamed copy of a rewrite rule from R, having no variables in common with a term s, and the subterm is not a variable and is unifiable with via the mgu, then can be narrowed to the term, i.e. to the term, with the subterm at p replaced by . The situation that s can be narrowed to t is commonly denoted as s ↝ t.Intuitively, a sequence of narrowing steps t1 ↝ t2 ↝ ... ↝ tn can be thought of as a sequence of rewrite steps t1 → t2 → ... → tn, but with the initial term t1 being further and further instantiated, as necessary to make each of the used rules applicable.
The above example paramodulation computation corresponds to the following narrowing sequence ("↓" indicating instantiation here):
app( | x | ,app(y, | x | )) | |||||||||||||
↓ | ↓ | x ↦ v2.v3 | |||||||||||||||
app( | v2.v3 | ,app(y, | v2.v3 | )) | → | v2.app(v3,app( | y | ,v2.v3)) | |||||||||
↓ | y ↦ nil | ||||||||||||||||
v2.app(v3,app( | nil | ,v2.v3)) | → | v2.app( | v3 | ,v2. | v3 | ) | |||||||||
↓ | ↓ | v3 ↦ nil | |||||||||||||||
v2.app( | nil | ,v2. | nil | ) | → | v2.v2.nil |
The last term, v2.v2.nil can be syntactically unified with the original right hand side term a.a.nil.
The narrowing lemma[40] ensures that whenever an instance of a term s can be rewritten to a term t by a convergent term rewriting system, then s and t can be narrowed and rewritten to a term and, respectively, such that is an instance of .
Formally: whenever holds for some substitution σ, then there exist terms such that and and for some substitution τ.
Many applications require one to consider the unification of typed lambda-terms instead of first-order terms. Such unification is often called higher-order unification. Higher-order unification is undecidable,[41] [42] [43] and such unification problems do not have most general unifiers. For example, the unification problem, where the only variable is f, has thesolutions,,,, and . A well studied branch of higher-order unification is the problem of unifying simply typed lambda terms modulo the equality determined by αβη conversions. Gérard Huet gave a semi-decidable (pre-)unification algorithm[44] that allows a systematic search of the space of unifiers (generalizing the unification algorithm of Martelli-Montanari[7] with rules for terms containing higher-order variables) that seems to work sufficiently well in practice. Huet[45] and Gilles Dowek[46] have written articles surveying this topic.
Several subsets of higher-order unification are well-behaved, in that they are decidable and have a most-general unifier for solvable problems. One such subset is the previously described first-order terms. Higher-order pattern unification, due to Dale Miller,[47] is another such subset. The higher-order logic programming languages λProlog and Twelf have switched from full higher-order unification to implementing only the pattern fragment; surprisingly pattern unification is sufficient for almost all programs, if each non-pattern unification problem is suspended until a subsequent substitution puts the unification into the pattern fragment. A superset of pattern unification called functions-as-constructors unification is also well-behaved.[48] The Zipperposition theorem prover has an algorithm integrating these well-behaved subsets into a full higher-order unification algorithm.[49]
In computational linguistics, one of the most influential theories of elliptical construction is that ellipses are represented by free variables whose values are then determined using Higher-Order Unification. For instance, the semantic representation of "Jon likes Mary and Peter does too" is and the value of R (the semantic representation of the ellipsis) is determined by the equation . The process of solving such equations is called Higher-Order Unification.[50]
Wayne Snyder gave a generalization of both higher-order unification and E-unification, i.e. an algorithm to unify lambda-terms modulo an equational theory.[51]
solving inequations between symbolic expression
computing a least general generalization (lgg) of two terms, dual to computing a most general instance (mgu)
(x ⊕ y)\{x\mapstoz,y\mapstoz\}=z ⊕ z\equivz