Unification is the solving of equations, either in free algebras of the form , or in relatively free algebras modulo a set of equations, that is, in algebras of the form . The first case is sometimes called syntactic unification. The second case is sometimes called -unification or unification modulo ; if is not explicitly mentioned, then it is called equational unification or semantic unification.
In solving any equation, such as, for example,
we look for instances of the variables appearing in the equation that make both sides equal. Variables can of course be instantiated by substitutions. A substitution that makes both sides of the equation equal, that is, a solution of the equation, is called a unifier. For example, if we are solving the above equation in the free algebra with a countable set of variables and with having a single sort (unsorted unification), the substitution is a unifier, and indeed the so-called most general unifier, so that for any other unifier there exists a substitution such that , where denotes composition of substitutions in diagrammatic order. That is, any other solution of the equation is an instance of the most general solution provided by .
Of course, some equations may not have syntactic unifiers, but may have semantic unifiers modulo some equations . Consider, for example, the equation
which obviously does not have any solution in . It does, however, have a solution in , where is the commutativity axiom . Indeed, the exact same substitution solving the first equation in a syntactic way, is now a unifier solving the second equation modulo , because we have .
Unification is a fundamental deductive mechanism used in many automated deduction tasks. It is also very important in combining the paradigms of functional programming and logic programming (in the Prolog sense of “logic programming”). Furthermore, in the context of Maude, unification can be very useful to reason not only about equational theories (functional modules or theories), but also about rewrite theories (system modules or theories) [100].
Therefore, it is very useful to have an efficient implementation of unification available in Maude, which is what this chapter describes. Specifically, we explain how order-sorted unification modulo frequently occurring equational axioms is supported in Maude. In Chapter 14, we explain order-sorted unification modulo convergent equational theories, also available in Maude.
Although the most general equational theories supported by Maude are membership equational theories, to obtain practical unification algorithms, allowing us to effectively compute the solutions of an equational unification problem, it is important to restrict ourselves to order-sorted equational theories. We can define the basic concepts of order-sorted -unification in full generality.
Given an order-sorted equational theory , an -unification problem consists of a nonempty set of unification equations of the form , written in the notation
where and the “conjunction” operator is assumed to be associative and commutative.
Given such an -unification problem, an -unifier for it is an order-sorted substitution1 (where we assume that the set of variables contains a countable number of variables for each sort) such that, for all ,
where , that is, all the equations can be deduced in (membership) equational logic from the set of equations .
A set of unifiers is called a complete set of -unifiers for a given -unification problem iff for any other -unifier of the same -unification problem there exists a substitution and a unifier such that , that is, for each variable in the domain of we have . A complete set of -unifiers is called minimal if any proper subset of fails to be complete.
For an order-sorted equational theory , unification is said to be finitary if for any -unification problem there is always a finite complete set of unifiers. Similarly, unification for is called unitary if it is finitary and for any -unification problem a minimal complete set of unifiers is always either empty or a singleton set. We say that has a unification algorithm if there is an algorithm generating a complete set of -unifiers for any -unification problem in .
Unlike unsorted syntactic unification, which always either fails or has a single most general unifier, order-sorted syntactic unification is not necessarily unitary, that is, there is in general no single most general unifier. What exists (if is finite) is a finite minimal complete set of syntactic unifiers. For some commonly occurring theories having a unification algorithm, such as the theory of associativity of a binary function symbol, it is well-known that unification is not finitary: in general an infinite number of solutions may exist (see Section 13.4.6). However, for other theories, such as commutativity or associativity-commutativity , unification is finitary, both when is unsorted and when is order-sorted (and finite).
We define a hybrid approach, in which we take advantage of Maude’s structuring of a module’s equations into equational axioms , such as associativity, and/or commutativity, and/or identity, and equations , which are assumed to be coherent,2 confluent, and terminating modulo . We can then consider order-sorted equational theories of the form and decompose the -unification problem into two problems: one of -unification, and another of -unification that uses an -unification algorithm as a subroutine. The point of this decomposition is that -unification needs to be very efficient in order to have -unification be built on top of -unification. Since the axioms are well-known and unification algorithms exist for them, the task of building in efficient -unification algorithms, although highly nontrivial, becomes manageable; which is what this chapter describes. Chapter 14 describes such -unification relying on this -unification.
As mentioned above, a practical way of dealing with order-sorted equational unification is to consider order-sorted theories of the form , with a set of commonly occurring axioms, declared in Maude as equational attributes (see Section 4.4.1), and the remaining equations specified with the eq or ceq keywords. We can then decompose the -unification problem into an -unification problem and an -unification problem that uses an -unification algorithm as a subroutine. In such a decomposition, the efficiency of the -unification algorithm becomes crucial.
Maude currently provides an order-sorted -unification algorithm for all order-sorted theories such that the order-sorted signature is preregular modulo (see Sections 3.8 and 21.3.5) and the axioms associated to function symbols are as follows:
there can be arbitrary function symbols and constants with no equational attributes;
the iter equational attribute can be declared for some unary symbols;
different equational attributes can be declared for some binary function symbols:
the assoc attribute3 ; usually referred to as A (for associative),
the comm attribute; usually referred to as C (for commutative),
the assoc comm attributes; usually referred to as AC (for associative and commutative),
the assoc comm id: attributes; usually referred to as ACU (for associative and commutative with identity, or unit),
the assoc id: attributes3; usually referred to as AU (for associative and identity, or unit),
the comm id: attributes; usually referred to as CU (for commutative and identity, or unit),
the id: attribute; usually referred to as U (for identity, or unit),
the left id: attribute; usually referred to as Ul (for left identity, or unit), and
the right id: attribute; usually referred to as Ur (for right identity, or unit),
but no other equational attributes must be given for such symbols.
Explicitly excluded are theories with a binary symbol declared with the idem attribute and associativity with only left or right identity. However, these cases have the finite variant property, so that, used as variant equations, they can be combined with all the other just-mentioned attributes by means of variant unification algorithms (see Section 14.8).
If we give to Maude a unification problem in a functional module of the form fmod endfm where and satisfy the above requirements, we get a complete4 set of order-sorted unifiers modulo the theory . If, instead, we give the same problem to Maude in the functional module fmod endfm, then the equations are ignored, and we get the same unifiers as for the module or theory obtained by omitting the equations . Similarly, if we provide the same unification problem in a functional theory fth endfth, a system module mod endm or a system theory th endth, we again get the same set of unifiers as for the theory . All this is consistent with the decomposition idea mentioned above: to deal with order-sorted -unification, other methods, that use the -unification algorithm as a component, can later be defined.
Maude is even more tolerant than this. The user can give to Maude a unification problem in a functional module (or functional theory, or system module, or system theory) of the form fmod endfm (or the analogous specification in the other cases), where satisfies the conditions mentioned above, but is an optional set of membership axioms (that is, can be a membership equational theory and not just an order-sorted theory), and the axioms violate those conditions mentioned above. Then what will happen is:
Furthermore, the functional module fmod endfm (or the analogous functional theory or system module or theory) may import predefined modules such as BOOL or NAT, so that function symbols in such predefined modules can also be used in unification problems.
Given a functional module or theory, or a system module or theory, ModId, the user can give to Maude a unification command of the following two forms:
unify [ ] in ModId : Term-1 =? Term’-1 /\ ... /\ Term-k =? Term’-k . irredundant unify [ ] in ModId : Term-1 =? Term’-1 /\ ... /\ Term-k =? Term’-k .
For a simple example of syntactic order-sorted unification problem illustrating:
the use of the unify command;
sort downgrading of a variable;
the use of the predefined operator _^_ in the NAT module (see Section 8.3), representing exponentiation on natural numbers; and
the, in general, non-unitary nature of order-sorted unification,
fmod UNIFICATION-EX1 is extending NAT . op f : Nat Nat -> Nat . op f : NzNat Nat -> NzNat . op f : Nat NzNat -> NzNat . endfm
Maude> unify f(X:Nat, Y:Nat) ^ B:NzNat =? A:NzNat ^ f(Y:Nat, Z:Nat) . Unifier 1 X:Nat --> #1:Nat Y:Nat --> #2:NzNat B:NzNat --> f(#2:NzNat, #3:Nat) A:NzNat --> f(#1:Nat, #2:NzNat) Z:Nat --> #3:Nat Unifier 2 X:Nat --> #1:NzNat Y:Nat --> #2:Nat B:NzNat --> f(#2:Nat, #3:NzNat) A:NzNat --> f(#1:NzNat, #2:Nat) Z:Nat --> #3:NzNat
The next example in the same module illustrates the use of the unify command with a unification problem consisting of two equations:
Maude> unify f(X:Nat, Y:NzNat) =? f(Z:NzNat, U:Nat) /\ V:NzNat =? f(X:Nat, U:Nat) . Unifier 1 X:Nat --> #1:NzNat Y:NzNat --> #2:NzNat Z:NzNat --> #1:NzNat U:Nat --> #2:NzNat V:NzNat --> f(#1:NzNat, #2:NzNat)
Note that, as already mentioned, we could instead invoke the unify command in a functional or system module or theory having additional equations, memberships, or rules, which are always ignored. For example, we could have instead declared the system theory
th UNIFICATION-EX2 is including NAT . op f : Nat Nat -> Nat . op f : NzNat Nat -> NzNat . op f : Nat NzNat -> NzNat . eq f(f(N:Nat, M:Nat), K:Nat) = f(N:Nat, M:Nat) . rl f(N:Nat, M:Nat) => 0 . endth
The following unification command in the predefined CONVERSION module (see Section 8.10) illustrates a further point on the handling of built-in constants and functions. Built-in constants, even though infinite in number (all strings, all quoted identifiers, all natural numbers, and so on), are handled and can be used in unification problems. But built-in functions are not considered built-in for unification purposes; therefore, built-in evaluation of such functions is not performed during the unification.
Maude> unify in CONVERSION : X:String < "foo" + Y:Char =? Z:String + string(pi) < "foo" + Z:String . Unifier 1 X:String --> #1:Char + string(pi) Y:Char --> #1:Char Z:String --> #1:Char
The above examples illustrate a further point about the form of the returned unifiers, namely, that in each assignment –> in a unifier, the variables appearing in the term are always fresh variables of the form #n:Sort . The user is required5 not to use variables of this form in the submitted unification problem. A warning is printed if this requirement is violated:
Maude> unify in NAT : X:Nat ^ #1:Nat =? #2:Nat . Warning: unsafe variable name #1:Nat in unification problem.
The handling of unification problems in modules with operators whose equational axioms are excluded from the current unification algorithm can be illustrated by means of the following module:
As already mentioned, a unification problem using such an idempotent function symbol f in a non-ground subterm will mean that the unification attempt fails and a warning is issued:Maude> unify f(f(X:Nat, Y:Nat), Z:Nat) =? f(A:Nat, B:Nat) . Warning: Term f(X:Nat, Y:Nat, Z:Nat) is non-ground and unification for its top symbol is not currently supported.
Maude> unify X:Nat + f(f(41, 42),43) =? Y:Nat + f(41,f(42,43)) . Unifier 1 X:Nat --> #1:Nat + f(41, f(42, 43)) Y:Nat --> #1:Nat + f(f(41, 42), 43) Unifier 2 X:Nat --> f(41, f(42, 43)) Y:Nat --> f(f(41, 42), 43)
Note, however, that, as already mentioned, unification modulo the idem attribute can be achieved by variant-based unification using the explicit equation f(N:Nat,N:Nat) = N:Nat (see Section 14.8).
The use of a bound on the number of unifiers, as well as the use of the associative-commutative (AC) operator + in the predefined NAT module (see Section 8.3), plus the fact that even small AC-unification problems can generate a large number of unifiers are all illustrated by the following command:
Maude> unify [100] in NAT : X:Nat + X:Nat + Y:Nat =? A:Nat + B:Nat + C:Nat . Unifier 1 X:Nat --> #1:Nat + #2:Nat + #3:Nat + #5:Nat + #6:Nat + #8:Nat Y:Nat --> #4:Nat + #7:Nat + #9:Nat A:Nat --> #1:Nat + #1:Nat + #2:Nat + #3:Nat + #4:Nat B:Nat --> #2:Nat + #5:Nat + #5:Nat + #6:Nat + #7:Nat C:Nat --> #3:Nat + #6:Nat + #8:Nat + #8:Nat + #9:Nat ... Unifier 100 X:Nat --> #1:Nat + #2:Nat + #3:Nat + #4:Nat Y:Nat --> #5:Nat A:Nat --> #1:Nat + #1:Nat + #2:Nat B:Nat --> #2:Nat + #3:Nat C:Nat --> #3:Nat + #4:Nat + #4:Nat + #5:Nat
The unification problem above has unifiers, though only were asked for. Indeed, it is the minimal set of most general unifiers and the irredundant unify command returns the same set with unifiers.
The following example illustrates the efficiency of order-sorted unification modulo the iter theory (in this example in combination with the comm theory). Consider the following module:
fmod ITER-EXAMPLE is sorts NzEvenNat EvenNat OddNat NzNat Nat EvenInt OddInt NzInt Int . subsorts OddNat < OddInt NzNat < NzInt < Int . subsorts EvenNat < EvenInt Nat < Int . subsorts NzEvenNat < NzNat EvenNat < Nat . op 0 : -> EvenNat . op s : EvenNat -> OddNat [iter] . op s : OddNat -> NzEvenNat [iter] . op s : Nat -> NzNat [iter] . op s : EvenInt -> OddInt [iter] . op s : OddInt -> EvenInt [iter] . op s : Int -> Int [iter] . op _+_ : Int Int -> Int [comm gather (E e)] . op _+_ : OddInt OddInt -> EvenInt [ditto] . op _+_ : EvenInt EvenInt -> EvenInt [ditto] . op _+_ : OddInt EvenInt -> OddInt [ditto] . op _+_ : Nat Nat -> Nat [ditto] . op _+_ : Nat NzNat -> NzNat [ditto] . op _+_ : OddNat OddNat -> NzEvenNat [ditto] . op _+_ : NzEvenNat EvenNat -> NzEvenNat [ditto] . op _+_ : EvenNat EvenNat -> EvenNat [ditto] . op _+_ : OddNat EvenNat -> OddNat [ditto] . endfm
We can then give the unification commands:
Maude> unify in ITER-EXAMPLE : s^1000000(X:OddNat) =? s^100000000001(Y:Int) . Unifier 1 X:OddNat --> s^99999000001(#1:EvenNat) Y:Int --> #1:EvenNat
Maude> unify in ITER-EXAMPLE : s^1000000(X:OddNat) =? s^100000000001(Y:Int + Z:Int + W:Int) . Unifier 1 X:OddNat --> s^99999000001(#1:OddNat + (#2:OddNat + #3:EvenNat)) W:Int --> #1:OddNat Z:Int --> #2:OddNat Y:Int --> #3:EvenNat Unifier 2 X:OddNat --> s^99999000001(#1:OddNat + (#2:EvenNat + #3:OddNat)) W:Int --> #1:OddNat Z:Int --> #2:EvenNat Y:Int --> #3:OddNat Unifier 3 X:OddNat --> s^99999000001(#1:EvenNat + (#2:OddNat + #3:OddNat)) W:Int --> #1:EvenNat Z:Int --> #2:OddNat Y:Int --> #3:OddNat Unifier 4 X:OddNat --> s^99999000001(#1:EvenNat + (#2:EvenNat + #3:EvenNat)) W:Int --> #1:EvenNat Z:Int --> #2:EvenNat Y:Int --> #3:EvenNat
Note that the second command produces more unifiers than the first command even though both unification problems have only one most general unifier. We can, however, obtain just the single most general unifier for the second unification problem by giving the command:
Maude> irredundant unify in ITER-EXAMPLE : s^1000000(X:OddNat) =? s^100000000001(Y:Int + Z:Int + W:Int) . Unifier 1 X:OddNat --> s^99999000001(#1:EvenNat + (#2:EvenNat + #3:EvenNat)) W:Int --> #1:EvenNat Z:Int --> #2:EvenNat Y:Int --> #3:EvenNat
As already mentioned, assuming that no bound on the number of unifiers is specified by the user, Maude will always compute a complete set of order-sorted unifiers modulo , for the supported equational axioms described in Section 13.3 for which unification is known to be finitary. However, the unify command does not guarantee that the computed set of unifiers is minimal, only the irredundant unify command guarantees that. That is, some of the unifiers in the computed set may be redundant, since they could be obtained as instances (modulo ) of other unifiers in the set.
To illustrate the use of the unification command in the presence of ACU operators, let us consider yet another version of the vending machine example (first presented in Section 5.1 and in other sections of this document in different forms):
mod UNIF-VENDING-MACHINE is sorts Coin Item Marking Money State . subsort Coin < Money . op empty : -> Money . op __ : Money Money -> Money [assoc comm id: empty] . subsort Money Item < Marking . op __ : Marking Marking -> Marking [assoc comm id: empty] . op <_> : Marking -> State . ops $ q : -> Coin . ops a c : -> Item . var M : Marking . rl [buy-c] : < M $ > => < M c > . rl [buy-a] : < M $ > => < M a q > . eq [change]: q q q q = $ . endm
We can ask whether there is an equational unifier of two configurations, one containing at least two quarters, and another containing at least one dollar.
Maude> unify in UNIF-VENDING-MACHINE : < q q X:Marking > =? < $ Y:Marking > . Unifier 1 X:Marking --> $ Y:Marking --> q q Unifier 2 X:Marking --> $ #1:Marking Y:Marking --> q q #1:Marking
Maude> irredundant unify in UNIF-VENDING-MACHINE : < q q X:Marking > =? < $ Y:Marking > . Unifier 1 X:Marking --> $ #1:Marking Y:Marking --> q q #1:Marking
Recall that memberships are discarded completely. For instance, if we modify the previous example to include a membership definition for a new sort Quarter, a unification call with that sort may not succeed.
mod UNIF-VENDING-MACHINE-MB is sorts Coin Item Marking Money State . subsort Coin < Money . op empty : -> Money . op __ : Money Money -> Money [assoc comm id: empty] . subsort Money Item < Marking . op __ : Marking Marking -> Marking [assoc comm id: empty] . op <_> : Marking -> State . ops $ q : -> Coin . ops a c : -> Item . sort Quarter . subsort Quarter < Coin . mb q : Quarter . var M : Marking . rl [buy-c] : < M $ > => < M c > . rl [buy-a] : < M $ > => < M a q > . eq [change]: q q q q = $ . endm
Maude> unify in UNIF-VENDING-MACHINE-MB : < q q X:Marking > =? < $ Y:Quarter Z:Quarter > . No unifier.
Let us illustrate the use of the different combinations of the identity attribute for unification. Let us consider first a module using the left-id attribute.
mod LEFTID-UNIFICATION-EX is sorts Magma Elem . subsorts Elem < Magma . op __ : Magma Magma -> Magma [gather (E e) left id: e] . ops a b c d e : -> Elem . endm
Then the following two unification problems have a different meaning, where we have swapped the position of the variables. First, when we unify two terms where variables of sort Magma are at the left of the terms, we have both a syntactic unifier and a unifier modulo identity.
Maude> unify in LEFTID-UNIFICATION-EX : X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> a Y:Magma --> e Unifier 2 X:Magma --> #1:Magma a Y:Magma --> #1:Magma
Maude> irredundant unify in LEFTID-UNIFICATION-EXAMPLE : X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> #1:Magma a Y:Magma --> #1:Magma
a a Y:Magma is parsed as (a a) Y:Magma in module LEFTID-UNIFICATION-EX due to the attribute gather (E e) (see Section 3.9).
Consider now a similar module but for the right identity.
mod RIGHTID-UNIFICATION-EX is sorts Magma Elem . subsorts Elem < Magma . op __ : Magma Magma -> Magma [gather (e E) right id: e] . ops a b c d e : -> Elem . endm
When we unify two terms where variables of sort Magma are at the left of the terms, there is clearly no unifier, since the term Y:Magma a a is parsed as Y:Magma (a a) in module RIGHTID-UNIFICATION-EX due to the attribute gather (e E) (see Section 3.9).
Maude> unify in RIGHTID-UNIFICATION-EX : a X:Magma =? a a Y:Magma . Unifier 1 X:Magma --> a Y:Magma --> e Unifier 2 X:Magma --> a #1:Magma Y:Magma --> #1:Magma
Maude> irredundant unify in RIGHTID-UNIFICATION-EX : a X:Magma =? a a Y:Magma . Unifier 1 X:Magma --> a #1:Magma Y:Magma --> #1:Magma
Consider now a similar module but with the identity attribute (no left or right restriction).
mod ID-UNIFICATION-EX is sorts Magma Elem . subsorts Elem < Magma . op __ : Magma Magma -> Magma [gather (E e) id: e] . ops a b c d e : -> Elem . endm
When we unify two terms where variables of sort Magma are at the left of the terms, we have both a syntactic unifier and a unifier modulo identity:
Maude> unify in ID-UNIFICATION-EX : X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> a Y:Magma --> e Unifier 2 X:Magma --> #1:Magma a Y:Magma --> #1:Magma
Maude> irredundant unify in ID-UNIFICATION-EX : X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> #1:Magma a Y:Magma --> #1:Magma
Maude> unify in ID-UNIFICATION-EX : a X:Magma =? a a Y:Magma . Unifier 1 X:Magma --> a Y:Magma --> e
And finally, when we add commutativity, we obtain slightly different results.
mod COMM-ID-UNIFICATION-EX is sorts Magma Elem . subsorts Elem < Magma . op __ : Magma Magma -> Magma [gather (E e) comm id: e] . ops a b c d e : -> Elem . endm
When we unify two terms where variables of sort Magma are at the left of the terms, we have both a syntactic unifier and a unifier modulo identity and commutativity, but the latter is duplicated:
Maude> unify in COMM-ID-UNIFICATION-EX: X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> a Y:Magma --> e Unifier 2 X:Magma --> a #1:Magma Y:Magma --> #1:Magma Unifier 3 X:Magma --> a Y:Magma --> e
Maude> irredundant unify in COMM-ID-UNIFICATION-EX : X:Magma a =? Y:Magma a a . Unifier 1 X:Magma --> a #1:Magma Y:Magma --> #1:Magma
Maude> unify in COMM-ID-UNIFICATION-EXAMPLE : a X:Magma =? a a Y:Magma . Unifier 1 X:Magma --> a a Y:Magma --> a Unifier 2 X:Magma --> a Y:Magma --> e
In general, unification modulo associativity is not finitary. However, the Maude implementation provides a finitary and complete set of unifiers for a substantial class of unification problems where associative unification happens to be finitary. In problems outside of this class, a finite but in general incomplete set of unifiers is returned, with an explicit warning that the set may be incomplete. Let us illustrate the use of the unification command in the presence of A symbols with the different capabilities and limitations. One of the key ideas for having finitary unification modulo associativity is to have variables over associative symbols being linear, i.e., having only one occurrence among all the terms in a unification problem.
Consider a very simple module with a binary associative function symbol:
fmod UNIFICATION-EX4 is protecting NAT . sort NList . subsort Nat < NList . op _:_ : NList NList -> NList [assoc] . endfm
Maude> unify in UNIFICATION-EX4 : X:NList : Y:NList : Z:NList =? P:NList : Q:NList . Unifier 1 X:NList --> #3:NList : #4:NList Y:NList --> #1:NList Z:NList --> #2:NList P:NList --> #3:NList Q:NList --> #4:NList : #1:NList : #2:NList Unifier 2 X:NList --> #1:NList Y:NList --> #3:NList : #4:NList Z:NList --> #2:NList P:NList --> #1:NList : #3:NList Q:NList --> #4:NList : #2:NList Unifier 3 X:NList --> #1:NList Y:NList --> #2:NList Z:NList --> #4:NList : #3:NList P:NList --> #1:NList : #2:NList : #4:NList Q:NList --> #3:NList Unifier 4 X:NList --> #1:NList Y:NList --> #2:NList Z:NList --> #3:NList P:NList --> #1:NList : #2:NList Q:NList --> #3:NList Unifier 5 X:NList --> #1:NList Y:NList --> #2:NList Z:NList --> #3:NList P:NList --> #1:NList Q:NList --> #2:NList : #3:NList
The unification problem may not be linear but it may be easy to detect that there is no unifier, e.g. it is impossible to unify a list X concatenated with itself with another list Y concatenated also with itself but with a natural number, e.g. , in between.
When associative variables are non-linear, Maude has implemented a cycle detection that may have different outcomes:
Maude> unify in UNIFICATION-EX4 : 0 : Q:NList =? Q:NList : 0 . Warning: Unification modulo the theory of operator _:_ has encountered an instance for which it may not be complete. Unifier 1 Q:NList --> 0 Warning: Some unifiers may have been missed due to incomplete unification algorithm(s).
Note that the unification problem has an infinite family of most general unifiers for being a list of consecutive 0 elements.
Maude> unify in UNIFICATION-EX4 : X:NList : X:NList : X:NList =? Y:NList : Y:NList : Z:NList : Y:NList . Warning: Unification modulo the theory of operator _:_ has encountered an instance for which it may not be complete. Unifier 1 X:NList --> #1:NList : #1:NList : #1:NList : #1:NList Y:NList --> #1:NList : #1:NList : #1:NList Z:NList --> #1:NList : #1:NList : #1:NList Unifier 2 X:NList --> #1:NList : #1:NList : #1:NList Y:NList --> #1:NList : #1:NList Z:NList --> #1:NList : #1:NList : #1:NList Unifier 3 X:NList --> #1:NList : #1:NList Y:NList --> #1:NList Z:NList --> #1:NList : #1:NList : #1:NList Warning: Some unifiers may have been missed due to incomplete unification algorithm(s).
If the verbose mode is activated (see Appendix A.15), Maude will print different internal messages associated to the situations above:
Associative unification using cycle detection.
Associative unification algorithm detected an infinite family of unifiers.
Associative unification using depth bound of 7.
Associative unification algorithm hit depth bound.
Note that the depth bound can be changed from the command line, see Appendix A.1.
Unification modulo associativity and identity was the missing case for associativity without commutativity until Maude 3.1. Unification modulo associativity but with left identity or right identity is still missing and will be available in the future. However, it is currently supported in a different way, namely, by variant-based unification using an explicit equation (see Section 14.8). Note that unification modulo associativity and identity is, in general, not finitary, as in the case of only associativity, and the same conventions and warnings apply (see Section 13.4.6). Let us illustrate the use of the unification command in the presence of AU symbols using previous examples.
Consider a very simple module, adapting the previous module UNIFICATION-EX4, with a binary associative symbol with an identity symbol for the empty list:
fmod UNIFICATION-EX5 is protecting NAT . sort NList . op nil : -> NList . subsort Nat < NList . op _:_ : NList NList -> NList [assoc id: nil] . endfm
Maude> irredundant unify in UNIFICATION-EX5 : X:NList : Y:NList : Z:NList =? P:NList : Q:NList . Unifier 1 X:NList --> #3:NList : #4:NList Y:NList --> #1:NList Z:NList --> #2:NList P:NList --> #3:NList Q:NList --> #4:NList : #1:NList : #2:NList Unifier 2 X:NList --> #1:NList Y:NList --> #3:NList : #4:NList Z:NList --> #2:NList P:NList --> #1:NList : #3:NList Q:NList --> #4:NList : #2:NList Unifier 3 X:NList --> #1:NList Y:NList --> #2:NList Z:NList --> #4:NList : #3:NList P:NList --> #1:NList : #2:NList : #4:NList Q:NList --> #3:NList
This is an example where associativity-identity has fewer most general unifiers than associativity; see the unification command for theory UNIFICATION-EX4 in page 441 above with most general unifiers (both the unify and irredundant unify commands return although only the former is shown).
The reader may be aware that the algorithm for associative-identity unification produces many redundant unifiers due to its collapse nature and how the order-sorted information is actually treated. Therefore, the use of the irredundant unify command is advised in this case.