The search tree, and what the search is looking for #
IsoGraph.Canon.Equivariance proves that the ingredients of the search — refinement,
individualisation, the certificate — are equivariant, and that every leaf the search records is
an honest one. This file is about the search tree:
lexCmpU64is shown to becompareonList UInt64, which hands us a linear order (Std'sOrientedOrd/TransOrd/LawfulEqOrdinstances) for free.Reachdescribes the leaves of the unpruned tree, andkeythe quantity the search maximises: the pair (node-invariant path, certificate), encoded as aList (List UInt64)so that lexicographiccompareon it is the comparisonleafUpdateperforms.reach_transfertransports leaves along a renaming, andbestKey_transferconcludes that the specification — "the largest key of any leaf" — is an isomorphism invariant.
The bridge from the algorithm to the specification — that the search's winner really is the
largest key, i.e. that none of the three pruning rules ever discards it — is dfsNode_dom of
IsoGraph/Canon/Optimal.lean; the two are joined in IsoGraph/Canon/Correct.lean.
The comparison used to pick the winner #
lexCmpU64 is compare on the underlying lists, so it is a linear order: antisymmetric
(LawfulEqCmp), total (OrientedCmp) and transitive (TransCmp).
The key a leaf is judged by: its node-invariant path first, its certificate second. Packing
the two as a List (List UInt64) makes lexicographic compare on the pair — exactly the
comparison leafUpdate performs — available with all of Std's order lemmas.
Instances For
The search tree #
Reach n f invPath p k says that the tree rooted at the refined partition p — the unpruned
tree, in which every vertex of the target cell is individualised in turn — has a leaf with key
k. This is the search's specification: canonical is supposed to return the largest such key
(BestKey), and that is manifestly an isomorphism invariant (bestKey_transfer).
The child of p obtained by individualising v and re-refining, with the trace of the
refinement. This is exactly the step dfsChildren takes.
Equations
- IsoGraph.Canon.child G p v = IsoGraph.Canon.refine G (IsoGraph.Canon.individualize p v).1 ((Array.replicate G.n false).set! (IsoGraph.Canon.individualize p v).2 true) IsoGraph.Canon.hashSeed
Instances For
The node invariant of that child, appended to the path invariant.
Equations
- IsoGraph.Canon.childInv G invPath p v = invPath.push (IsoGraph.Canon.mix (IsoGraph.Canon.child G p v).2 ((IsoGraph.Canon.child G p v).1.shapeHash G.n))
Instances For
The leaves of the unpruned search tree below p, described by their keys.
- leaf {n : ℕ} {f : ℕ → ℕ → Bool} {invPath : Array UInt64} {p : Part} (h : p.targetCell n = none) : Reach n f invPath p (leafKey invPath (certOf (Graph.ofOracle n f) p.lab))
- step {n : ℕ} {f : ℕ → ℕ → Bool} {invPath : Array UInt64} {p : Part} {c v : ℕ} {k : List (List UInt64)} (hc : p.targetCell n = some c) (hv : v < n) (hcell : p.cst[p.pos[v]!]! = c) (h : Reach n f (childInv (Graph.ofOracle n f) invPath p v) (child (Graph.ofOracle n f) p v).1 k) : Reach n f invPath p k
Instances For
The tree is equivariant #
Leaves transport along a renaming. If p is q renamed by σ, every leaf of the tree
below q in the renamed graph has a leaf below p in the original one with the same key.
The converse direction: a leaf below p gives one below q, again with the same key. The
vertex to individualise is pulled back through σ.
The specification, and its invariance #
The root of the search: the initially refined partition and its one-entry invariant path.
Equations
Instances For
The invariant path at the root.
Equations
Instances For
k is the key of a leaf of the whole (unpruned) search tree.
Equations
- IsoGraph.Canon.Leafkey n f k = IsoGraph.Canon.Reach n f (IsoGraph.Canon.rootInv n f) (IsoGraph.Canon.rootPart n f) k
Instances For
The specification of canonical: the largest key of any leaf.
Equations
- IsoGraph.Canon.BestKey n f k = (IsoGraph.Canon.Leafkey n f k ∧ ∀ (k' : List (List UInt64)), IsoGraph.Canon.Leafkey n f k' → compare k' k ≠ Ordering.gt)
Instances For
The target cell really is a cell #
The winner is a leaf of the tree #
The induction is parametric in a predicate P on keys: if everything reachable below the current
node satisfies P, and everything the state already holds satisfies P, then so does everything
the state holds afterwards. Taking P to be "is a leaf key of the whole tree" at the root gives
canonical_leafkey.
Every leaf the state holds satisfies P.
Equations
- IsoGraph.Canon.StP P st = ∀ (l : IsoGraph.Canon.Leaf), st.best = some l → P (IsoGraph.Canon.leafKey l.invPath l.cert)
Instances For
The winner is a leaf of the whole tree #
Leaves extend the invariant path of the node they hang below #
If a node's invariant path is already worse than the incumbent's, so is every leaf below it.
Invariant pruning is sound #
k is beaten by the leaf the state currently holds.
Equations
- IsoGraph.Canon.Beaten st k = ∃ (l : IsoGraph.Canon.Leaf), st.best = some l ∧ compare k (IsoGraph.Canon.leafKey l.invPath l.cert) = Ordering.lt