Lectures onType Theory
Chapter 113
Chapter 113Optional

Efficient First-Order Unification

Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.

The readable tree unifier repeatedly copies the term substituted for a variable. On the triangular equations x0a,xiF(xi1,xi1)(1in), the input has linear size while the fully expanded image of xn has 2n occurrences of a. A linear unifier must therefore compute with sharing and return a compact substitution. The proof must count pointer operations rather than the size of an expanded answer.

Graph unification

The equations F(x,G(a))F(G(y),y) use one shared variable node for both occurrences of y. After the two F-nodes are identified, their first children require xG(y), and their second children require G(a)y. Processing the former class first records xG(y); processing the latter records yG(a). The two bindings point into the existing graph and are already a compact answer. Expanding the image of x to G(G(a)) is a separate operation.

Definition 113.1 — Shared term DAG and its tree solutions

Fix a finite first-order signature Σ, whose symbol arities are part of the signature, and a finite set X of flexible variables. Ambient Timpl variables are treated here as distinct rigid nullary symbols. A shared term DAG is a finite directed acyclic graph G with the following labels.

  1. A node labelled fΣ has the ordered children n[1],,n[k], where k is the arity of f.

  2. A node labelled xX has no children, and every occurrence of x in the input points to this one node. Rigid nullary nodes may also be shared.

A problem adds m pairs of distinguished nodes (pi,qi), for 1im. Its size is |G|:=|V(G)|+|A(G)|+m, so a child pointer and an input equation are counted once.

For a substitution θ:XTΣ(Y) into finite trees, define Uθ(n) by following child pointers and replacing a flexible leaf x by θ(x). The recursion is defined because G is acyclic. The substitution solves the graph problem when Uθ(pi)=Uθ(qi) for every i. Thus sharing changes the representation, not the set of tree solutions.

Definition 113.2 — Homogeneous acyclic congruence

An equivalence relation on the nodes of a shared term DAG is valid for the distinguished pairs when:

  1. piqi for every input pair;

  2. if rs and both nodes have rigid labels, those labels are the same symbol f, and r[j]s[j] at every argument position j;

  3. after every equivalence class is contracted, the directed child graph has no directed cycle.

The second clause is the homogeneous closure condition; it includes both rigid-head compatibility and propagation to corresponding children. The third is the acyclic closure condition. It is not optional: a class containing both x and f(x) is homogeneous but denotes no finite tree.

Lemma 113.3 — Valid-congruence criterion

A shared term-DAG problem is unifiable by finite first-order trees if and only if it admits a valid equivalence relation. When it is unifiable, closing the input pairs only under equivalence and corresponding-child propagation gives the unique least valid relation.

Proof of Lemma 113.3 — Valid-congruence criterion

Proof. Suppose θ is a unifier. Put rθs when Uθ(r)=Uθ(s). Equality of rigid trees gives equal heads and equal corresponding subtrees. If the quotient had a cycle, the finite tree naming one class on that cycle would equal one of its proper subtrees, which finite-tree height forbids. Hence θ is valid.

Conversely, let be valid. Topologically order its quotient from children to parents. Give each variable-only class C a fresh parameter zC. Define a tree TC by TC:={zC,C has no rigid node,f(T[r[1]],,T[r[k]]),rC has label f. Homogeneity makes the second line independent of r, and acyclicity makes the recursion finite. The assignment xT[x] makes equivalent nodes unfold equally, hence solves every distinguished pair.

Finally, every valid relation containing the input pairs must contain every pair forced by equivalence and corresponding-child propagation. Their least closure is therefore contained in every valid relation. If that closure had a clash or quotient cycle, every extension would retain it; since a valid extension exists, the least closure is itself valid and is unique. ◻

Exercise 113.1

★★☆ Let the shared DAG have rigid nodes for F(x,G(a)) and F(G(y),y), one node for each variable, and one shared node for G(a). Starting from the pair of F-roots, calculate the least propagated equivalence relation. Exhibit its quotient DAG, prove that the quotient is homogeneous and acyclic, and read off a triangular most general unifier. Then replace the second input root by F(G(y),x) and determine whether the least-closure calculation still yields an acyclic quotient.

The criterion is declarative. Root-class graph unification computes its least closure without repeatedly rescanning an equivalence class.

Definition 113.4 — Root-class graph unification

A live state consists of the undeleted part of G, undirected links between nodes required to be equal, and an ordered list S of bindings. Initially the input pairs are the links and S is empty. A link class is a connected component of the undirected links. A root class is a link class all of whose live nodes have no live parent.

One transition chooses a root class R.

  1. If R contains two rigid nodes with different labels, return clash.

  2. Otherwise choose a rigid node rR when one exists; if all nodes are flexible, choose one of them as r. For every other sR, record sr when s is flexible. When s and r are rigid nodes labelled by the same k-ary symbol, add the links (s[j],r[j]) for 1jk.

  3. Delete the nodes of R and their outgoing child arcs from the live graph. A deleted rigid node remains addressable as the compact recipe consisting of its label and child pointers; it is absent only from subsequent scheduling scans.

If no root class exists while live nodes remain, return cycle. If no live node remains, return S.

In the displayed example the first root class consists of the two F-nodes. Its transition adds the two child links. The class processed after it contains x and G(y), and the last nontrivial class contains y and G(a). The calculation therefore returns exactly xG(y),yG(a).

Exercise 113.2

★☆☆ Trace the root-class transitions for H(x,F(y))H(F(a),F(a)). Use the maximally shared input DAG: the two printed occurrences of F(a) are one rigid node, and their occurrences of a are one nullary node. At each transition list the live root class, every child link created, and every binding recorded. Give the final triangular substitution and verify it by unfolding both input roots.

Lemma 113.5 — Root transition and closure invariant

Every nonfailing root-class transition has the following properties.

  1. It preserves exactly the finite-tree solutions, after the recorded binding is read as an equation.

  2. Its new links are exactly the corresponding-child consequences of the rigid nodes in the deleted class; no other closure pair is introduced.

  3. Every deleted class is homogeneous. If the least propagated quotient is acyclic, the live state has a root class. If a live state has none, its link quotient contains a directed cycle.

Proof of Lemma 113.5 — Root transition and closure invariant

Proof. Let R be the selected class. Since its nodes have no live parents, their only remaining semantic obligations are the links within R. If R is variable-only, the equations s=r for sR{r} are exactly the recorded bindings. If R contains rigid nodes, homogeneity gives one common label f. Rigid injectivity gives, in both directions, f(t1,,tk)=f(u1,,uk)t1=u1,,tk=uk. Thus replacing equality of two nodes in R by the child links preserves exactly the solutions. A flexible member must equal the chosen rigid recipe, which is exactly its recorded binding. This proves the first two clauses and also shows why a head clash has no solution.

For the last clause, order quotient classes from parents to children. A maximal class in an acyclic quotient has no incoming child arc. It also has no arc internal to the class, since that would be a quotient self-cycle. Every node in it is therefore a live root. Conversely, a finite quotient with no maximal class has a directed cycle. Induction over transitions now maintains the homogeneous-and-acyclic closure invariant until success, or exposes the first clash or cycle that prevents it. ◻

Theorem 113.6 — Termination, correctness, and compact MGU

Root-class graph unification terminates. It returns clash or cycle exactly when the input has no finite first-order unifier. Otherwise it returns a triangular substitution S that is a most general unifier of the input tree equations.

More precisely, every flexible variable occurs on the left of at most one binding. Flexible descendants of a rigid right-hand recipe are deleted strictly later; a variable-only class instead binds its other members to one chosen representative, which remains the unbound class parameter. If θ is any tree unifier, there is a substitution δ on the variable-only quotient classes such that, on the input variables, θ=δS.

Proof of Theorem 113.6 — Termination, correctness, and compact MGU

Proof. Each transition deletes at least one live node, so there are at most |V(G)| transitions. A clash is nonunifiability by rigid-head disjointness. A cycle is nonunifiability by lemma 113.3, lemma 113.5. If the algorithm succeeds, repeated use of lemma 113.5 shows that its bindings solve exactly the original equations.

A flexible node is shared and deleted once, so it is bound at most once. In a rigid class, a right-hand child of the selected root class cannot belong to that class: it has a live parent there and would make the class non-root. Its class is therefore deleted later. In a variable-only class, every nonrepresentative member is bound directly to the chosen representative; that representative receives no binding and is the class parameter in the compact substitution. The bindings are therefore triangular by root-class deletion order, with one parameter at each variable-only leaf class.

For most-generality, take the successful least valid quotient. In each variable-only class C, identify the semantic parameter zC from the proof of lemma 113.3 with the chosen unbound input representative rC of the operational substitution S. Any unifier θ gives one common tree to all variables of C; define δ(rC) to be that tree. Induction along the quotient’s child-before-parent topological order gives θ(x)=δ(S(x)) for every input variable x. This is the required factorization. ◻

Definition 113.7 — Paterson–Wegman scheduling interface

The procedure Finish(r) implements one root-class transition as follows. Every node stores its label, ordered children, a list of parents, an incident-link list, and an initially null owner pointer. Deleted nodes are skipped by live scans. On entry, an already deleted r is ignored; a live node with a nonnull owner reports cycle. Otherwise set owner(r):=r, push r, and repeat:

  1. pop s; if r and s have different rigid labels, report clash;

  2. before inspecting s’s links, recursively call Finish(t) for every live parent t of s;

  3. consume every link (s,t). Ignore a deleted t or t=r. If t’s owner is null, set it to r and push t; if its owner is r, it is already on this class’s stack; any other owner reports cycle;

  4. for sr, record sr when s is flexible, and add links between corresponding children when both are rigid. Mark s deleted.

When the stack empties, mark r deleted. The solver adds the input links, calls Finish on every rigid node in one global list, and only then on the remaining flexible nodes. Hence a mixed class is represented by a rigid r, while a variable-only class may choose a flexible r.

The parent-first recursive call is the decisive scheduling operation. Work on a non-root class is suspended until its parents have been deleted. An owner conflict is precisely a return to an unfinished class, and therefore detects the acyclicity failure exemplified by xf(x).

Lemma 113.8 — Scheduling refinement

A successful Finish(r) performs one transition of the root-class algorithm, and every root-class transition is eventually scheduled. The links, clashes, bindings, and cycle failures of definition 113.7, definition 113.4 agree.

Proof of Lemma 113.8 — Scheduling refinement

Proof. At the moment the incident links of s are inspected, every live parent has first been finished and deleted. Thus every node accumulated under owner r is a root when the class is processed. Consuming links computes exactly their connected component. Equal rigid labels generate exactly the child links of the root-class transition; variables generate exactly its bindings.

If recursion encounters a node already owned by a different unfinished invocation, or re-enters the invocation whose owner is r, following parent calls and owner links back to that node exhibits a directed cycle in the link quotient. If no such encounter occurs, the stack exhausts the whole root class and deletion implements its transition. Finally, every nonempty acyclic live quotient has a root class by lemma 113.5; the global scan or a parent call reaches one of its nodes. Induction on the number of live nodes gives eventual scheduling of every transition. ◻

Theorem 113.9 — Linear pointer-machine implementation

Assume that the input already has shared variable nodes and the records of definition 113.7; labels and pointers compare in constant time; allocation, stack push/pop, pointer update, and list-cursor advance take constant time; and parent and incident-link lists are scanned by monotone cursors that never restart. Then Paterson–Wegman scheduling decides unifiability and constructs the compact triangular MGU in O(|G|) time and O(|G|) space on a pointer machine.

Proof of Theorem 113.9 — Linear pointer-machine implementation

Proof. Charge a global-list visit and stack work to its node. Charge a parent-list cursor advance to the child arc it passes, including advances past deleted parents. Charge consuming a link to that link. When a class contains k rigid nodes of arity q, it creates q(k1) child links; charge them to the q(k1) outgoing arcs of the nonrepresentative rigid nodes deleted in that class. Thus the number of generated links is at most the number of input child arcs, and no node, arc, or link receives more than a constant number of charges. Output bindings are node/recipe pointers and add constant space per bound variable. Correctness and the MGU property follow from theorem 113.6, lemma 113.8. ◻

Exercise 113.3

★★☆ Suppose one processed class contains k1 rigid nodes of arity q. Prove that the transition creates exactly q(k1) child links after a representative is chosen. Give an injective charge from these links to the outgoing arcs of the nonrepresentative nodes, and extend the charge argument to a complete input DAG. State which step fails if an incident-link cursor is restarted after every merge.

The correction and the output boundary

This is the representation and machine model of the linear theorem; hashing, random access, and tree copying are not hypotheses. Constructing the shared variable nodes from an uninterned token stream is a separate front-end cost. Paterson and Wegman supply the original algorithm, root-class invariant, and linear charge argument [PW78]; Baader and Snyder supply the problem-relative substitution and term-DAG account used in the factorization statement [BS01]. In the terminology of the original article, Algorithm C therefore processes one completed root class at a time, and its printed sr output is a sequence of bindings over shared DAG recipes, not an expanded tree. In the later de Champeaux presentation, a completed-node variant must mark Complete(s) inside the sr branch, leaving r unfinished until its class stack empties. Putting that assignment after the branch incorrectly accepts xf(x) before substitution construction loops. This is the exact typographical defect isolated by Motroi and Ciobâcă [MC20]. The destructive schedule in definition 113.7 follows the original ordering and does not use the defective placement.

Proposition 113.10 — Placement of the completion mark

In the completed-node presentation of the destructive schedule, assigning Complete(s):=tt only in the branch sr rejects the equation xf(x). Moving that assignment after the branch can mark the class representative r complete before parent recursion closes its class; the same input then reaches cyclic substitution construction instead of returning the occurs-check failure.

Proof of Proposition 113.10 — Placement of the completion mark

Proof. The shared input has one variable node x and one rigid node f(x). Linking the roots puts them in one unfinished class. The rigid node has x as a child, while the unique occurrence of x is also the flexible member of that class. With the mark inside the sr branch, the representative remains unfinished until its class stack empties. Following the parent edge from x therefore revisits that unfinished class, which is the quotient self-cycle required for the occurs-check rejection.

With the mark after the branch, the invocation may mark r complete before the revisit. The revisit is skipped as completed, so the procedure emits the cyclic recipe xf(x). Expanding that recipe asks again for the expansion of x and has no finite result. Thus the misplaced assignment changes a required rejection into a nonterminating post-processing calculation. Motroi and Ciobâcă give this trace and place the assignment inside the branch in their corrected Figure 7. ◻

Exercise 113.4

★★☆ Write the owner and completion states reached on xf(x) for both placements in proposition 113.10. Then trace xf(y),yg(x). Identify the first unfinished class revisited by the corrected procedure and the cyclic pair of quotient classes that it certifies.

The compact output must not be confused with its tree expansion. For x0a,xiF(xi1,xi1)(1in), the input DAG and triangular substitution have O(n) nodes and pointers. The fully expanded tree for xn has 2n leaves labelled a and 2n+11 total nodes. No algorithm can print that tree in linear time; the theorem prints the sharing-preserving recipes.

Proposition 113.11 — Expansion is outside the linear bound

For the displayed family with n+1 equations, the shared input and compact triangular unifier have O(n) nodes and pointers. Every ordinary tree that is the fully expanded image of xn has 2n leaves and 2n+11 total nodes.

Proof of Proposition 113.11 — Expansion is outside the linear bound

Proof. Let Ln and Nn be the numbers of leaves and total nodes in the expanded image of xn. The base equation gives L0=N0=1. Each successor equation duplicates the preceding tree beneath one new F-node, so Ln+1=2Ln,Nn+1=1+2Nn. Induction gives Ln=2n and Nn=2n+11. The compact representation stores one binding and two pointers per successor equation, hence has linear size. ◻

Suggested first pass.

None of these problems is a prerequisite for a later chapter. Begin with exercise 113.5, then complete exercise 113.8.

Exercise 113.5

★★☆ For F(x,H(y,a),y)F(H(z,a),H(G(a),a),G(a)), draw the maximally shared input DAG. Execute every root-class transition, recording the links, representative, bindings, and deleted nodes. Prove that the returned substitution is most general by giving the factorization of an arbitrary unifier through its unbound quotient parameters.

Exercise 113.6

★★☆ Construct three shared problems that fail for different reasons: a rigid-head clash, a quotient self-cycle, and a quotient cycle of length three. For each problem, name the first transition at which the failure becomes detectable and prove that no finite-tree unifier exists. The three proofs must use, respectively, head disjointness, proper-subtree height, and a strict cycle of proper-subtree inequalities.

Exercise 113.7

★★☆ For the family in proposition 113.11, give a sharing-preserving representation of the image of xn and an algorithm that reads its root symbol and follows one chosen leaf in O(n) time. Prove that enumerating every leaf still takes Ω(2n) time. Explain why neither conclusion contradicts theorem 113.9.

Exercise 113.8

★★★ Practical project.shared-dag-unifier Implement in Kappa a finite first-order unifier whose answer is a compact triangular list of recipes. Represent variables and rigid symbols by natural identifiers, terms by a flexible leaf or a rigid symbol with an ordered list of arguments, and a problem by a list of equations. Implement deletion, orientation, elimination with an occurs check, rigid-head clash, and decomposition. Do not expand a binding when it is recorded.

Maintain the invariant that every residual equation is obtained from an input equation by the recorded eliminations, each variable occurs on the left of at most one binding, and every right-hand side is a finite term. Check a successful answer separately by applying the triangular bindings to every original equation. The five records are:

shared-exampleF(x,G(a))F(G(y),y)[xG(y),yG(a)],head-clashF(x)G(x)clash,occurs-selfxF(x)cycle,occurs-threexF(y),yG(z),zH(x)cycle,compact-eightn=8binary-recipes=8,n=8total-bindings=9,expanded-leaves=256.

The last record must not construct the 256 leaves. Mutate the flexible-variable clause of the occurs check to return false; both occurs records must change outcome while the other three remain accepted. The run neither implements the DAG schedule nor proves its MGU or linearity theorem.

Search the book

Type to search the local edition.