Proofs: Ullmann's algorithm
These are the human proofs of Ullmann's algorithm, at full length.
Ullmann's algorithm outputs every embedding exactly once full
This proof shows: correctness, termination.
Setting. with is the pattern and with the host, both simple and undirected, with labels . An embedding is an injective with for all and ; in the induced mode also the converse. A matrix admits when for every row .
Lemma 1 (L1 admits every embedding). The initial matrix admits every embedding.
Proof. An embedding keeps labels, and it maps the neighbors of injectively to neighbors of , so .
Lemma 2 (REFINE keeps admitted embeddings and terminates). If admits , then after REFINE() the matrix still admits . REFINE stops after at most passes.
Proof. Consider the first entry cleared by L10 at a moment when the current matrix admits , and suppose . L10 found a neighbor of with for all . But since is an embedding, and because the matrix admits . Contradiction; so no entry is ever cleared. Every pass that does not stop clears at least one of at most entries, and entries are never set back to 1, so there are at most changing passes and one final pass.
Lemma 3 (L5 keeps the embeddings of the branch). Let admit and let . Then the matrix of L5 admits .
Proof. Row of has its 1 at . In a row , only column is cleared, and because is injective. Rows above are unchanged.
Lemma 4 (the rows above the current one are fixed and distinct). At a node of the search at row , with matrix , every row has exactly one 1, in a column , and the are pairwise distinct.
Proof. By induction on . For there is nothing to show. Going from row to row , L5 sets row to a single 1 at and clears column in all rows below , so no later row can hold . REFINE only clears entries, and L6 discards the matrix when a row becomes empty, so the single 1 of each fixed row survives. Earlier fixed columns , , were cleared from row before was chosen, so .
Theorem. The search terminates and outputs exactly the embeddings of into , each once.
Proof. Termination. Each node at row has at most children, all at row , and REFINE terminates by Lemma 2, so the search tree is finite and depth-first search visits it once.
Soundness. An output happens at row after REFINE succeeded. By Lemma 4 applied with (the row is fixed in L5 in the same way), every row has exactly one 1, in distinct columns, so is injective. L1 and the fact that entries are only cleared give equal labels. L7 checks every edge of , and in the induced mode every non-edge, before it outputs. So every output is an embedding.
Completeness. Let be an embedding. By Lemmas 1 and 2 the root matrix admits , so no row is empty and the search starts. Suppose the search reaches a node at row whose matrix admits and whose fixed columns are for . Then , so L4 tries . By Lemmas 3 and 2 the refined admits , so no row is empty and L6 does not reject. If , the search goes on at row with the same two properties. If , the single 1 of each row is at , and the edge check of L7 passes because is an embedding, so is output.
Uniqueness. Two different leaves differ at the first row where their paths choose different columns, so they output different maps.