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 𝑥0≐𝑎,𝑥𝑖≐𝐹(𝑥𝑖−1,𝑥𝑖−1)(1≤𝑖≤𝑛), the input has linear size while the fully expanded image of 𝑥𝑛 has 2𝑛 occurrences of 𝑎. 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 𝐹(𝑥,𝐺(𝑎))≐𝐹(𝐺(𝑦),𝑦) use one shared variable node for both occurrences of 𝑦. After the two 𝐹-nodes are identified, their first children require 𝑥 ≐𝐺(𝑦), and their second children require 𝐺(𝑎) ≐𝑦. Processing the former class first records 𝑥 ↦𝐺(𝑦); processing the latter records 𝑦 ↦𝐺(𝑎). The two bindings point into the existing graph and are already a compact answer. Expanding the image of 𝑥 to 𝐺(𝐺(𝑎)) is a separate operation.
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 𝐺 with the following labels.
A node labelled 𝑓 ∈Σ has the ordered children 𝑛[1],…,𝑛[𝑘], where 𝑘 is the arity of 𝑓.
A node labelled 𝑥 ∈X has no children, and every occurrence of 𝑥 in the input points to this one node. Rigid nullary nodes may also be shared.
A problem adds 𝑚 pairs of distinguished nodes (𝑝𝑖,𝑞𝑖), for 1 ≤𝑖 ≤𝑚. Its size is |𝐺|:=|𝑉(𝐺)|+|𝐴(𝐺)|+𝑚, so a child pointer and an input equation are counted once.
For a substitution 𝜃 :X →𝑇Σ(Y) into finite trees, define 𝑈𝜃(𝑛) by following child pointers and replacing a flexible leaf 𝑥 by 𝜃(𝑥). The recursion is defined because 𝐺 is acyclic. The substitution solves the graph problem when 𝑈𝜃(𝑝𝑖) =𝑈𝜃(𝑞𝑖) for every 𝑖. Thus sharing changes the representation, not the set of tree solutions.
Referenced from 2 locations
An equivalence relation ∼ on the nodes of a shared term DAG is valid for the distinguished pairs when:
𝑝𝑖 ∼𝑞𝑖 for every input pair;
if 𝑟 ∼𝑠 and both nodes have rigid labels, those labels are the same symbol 𝑓, and 𝑟[𝑗] ∼𝑠[𝑗] at every argument position 𝑗;
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 𝑥 and 𝑓(𝑥) is homogeneous but denotes no finite tree.
Referenced from 2 locations
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.
Referenced from 4 locations
Proof of Lemma 113.3 — Valid-congruence criterion
Proof. Suppose 𝜃 is a unifier. Put 𝑟 ∼𝜃𝑠 when 𝑈𝜃(𝑟) =𝑈𝜃(𝑠). 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 𝐶 a fresh parameter 𝑧𝐶. Define a tree 𝑇𝐶 by 𝑇𝐶:={𝑧𝐶,𝐶 has no rigid node,𝑓(𝑇[𝑟[1]],…,𝑇[𝑟[𝑘]]),𝑟∈𝐶 has label 𝑓. Homogeneity makes the second line independent of 𝑟, and acyclicity makes the recursion finite. The assignment 𝑥 ↦𝑇[𝑥] 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. ◻
★★☆ Let the shared DAG have rigid nodes for 𝐹(𝑥,𝐺(𝑎)) and 𝐹(𝐺(𝑦),𝑦), one node for each variable, and one shared node for 𝐺(𝑎). Starting from the pair of 𝐹-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 𝐹(𝐺(𝑦),𝑥) and determine whether the least-closure calculation still yields an acyclic quotient.
Referenced from 3 locations
The criterion is declarative. Root-class graph unification computes its least closure without repeatedly rescanning an equivalence class.
A live state consists of the undeleted part of 𝐺, undirected links between nodes required to be equal, and an ordered list 𝑆 of bindings. Initially the input pairs are the links and 𝑆 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 𝑅.
If 𝑅 contains two rigid nodes with different labels, return 𝖼𝗅𝖺𝗌𝗁.
Otherwise choose a rigid node 𝑟 ∈𝑅 when one exists; if all nodes are flexible, choose one of them as 𝑟. For every other 𝑠 ∈𝑅, record 𝑠 ↦𝑟 when 𝑠 is flexible. When 𝑠 and 𝑟 are rigid nodes labelled by the same 𝑘-ary symbol, add the links (𝑠[𝑗],𝑟[𝑗]) for 1 ≤𝑗 ≤𝑘.
Delete the nodes of 𝑅 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 𝖼𝗒𝖼𝗅𝖾. If no live node remains, return 𝑆.
Referenced from 3 locations
In the displayed example the first root class consists of the two 𝐹-nodes. Its transition adds the two child links. The class processed after it contains 𝑥 and 𝐺(𝑦), and the last nontrivial class contains 𝑦 and 𝐺(𝑎). The calculation therefore returns exactly 𝑥↦𝐺(𝑦),𝑦↦𝐺(𝑎).
★☆☆ Trace the root-class transitions for 𝐻(𝑥,𝐹(𝑦))≐𝐻(𝐹(𝑎),𝐹(𝑎)). Use the maximally shared input DAG: the two printed occurrences of 𝐹(𝑎) are one rigid node, and their occurrences of 𝑎 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.
Referenced from 3 locations
Every nonfailing root-class transition has the following properties.
It preserves exactly the finite-tree solutions, after the recorded binding is read as an equation.
Its new links are exactly the corresponding-child consequences of the rigid nodes in the deleted class; no other closure pair is introduced.
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.
Referenced from 5 locations
Proof of Lemma 113.5 — Root transition and closure invariant
Proof. Let 𝑅 be the selected class. Since its nodes have no live parents, their only remaining semantic obligations are the links within 𝑅. If 𝑅 is variable-only, the equations 𝑠 =𝑟 for 𝑠 ∈𝑅 ∖{𝑟} are exactly the recorded bindings. If 𝑅 contains rigid nodes, homogeneity gives one common label 𝑓. Rigid injectivity gives, in both directions, 𝑓(𝑡1,…,𝑡𝑘)=𝑓(𝑢1,…,𝑢𝑘)⟺𝑡1=𝑢1,…,𝑡𝑘=𝑢𝑘. Thus replacing equality of two nodes in 𝑅 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. ◻
Root-class graph unification terminates. It returns 𝖼𝗅𝖺𝗌𝗁 or 𝖼𝗒𝖼𝗅𝖾 exactly when the input has no finite first-order unifier. Otherwise it returns a triangular substitution 𝑆 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, 𝜃=𝛿∘𝑆.
Referenced from 4 locations
Proof of Theorem 113.6 — Termination, correctness, and compact MGU
Proof. Each transition deletes at least one live node, so there are at most |𝑉(𝐺)| 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 𝐶, identify the semantic parameter 𝑧𝐶 from the proof of lemma 113.3 with the chosen unbound input representative 𝑟𝐶 of the operational substitution 𝑆. Any unifier 𝜃 gives one common tree to all variables of 𝐶; define 𝛿(𝑟𝐶) to be that tree. Induction along the quotient’s child-before-parent topological order gives 𝜃(𝑥) =𝛿(𝑆(𝑥)) for every input variable 𝑥. This is the required factorization. ◻
The procedure 𝖥𝗂𝗇𝗂𝗌𝗁(𝑟) 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 𝑟 is ignored; a live node with a nonnull owner reports 𝖼𝗒𝖼𝗅𝖾. Otherwise set 𝗈𝗐𝗇𝖾𝗋(𝑟) :=𝑟, push 𝑟, and repeat:
pop 𝑠; if 𝑟 and 𝑠 have different rigid labels, report 𝖼𝗅𝖺𝗌𝗁;
before inspecting 𝑠’s links, recursively call 𝖥𝗂𝗇𝗂𝗌𝗁(𝑡) for every live parent 𝑡 of 𝑠;
consume every link (𝑠,𝑡). Ignore a deleted 𝑡 or 𝑡 =𝑟. If 𝑡’s owner is null, set it to 𝑟 and push 𝑡; if its owner is 𝑟, it is already on this class’s stack; any other owner reports 𝖼𝗒𝖼𝗅𝖾;
for 𝑠 ≠𝑟, record 𝑠 ↦𝑟 when 𝑠 is flexible, and add links between corresponding children when both are rigid. Mark 𝑠 deleted.
When the stack empties, mark 𝑟 deleted. The solver adds the input links, calls 𝖥𝗂𝗇𝗂𝗌𝗁 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 𝑟, while a variable-only class may choose a flexible 𝑟.
Referenced from 6 locations
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 𝑥 ≐𝑓(𝑥).
A successful 𝖥𝗂𝗇𝗂𝗌𝗁(𝑟) 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.
Referenced from 3 locations
Proof of Lemma 113.8 — Scheduling refinement
Proof. At the moment the incident links of 𝑠 are inspected, every live parent has first been finished and deleted. Thus every node accumulated under owner 𝑟 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 𝑟, 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. ◻
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 𝑂(|𝐺|) time and 𝑂(|𝐺|) space on a pointer machine.
Referenced from 4 locations
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 𝑘 rigid nodes of arity 𝑞, it creates 𝑞(𝑘 −1) child links; charge them to the 𝑞(𝑘 −1) 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. ◻
★★☆ Suppose one processed class contains 𝑘 ≥1 rigid nodes of arity 𝑞. Prove that the transition creates exactly 𝑞(𝑘 −1) 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.
Referenced from 3 locations
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 𝑠 ↦𝑟 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 𝖢𝗈𝗆𝗉𝗅𝖾𝗍𝖾(𝑠) inside the 𝑠 ≠𝑟 branch, leaving 𝑟 unfinished until its class stack empties. Putting that assignment after the branch incorrectly accepts 𝑥 ≐𝑓(𝑥) 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.
In the completed-node presentation of the destructive schedule, assigning 𝖢𝗈𝗆𝗉𝗅𝖾𝗍𝖾(𝑠) :=𝗍𝗍 only in the branch 𝑠 ≠𝑟 rejects the equation 𝑥 ≐𝑓(𝑥). Moving that assignment after the branch can mark the class representative 𝑟 complete before parent recursion closes its class; the same input then reaches cyclic substitution construction instead of returning the occurs-check failure.
Referenced from 3 locations
Proof of Proposition 113.10 — Placement of the completion mark
Proof. The shared input has one variable node 𝑥 and one rigid node 𝑓(𝑥). Linking the roots puts them in one unfinished class. The rigid node has 𝑥 as a child, while the unique occurrence of 𝑥 is also the flexible member of that class. With the mark inside the 𝑠 ≠𝑟 branch, the representative remains unfinished until its class stack empties. Following the parent edge from 𝑥 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 𝑟 complete before the revisit. The revisit is skipped as completed, so the procedure emits the cyclic recipe 𝑥 ↦𝑓(𝑥). Expanding that recipe asks again for the expansion of 𝑥 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. ◻
★★☆ Write the owner and completion states reached on 𝑥 ≐𝑓(𝑥) for both placements in proposition 113.10. Then trace 𝑥 ≐𝑓(𝑦),𝑦 ≐𝑔(𝑥). Identify the first unfinished class revisited by the corrected procedure and the cyclic pair of quotient classes that it certifies.
Referenced from 3 locations
The compact output must not be confused with its tree expansion. For 𝑥0≐𝑎,𝑥𝑖≐𝐹(𝑥𝑖−1,𝑥𝑖−1)(1≤𝑖≤𝑛), the input DAG and triangular substitution have 𝑂(𝑛) nodes and pointers. The fully expanded tree for 𝑥𝑛 has 2𝑛 leaves labelled 𝑎 and 2𝑛+1 −1 total nodes. No algorithm can print that tree in linear time; the theorem prints the sharing-preserving recipes.
For the displayed family with 𝑛 +1 equations, the shared input and compact triangular unifier have 𝑂(𝑛) nodes and pointers. Every ordinary tree that is the fully expanded image of 𝑥𝑛 has 2𝑛 leaves and 2𝑛+1 −1 total nodes.
Referenced from 3 locations
Proof of Proposition 113.11 — Expansion is outside the linear bound
Proof. Let 𝐿𝑛 and 𝑁𝑛 be the numbers of leaves and total nodes in the expanded image of 𝑥𝑛. The base equation gives 𝐿0 =𝑁0 =1. Each successor equation duplicates the preceding tree beneath one new 𝐹-node, so 𝐿𝑛+1=2𝐿𝑛,𝑁𝑛+1=1+2𝑁𝑛. Induction gives 𝐿𝑛 =2𝑛 and 𝑁𝑛 =2𝑛+1 −1. 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.
★★☆ For 𝐹(𝑥,𝐻(𝑦,𝑎),𝑦)≐𝐹(𝐻(𝑧,𝑎),𝐻(𝐺(𝑎),𝑎),𝐺(𝑎)), 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.
Referenced from 4 locations
★★☆ 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.
Referenced from 3 locations
★★☆ For the family in proposition 113.11, give a sharing-preserving representation of the image of 𝑥𝑛 and an algorithm that reads its root symbol and follows one chosen leaf in 𝑂(𝑛) time. Prove that enumerating every leaf still takes Ω(2𝑛) time. Explain why neither conclusion contradicts theorem 113.9.
Referenced from 3 locations
★★★ 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:
𝚜𝚑𝚊𝚛𝚎𝚍-𝚎𝚡𝚊𝚖𝚙𝚕𝚎𝐹(𝑥,𝐺(𝑎))≐𝐹(𝐺(𝑦),𝑦)↦[𝑥↦𝐺(𝑦),𝑦↦𝐺(𝑎)],𝚑𝚎𝚊𝚍-𝚌𝚕𝚊𝚜𝚑𝐹(𝑥)≐𝐺(𝑥)↦𝚌𝚕𝚊𝚜𝚑,𝚘𝚌𝚌𝚞𝚛𝚜-𝚜𝚎𝚕𝚏𝑥≐𝐹(𝑥)↦𝚌𝚢𝚌𝚕𝚎,𝚘𝚌𝚌𝚞𝚛𝚜-𝚝𝚑𝚛𝚎𝚎𝑥≐𝐹(𝑦),𝑦≐𝐺(𝑧),𝑧≐𝐻(𝑥)↦𝚌𝚢𝚌𝚕𝚎,𝚌𝚘𝚖𝚙𝚊𝚌𝚝-𝚎𝚒𝚐𝚑𝚝𝑛=8↦𝚋𝚒𝚗𝚊𝚛𝚢-𝚛𝚎𝚌𝚒𝚙𝚎𝚜=𝟾,𝑛=8↦𝚝𝚘𝚝𝚊𝚕-𝚋𝚒𝚗𝚍𝚒𝚗𝚐𝚜=𝟿,𝚎𝚡𝚙𝚊𝚗𝚍𝚎𝚍-𝚕𝚎𝚊𝚟𝚎𝚜=𝟸𝟻𝟼.
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.
Referenced from 5 locations