hex

12.7. The Mathlib correspondence🔗

Everything the driver computes is executable and Mathlib-free. HexRootsMathlib is the companion that interprets it: a Hex.ZPoly input becomes a complex polynomial through HexRootsMathlib.toPolyℂ, and the executable certificates become statements about its root set in Polynomial ℂ. The correspondence has two halves. Soundness is HexRootsMathlib.isolateComplexRoots?_sound from the certificate section: a successful run enumerates exactly the distinct complex roots, at the requested precision. Completeness is the converse guarantee, that on a nonzero polynomial with only simple roots the search cannot fail, for every strategy and every requested precision:

🔗theorem
HexRootsMathlib.isolateComplexRoots?_isSome (p : Hex.ZPoly) (h : Hex.HasOnlySimpleRoots p) (hp : p 0) (atomPrec : ) (strategy : Hex.AtomStrategy) : (p.isolateComplexRoots? h atomPrec strategy).isSome = true
HexRootsMathlib.isolateComplexRoots?_isSome (p : Hex.ZPoly) (h : Hex.HasOnlySimpleRoots p) (hp : p 0) (atomPrec : ) (strategy : Hex.AtomStrategy) : (p.isolateComplexRoots? h atomPrec strategy).isSome = true

Boolean isSome form of full driver completeness.

Completeness is what lets the total wrapper HexRootsMathlib.isolateComplexRoots from the entry-point section drop the Option and return the atom array directly, with its run equation, root count, root set, and precision exposed by the isolate_* theorems shown there. One further guarantee is stated on the wrapper: distinct atoms have disjoint closed circumscribed discs, so the certified enclosures never overlap and each root is separated from every other by exact dyadic data.

🔗theorem
HexRootsMathlib.isolateComplexRoots_disjoint (p : Hex.ZPoly) (h : Hex.HasOnlySimpleRoots p) (hp : p 0) (atomPrec : ) (strategy : Hex.AtomStrategy := Hex.AtomStrategy.nkThenPellet) {i j : } (hi : i < (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy).size) (hj : j < (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy).size) (hij : i j) : Disjoint (HexRootsMathlib.DyadicSquare.closedDisc (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy)[i].square) (HexRootsMathlib.DyadicSquare.closedDisc (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy)[j].square)
HexRootsMathlib.isolateComplexRoots_disjoint (p : Hex.ZPoly) (h : Hex.HasOnlySimpleRoots p) (hp : p 0) (atomPrec : ) (strategy : Hex.AtomStrategy := Hex.AtomStrategy.nkThenPellet) {i j : } (hi : i < (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy).size) (hj : j < (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy).size) (hij : i j) : Disjoint (HexRootsMathlib.DyadicSquare.closedDisc (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy)[i].square) (HexRootsMathlib.DyadicSquare.closedDisc (HexRootsMathlib.isolateComplexRoots p h hp atomPrec strategy)[j].square)

Distinct atoms returned by the total wrapper have disjoint closed circumscribed discs.

Behind these statements the companion develops the analysis the certificates rely on: a ported Newton-Kantorovich contraction theorem, the argument principle and Rouché's theorem for counting roots in discs, and the Mahler separation bound that keeps subdivision terminating. None of that analysis runs; it justifies, once and for all, the fixed dyadic comparisons the kernel re-checks.