Sparse natural counts on distinct well-formed sign conditions. Root completeness is a property of the producing replay and its interpretation, not a consequence of these structural invariants alone.
39.8. HexSignDet: sign tables and Thom encodings
39.8.1. Sign determination
A Sturm–Tarski query gives a signed sum. Sign determination gives the
complete distribution: how many distinct roots realize each ordered list
of query signs. HexSignDet implements the Ben-Or–Kozen–Reif method
using the shared Sturm–Tarski query and checked integer
linear algebra. It also supplies Thom encodings for selected roots,
comparisons of full encodings and signs at a selected root.
The computational import is HexSignDet; it is Mathlib-free. The
HexSignDetTheory umbrella exports the finite algebraic correspondence
and the root interpretation, producer and conversion theorems used below.
The individual HexSignDetTheory.TableProducer,
HexSignDetTheory.ThomRoots and HexSignDetTheory.Naturality imports
are also available in the normal companion target. Both libraries are
unreleased; these development imports do not establish availability in a
published companion package.
Tau Ceti is a dependency of the Mathlib proofs, never of the computation.
39.8.2. Sparse tables with exact counts
For query polynomials Q₁, …, Qₙ, a sign condition is a list of n
integers from -1, 0, 1. Order matters, and repeated or zero queries
keep their positions. Each count is a natural number of distinct roots;
it is not a multiplicity or a signed sum.
Only positive counts are stored in Hex.SignDet.SignTable.rows.
Hex.SignDet.SignTable.count returns zero for an omitted condition,
including malformed conditions. Structural well-formedness of a table
does not itself prove that its rows describe polynomial roots.
Hex.SignDet.determine.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [Neg E] [Inv E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) (reduced : Bool := true) : Option (Hex.SignDet.SignTable qs.length)Hex.SignDet.determine.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [Neg E] [Inv E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) (reduced : Bool := true) : Option (Hex.SignDet.SignTable qs.length)
Sign determination returns none exactly when preparation rejects the
root domain. A valid domain uses the total prepared operation, retaining the
supplied query order and exact counts, including omitted conditions.
The domain is the same as for Sturm: a nonzero squarefree head and an
open interval with strictly ordered, root-free endpoints. Here the head
is X²-1, and the queries are X and X-1. The root -1 contributes
[-1, -1]; the root 1 contributes [1, 0].
open Hex Hex.SignDet
namespace SignTables
def x : DensePoly Rat :=
DensePoly.ofCoeffs #[0, 1]
def p : DensePoly Rat :=
DensePoly.ofCoeffs #[-1, 0, 1]
def table := determine Sturm.orderSign 7
p .negInf .posInf [x, x - 1]
#guard table.map (fun t => t.rows.toList) =
some [([-1, -1], 1), ([1, 0], 1)]
#guard table.map (fun t => t.count [0, 0]) =
some 0
An empty query list has one possible sign condition, []. Its count is
the total root count. A valid domain without roots has an empty sparse
table. Neither case is an invalid domain:
#guard (determine Sturm.orderSign 7 p
.negInf .posInf []).map
(fun t => t.rows.toList) = some [([], 2)]
#guard (determine Sturm.orderSign 7
(1 : DensePoly Rat) .negInf .posInf []).map
(fun t => t.rows.toList) = some []
#guard (determine Sturm.orderSign 7
(0 : DensePoly Rat) .negInf .posInf []).isNone
end SignTables
For several queries on one head and interval, call
Hex.Sturm.prepare once and pass its result to
Hex.SignDet.buildTablePrepared or
Hex.SignDet.determinePrepared. Preparation binds the coefficient
sign function as well as the head and endpoints. It does not authorize
reuse in another coefficient context.
buildTablePrepared exposes internal construction diagnostics for
arbitrary supplied coefficient operations. determinePrepared has a
diagnostic panic branch with an empty-table fallback. The companion's
Hex.SignDet.determinePrepared_success proves that this branch is
unreachable under a lawful interpretation and the prepared sign binding.
An arbitrary provider's successful output is insufficient to establish
those hypotheses.
39.8.3. Moments, rank and literal replay
The method recursively splits the ordered queries. Tarski queries of products give moments of their sign conditions. The integer system uses a checked rank certificate and a nonzero scaled left inverse to recover counts. Zero counts are pruned; retained columns and rows keep their order. The producer and checker share these exact finite structures.
Hex.SignDet.System.check_eq characterizes acceptance of an integer
moment system: row and column shapes, ternary exponents and signs, distinct
columns, nonnegative counts, a nonzero inverse denominator, and both integer
matrix identities. The named row/column, distinctness and nonnegativity
projections expose individual guards. The characterization includes empty
systems. Completeness of the candidate support remains a separate hypothesis
when recovering actual root counts.
Hex.SignDet.Replay.check.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) : Hex.SignDet.Replay E Ctx → BoolHex.SignDet.Replay.check.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) : Hex.SignDet.Replay E Ctx → Bool
Literal recursive replay. Leaves include the root-count moment even for an empty query list. At internal nodes both children are checked before the parent solve, including when their product is empty. Thus a vacuous zero-size system never stands alone as evidence of zero roots.
Hex.SignDet.Replay.check_leaf and
Hex.SignDet.Replay.check_split characterize every branch guard.
Leaf acceptance retains the root-count row even with no queries; split
acceptance checks both children and their exact ordered support and row
products. An empty parent system cannot bypass the leaf domain evidence.
The checker accepts supplied evidence: it checks children, literal query
bindings, Tarski certificates, rank data and moment equations. It does
not accept an integer system merely because that system has a unique
solution. Hex.SignDet.System.unique proves uniqueness of an accepted finite
system. Under a lawful coefficient interpretation,
Hex.SignDet.Replay.count_roots proves that any accepted replay
has exactly the actual root counts, including omitted sign conditions.
Coefficient storage need not carry a Mathlib field instance or have an injective representation. Computation uses explicit operations and a total sign function. Its mathematical interpretation must preserve the operations used and reflect zero: only the stored zero may have value zero. Nonzero values may have several representatives. This distinction permits canonical fields and noncanonical representatives to use the same polynomial API.
39.8.4. Selecting a root with derivatives
A Thom encoding records signs of formal derivatives of the original head. Derivatives retain their original scaling: a sign-changing normalization would change the encoding. Derivative indices start at one, are distinct and lie within the head's degree.
Hex.SignDet.RawDescriptor.{u, v} (E : Type u) (Ctx : Type v) [Zero E] [DecidableEq E] : Type (max u v)Hex.SignDet.RawDescriptor.{u, v} (E : Type u) (Ctx : Type v) [Zero E] [DecidableEq E] : Type (max u v)
Unvalidated literal input for a selected squarefree root. Derivative polynomials are reconstructed from the head; callers supply only their indices and signs.
Constructor
Hex.SignDet.RawDescriptor.mk.{u, v}
A raw descriptor is a claim. Hex.SignDet.Descriptor contains
accepted count-one evidence for that exact context, head, interval and
ordered derivative list. A partial list of derivatives can select a root
when its sign condition has count one; well-formedness alone is insufficient.
Hex.SignDet.RawDescriptor.wellFormed_iff characterizes positive degree,
matching lengths, distinct valid derivative slots and ternary signs. A partial
selection need not contain the highest derivative. The separate
Hex.SignDet.RawDescriptor.check_iff characterizes complete literal
acceptance: that shape, the expected context, accepted replay for the exact
head, interval and derivative queries, and a count-one row. It applies to supplied evidence as
well as evidence returned by a producer.
The first derivative of X²-1 is 2X. Its negative and positive signs
select the two roots even on the whole line, without rational separators.
The empty derivative word on that same interval is ambiguous.
namespace ThomRoots
open SignTables
def raw (signs : List Int) :
RawDescriptor Rat Nat :=
⟨7, p, .negInf, .posInf, [1], signs⟩
def accepted (r : RawDescriptor Rat Nat) :
Bool :=
match Descriptor.build
Sturm.orderSign 7 r with
| .ok (.ok _) => true
| _ => false
#guard accepted (raw [-1])
#guard accepted (raw [1])
#guard !accepted (raw [0])
#guard !accepted {raw [1] with context := 8}
#guard !accepted
{raw [] with indices := [], signs := []}
end ThomRoots
Hex.SignDet.Descriptor.buildRoots constructs the complete root
list from full derivative words. The mathematical producer theorem below
proves success, complete coverage, absence of duplicates and strict order.
Multiplicity handling and adjoining the selected algebraic root belong
to the real-closure library.
For finite row extraction, Hex.SignDet.Descriptor.rootsFrom_length
shows that successful extraction returns one descriptor per supplied row.
Hex.SignDet.Descriptor.rootsFrom_counts shows that each accepted row
has count one. These counts are occurrences of full sign words, rather than
polynomial root multiplicities. Passing only some table rows to the helper
does not establish that all roots were enumerated: the public producer uses
its complete actual table, and the companion proves mathematical coverage.
Hex.SignDet.Descriptor.rootsFromTable_eq identifies shared-table
extraction with literal per-descriptor checking, including its errors and
ordering. The permutation and strict-order laws preserve the supplied words
and establish order by the finite comparator; the companion then identifies
that comparator with the order of the interpreted roots.
For supplied certificates, Hex.SignDet.Descriptor.rootsFrom_coverage
proves complete coverage and absence of duplicate root values from accepted
full replay and extraction of the complete table. It requires the companion's
coefficient interpretation and sign laws, and an ordered real-closed target.
Hex.SignDet.Descriptor.rootsFrom_ordered proves strict mathematical
order for any successful extraction, including a partial row list. These
exports let proof consumers check supplied evidence and use its root list
without proving that it came from native root production.
For full encodings of the same head, the Thom comparison rule inspects
the highest differing derivative slot. The shared sign in the immediately
next higher derivative slot must be
nonzero and determines its direction. A zero or missing next slot returns
none:
#guard Thom.compareSigns [-1, 1] [1, 1] =
some .lt
#guard Thom.compareSigns [1] [-1] = none
Hex.SignDet.Thom.compareSigns checks a finite word rule. It does
not establish root realization or compare roots of different heads.
Use Hex.SignDet.Descriptor.fullOrder on validated full descriptors
with their literal head and context checks. Reencoding to a different
head and cross-field comparison require the corresponding checked
conversion and embedding laws.
Under a lawful interpretation, including negation and inverse, in an ordered
real closed field, Hex.SignDet.Descriptor.complete
extends a validated selected-root word to all derivative slots. Use
Hex.SignDet.Descriptor.buildCompletion for its diagnostics.
Hex.SignDet.RawDescriptor.completes_iff describes the literal
bindings, canonical full target slots and exact source-word restriction
checked by completion. Both descriptors still need their own count-one replay. The separate
Hex.SignDet.Descriptor.fullOrder_iff characterizes comparison
success by the common head, canonical full slots and finite word result.
Under a lawful interpretation in an ordered real closed field,
Hex.SignDet.Descriptor.fullOrder_root identifies that result with
the order of the denoted roots.
For different stored heads,
Hex.SignDet.Descriptor.buildComparison retains a checked common
polynomial and both original-root re-encodings. The common domain is the
whole line; each original open interval is retained through query signs.
Hex.SignDet.CommonProduct.check_iff characterizes the literal
bindings and three polynomial identities. Squarefreeness is checked separately.
Hex.SignDet.Descriptor.checkReencoding_iff characterizes the exact
target head and interval, complete joint replay and count one for the joint
word of target signs followed by the original source constraints.
These checks describe accepted evidence; the companion's lawful interpretation
hypotheses supply root preservation and actual producer success.
39.8.5. Signs at a selected root and shared evidence
Hex.SignDet.SelectedSigns combines the descriptor's derivative
queries with the caller's exact ordered query list. Its checker requires
a complete joint table whose descriptor prefix has exactly one extending
row of count one. Counting one matching row without excluding other
matching observations would not justify the selected signs.
Hex.SignDet.RawDescriptor.checkSigns.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (raw : Hex.SignDet.RawDescriptor E Ctx) (qs : List (Hex.DensePoly E)) (values : Vector ℤ qs.length) (t : Hex.SignDet.Replay E Ctx) : BoolHex.SignDet.RawDescriptor.checkSigns.{u, v} {E : Type u} {Ctx : Type v} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] (sign : E → ℤ) (context : Ctx) (raw : Hex.SignDet.RawDescriptor E Ctx) (qs : List (Hex.DensePoly E)) (values : Vector ℤ qs.length) (t : Hex.SignDet.Replay E Ctx) : Bool
Joint table replay on the selected formal derivatives and the exact additional query list. Filtering must give exactly the claimed count-one row, including every requested sign. No singleton-interval shortcut is used.
Hex.SignDet.RawDescriptor.checkSigns_eq characterizes all four
acceptance conditions. For a validated descriptor,
Hex.SignDet.Descriptor.checkSigns_eq uses its existing shape and
context proof, leaving the joint replay and unique extending row of count one
to establish.
For repeated queries at one validated root,
prepareQueries retains the prepared domain in a
QueryHandle. Its success criterion
prepareQueries_isSome is exactly success of preparation on
the descriptor's original sign function, head and endpoints, without producing query answers.
buildSigns_eq proves agreement with ordinary
query production. Supplied evidence still goes through the descriptor checker,
as stated by checkSigns_eq; retaining a domain
does not bypass replay checks. Moving a handle to equal coefficient operations
requires literal operation equalities, as in
changeOps, rather than equality of selected roots.
The companion theorem
prepareQueries_success
proves preparation succeeds for every validated descriptor under the stated
lawful coefficient interpretation; arbitrary coefficient operations retain
possible failure.
The DAG interfaces share repeated evidence. Encode a tree with
Hex.SignDet.Dag.encode, validate the graph once with
Hex.SignDet.Dag.validate?, then use its memo for several selections.
Select a stored result with Hex.SignDet.Dag.select?.
Hex.SignDet.Dag.select_isSome characterizes success: the index exists
and the stored ordered queries equal the requested list. Selection reuses the
accepted tree without running its checker again.
Hex.SignDet.Dag.select_values identifies that tree with the stored entry.
The memo fixes the sign function, context, head and endpoints in its type.
Hex.SignDet.Dag.bindDomain? accepts a requested head and endpoints only
when they literally equal the memo's own; context stays fixed.
Hex.SignDet.Dag.bindDomain_isSome characterizes these three bindings,
and Hex.SignDet.Dag.bindDomain_values shows that accepted transport
preserves every stored tree.
Forward references, missing entries and invalid unreachable entries reject:
validation checks every stored entry, not only entries reachable from the root.
Hex.SignDet.Replay.signOperands and
Hex.SignDet.Dag.signOperands expose finite coefficient-sign
dependencies. Their congruence lemmas transfer the exact checker result
when a replacement sign function agrees on every required operand.
These inventories may contain repetitions and are not execution traces.
Cross-level context reconstruction and automatic arithmetic evidence
remain distinct from these finite congruence laws.
39.8.6. Printing and reading a selected-root subject
The HexSignDet umbrella includes
Hex.SignDet.Codec.descriptor and
Hex.SignDet.Codec.readDescriptor. They encode and read all six
fields of a raw descriptor: context, head, lower endpoint, upper endpoint,
derivative indices and derivative signs. The derivative lists retain their
order. The reader rejects malformed records, but a parsed record is still
an unchecked root claim.
Use Hex.SignDet.Codec.readDescriptorBinding when a packet must
refer to a particular caller-supplied descriptor. It compares the complete
parsed subject with that descriptor, including the indices and signs that
distinguish roots of the same head on the same interval. Successful binding
gives the following literal equality through the existing public theorem:
namespace RootPackets
open Codec
variable (raw : RawDescriptor Rat Nat)
variable (packet : Json)
variable
(accepted : readDescriptorBinding
ValueCodec.rat ValueCodec.nat
raw packet = .ok ())
example : readDescriptor
ValueCodec.rat ValueCodec.nat
packet = .ok raw :=
readDescriptorBinding_checked
ValueCodec.rat ValueCodec.nat
raw packet accepted
end RootPackets
This theorem establishes subject binding. Root validity requires a
Hex.SignDet.Descriptor carrying accepted count-one evidence;
Hex.SignDet.Descriptor.ofReplay? is one way to obtain it.
The owning DescriptorCodec conformance module checks changed contexts,
heads, the lower endpoint, indices and signs, as well as malformed field counts and
coefficient records.
Hex.SignDet.Codec.read_descriptor_of proves that printing and
reading the subject preserves it literally. Its hypotheses require the
coefficient reader to cover the stored head and finite endpoints, and the
context reader to cover this actual context. A partial coefficient reader
need not satisfy a roundtrip law for every possible coefficient.
The low-level integer-only JSON parser
Json.readBytes reconstructs a complete
value and rejects trailing tokens. It applies no byte, nesting or integer-digit
limit; certificate APIs run
Codec.checkBytes before parsing.
The native value parser's
readLoop_tokens law reconstructs
emitted tokens with an arbitrary suffix when fuel exceeds the value's structural
rank, which accounts for width and depth. The byte-roundtrip theorem
readBytes_write uses this law.
Object field order and
duplicate keys remain literal data; reconstruction asserts no arithmetic truth.
For full replay graphs, Hex.SignDet.Dag.encodeBytes prints the
literal graph and Hex.SignDet.Codec.decodeGraph parses it after
the byte syntax and resource checks. Parsing checks references, context and domain
bindings; Hex.SignDet.Dag.decodeBytes additionally runs replay
against the caller's sign operation and ordered query list.
Hex.SignDet.Dag.decode_replays identifies the returned checked
tree with the parsed graph's actual replay result.
The decode-time check Codec.bindings fixes
the node's and every stored moment's context, head and both endpoints.
bindings_iff characterizes those four
literal equalities.
bindings_of_check derives them
from an accepted node check. Replay separately binds query lists and query polynomials;
equal coefficient meanings alone do not satisfy the decode-time check. Neither
this binding nor reconstruction supplies an arithmetic or root-count conclusion.
The parser bounds are recorded by
Shape: row and column lengths, basis-rank
bounds, and indices in stored reductions and preparation. The theorem
Shape.of_validate derives these
bounds from successful graph validation for every stored entry, including
unreachable entries. These structural bounds are weaker than validation:
graphs with false arithmetic evidence can also satisfy them. Reconstruction
alone does not establish arithmetic correctness; replay checks that evidence
independently.
Hex.SignDet.Codec.decode_graph_covered proves the byte roundtrip
for partial readers covering every stored graph coefficient and context.
It also requires a valid root index, the node shape, context and domain bindings
for every entry, earlier-only child references, and acceptance by the
byte syntax and resource checks. Subject coverage alone does not establish
these graph conditions.
The finite coverage inventories
Coefficients.graph and
graphContexts include every stored
coefficient and context, including witnesses in unreachable entries. A
partial reader need only satisfy
Covers on these actual inventories;
the readers need not roundtrip values outside these inventories.
Dag.expand? reconstructs a tree from the graph
without validating arithmetic evidence. Structural expansion reads entries
in order. The criterion
Expansion.step_isSome says a leaf
always expands, while a split needs both child lookups in the supplied memo.
expand_encode recovers any supplied tree
literally after encoding, including a tree whose arithmetic evidence is invalid.
check_encode_eq preserves both
checker acceptance and rejection. Mapping nodes with
mapNodes retains every index and ordered edge;
it carries no proof that the new nodes pass replay.
Hex.SignDet.Dag.decodeDescriptor checks graph bytes against the
caller's full raw descriptor and returns a validated count-one descriptor.
Hex.SignDet.Dag.decodeSigns checks supplied query signs against an
already validated descriptor, using the supplied graph's joint-table evidence.
Neither reader calls the selected-sign producer to replace missing evidence.
Hex.SignDet.Dag.decodeDescriptor_raw preserves the exact requested
subject; Hex.SignDet.Dag.decodeSigns_evidence preserves the caller's
claimed signs exactly and identifies the checked replay used for them.
39.8.7. Shared coefficient evidence
Dependencies.Graph stores packets with
explicit lower-level references. Every reference contains the complete literal
subject, rather than just a context hash. Structural checking covers every
stored entry, including entries outside the selected result paths; each child
must point backward and have a strictly lower coefficient level.
Dependencies.Graph.decode first
parses the bytes and binds the ordered requested levels and subjects, then
uses the caller's local packet reader. The reader owns arithmetic acceptance
and coverage of every coefficient fact its packet needs. Its result type may
express proved facts, but the shared envelope does not supply those proofs.
validate_entries
preserves every literal packet in checking order, and
Decoded.memo_size gives
one memo position per stored packet. Selecting
Decoded.results retains root
order and repetitions, sharing the stored results. The theorem
results_bound preserves
the caller's full ordered levels and subjects.
decode_encode composes
the actual printer and byte parser with an accepted local-reader run. Its
remaining byte premise is the syntax and resource precheck. The existing
DependenciesConformance fixture reuses shared lower-level sign facts and
checks false, stale, missing, forward, cyclic and same-level dependencies,
including invalid unused packets. These finite packet laws do not construct
a common field or supply missing arithmetic evidence for a general tower.
39.8.8. Converting coefficients and contexts
To move a selected root to another coefficient representation, use
Hex.SignDet.Descriptor.convert. This operation maps the literal
subject and builds fresh checked evidence with the target sign operation
and context. Its result distinguishes an internal Hex.SignDet.BuildError
from an input diagnostic for the mapped subject, such as an invalid domain
or an absent or ambiguous sign condition. Merely changing a context tag does not authorize
reuse of the original certificate.
The correspondence uses source and target interpretations in one ordered
real-closed field. Value preservation means g (convert a) = f a for every
coefficient a, with source interpretation f and target interpretation g.
The conversion must also reflect zero. Each law states the arithmetic and
sign hypotheses it uses. Conversion success uses target negation and inverse
laws; root preservation needs neither interpretation's negation or inverse
laws. Selected-root sign and comparison laws additionally use source negation
and inverse; comparison also uses division. With its stated hypotheses,
Hex.SignDet.Descriptor.convert_success proves actual conversion
success, and Hex.SignDet.Descriptor.convert_root proves preservation
of the selected root. The checked returned descriptors also satisfy:
-
Hex.SignDet.Descriptor.convert_signAtpreserves the total sign at that root for the converted query polynomial. -
Hex.SignDet.Descriptor.convert_comparepreserves all three comparison results after both descriptors convert successfully, even when they have different defining polynomials.
For tables and root lists, run the existing producers on the mapped head,
endpoints and ordered queries, using the same reduced flag for the table
calls. The following laws compare those actual
source and target runs; they do not convert an already returned table or
convert each descriptor in an existing root list:
-
Hex.SignDet.determine_convert_isSomepreserves the table API's success domain.Hex.SignDet.determine_convert_countsequates every count in actual returned tables, including omitted sign words. -
Hex.SignDet.Descriptor.buildRoots_convert_isSomepreserves root-list success.Hex.SignDet.Descriptor.buildRoots_convert_rootsidentifies the interpreted, ordered returned root lists, including empty lists.
These are value-preserving conversion laws with explicit semantic
hypotheses. They do not construct a common coefficient field or an
ordinary-real realization of a nested tower. The owning FieldChecks
conversion cases exercise Hex.SignDet.Descriptor.convert and
Hex.SignDet.Descriptor.signAt; its root-list cases use unconverted
inputs. The producer-run conversion laws above have ordinary-kernel
axiom checks in the owning RootSemantics diagnostic module.
39.8.9. The Mathlib correspondence
The interpretation targets an ordered real-closed field, which may be non-Archimedean. Sign tables and Thom encodings therefore apply to infinitesimal coefficients without rational separating intervals. The laws relate the supplied coefficient operations and sign function to that model; they do not construct a joint ordinary-real realization of an arbitrary nested tower.
Hex.SignDet.determine_correct.{u, v, w} {E : Type u} {K : Type v} {Ctx : Type w} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [Neg E] [Inv E] [DecidableEq Ctx] [Field K] [DecidableEq K] [LinearOrder K] [IsStrictOrderedRing K] [IsRealClosed K] (f : E → K) (hz : ∀ (a : E), f a = 0 ↔ a = 0) (h1 : f 1 = 1) (ha : ∀ (a b : E), f (a + b) = f a + f b) (hs : ∀ (a b : E), f (a - b) = f a - f b) (hm : ∀ (a b : E), f (a * b) = f a * f b) (hnat : ∀ (n : ℕ), f ↑n = ↑n) (hn : ∀ (a : E), f (-a) = -f a) (hi : ∀ (a : E), f a⁻¹ = (f a)⁻¹) (sign : E → ℤ) (hsign : ∀ (a : E), sign a = ↑(SignType.sign (f a))) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) (reduced : Bool) (table : Hex.SignDet.SignTable qs.length) (h : Hex.SignDet.determine sign context p a b qs reduced = some table) : HexSturmTheory.Domain f hz p a b ∧ ∀ (word : List ℤ), table.count word = {x ∈ HexRealRootsTheory.Tarski.rootsIn (HexPolyTheory.Interpret.interpret f hz p) (Hex.Endpoint.map f a) (Hex.Endpoint.map f b) | Hex.SignDet.signsAt f hz qs x = word}.cardHex.SignDet.determine_correct.{u, v, w} {E : Type u} {K : Type v} {Ctx : Type w} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [Neg E] [Inv E] [DecidableEq Ctx] [Field K] [DecidableEq K] [LinearOrder K] [IsStrictOrderedRing K] [IsRealClosed K] (f : E → K) (hz : ∀ (a : E), f a = 0 ↔ a = 0) (h1 : f 1 = 1) (ha : ∀ (a b : E), f (a + b) = f a + f b) (hs : ∀ (a b : E), f (a - b) = f a - f b) (hm : ∀ (a b : E), f (a * b) = f a * f b) (hnat : ∀ (n : ℕ), f ↑n = ↑n) (hn : ∀ (a : E), f (-a) = -f a) (hi : ∀ (a : E), f a⁻¹ = (f a)⁻¹) (sign : E → ℤ) (hsign : ∀ (a : E), sign a = ↑(SignType.sign (f a))) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (qs : List (Hex.DensePoly E)) (reduced : Bool) (table : Hex.SignDet.SignTable qs.length) (h : Hex.SignDet.determine sign context p a b qs reduced = some table) : HexSturmTheory.Domain f hz p a b ∧ ∀ (word : List ℤ), table.count word = {x ∈ HexRealRootsTheory.Tarski.rootsIn (HexPolyTheory.Interpret.interpret f hz p) (Hex.Endpoint.map f a) (Hex.Endpoint.map f b) | Hex.SignDet.signsAt f hz qs x = word}.card
A returned table has the exact mathematical root counts on the supplied polynomial and interval. Queries retain their order, repetitions and zeros.
This theorem characterizes every returned count, including omitted words.
Hex.SignDet.buildTablePrepared_success establishes actual producer
success, while Hex.SignDet.determine_isSome characterizes the domain.
These producer obligations are separate from the arbitrary-certificate
soundness proved by Hex.SignDet.Replay.count_roots.
Hex.SignDet.Descriptor.buildRoots_roots.{u, v, w} {E : Type u} {K : Type v} {Ctx : Type w} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] [Field K] [DecidableEq K] [LinearOrder K] [IsStrictOrderedRing K] [IsRealClosed K] (f : E → K) (hz : ∀ (a : E), f a = 0 ↔ a = 0) (h1 : f 1 = 1) (ha : ∀ (a b : E), f (a + b) = f a + f b) (hs : ∀ (a b : E), f (a - b) = f a - f b) (hm : ∀ (a b : E), f (a * b) = f a * f b) (hnat : ∀ (n : ℕ), f ↑n = ↑n) {sign : E → ℤ} (hsign : ∀ (a : E), sign a = ↑(SignType.sign (f a))) [Neg E] [Inv E] (hn : ∀ (a : E), f (-a) = -f a) (hi : ∀ (a : E), f a⁻¹ = (f a)⁻¹) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (hdom : HexSturmTheory.Domain f hz p a b) : ∃ out, Hex.SignDet.Descriptor.buildRoots sign context p a b = Except.ok (some out) ∧ (∀ (x : K), x ∈ HexRealRootsTheory.Tarski.rootsIn (HexPolyTheory.Interpret.interpret f hz p) (Hex.Endpoint.map f a) (Hex.Endpoint.map f b) ↔ x ∈ List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out) ∧ (List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out).Nodup ∧ List.Pairwise (fun x1 x2 => x1 < x2) (List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out)Hex.SignDet.Descriptor.buildRoots_roots.{u, v, w} {E : Type u} {K : Type v} {Ctx : Type w} [Zero E] [DecidableEq E] [One E] [Add E] [Sub E] [Mul E] [NatCast E] [DecidableEq Ctx] [Field K] [DecidableEq K] [LinearOrder K] [IsStrictOrderedRing K] [IsRealClosed K] (f : E → K) (hz : ∀ (a : E), f a = 0 ↔ a = 0) (h1 : f 1 = 1) (ha : ∀ (a b : E), f (a + b) = f a + f b) (hs : ∀ (a b : E), f (a - b) = f a - f b) (hm : ∀ (a b : E), f (a * b) = f a * f b) (hnat : ∀ (n : ℕ), f ↑n = ↑n) {sign : E → ℤ} (hsign : ∀ (a : E), sign a = ↑(SignType.sign (f a))) [Neg E] [Inv E] (hn : ∀ (a : E), f (-a) = -f a) (hi : ∀ (a : E), f a⁻¹ = (f a)⁻¹) (context : Ctx) (p : Hex.DensePoly E) (a b : Hex.Endpoint E) (hdom : HexSturmTheory.Domain f hz p a b) : ∃ out, Hex.SignDet.Descriptor.buildRoots sign context p a b = Except.ok (some out) ∧ (∀ (x : K), x ∈ HexRealRootsTheory.Tarski.rootsIn (HexPolyTheory.Interpret.interpret f hz p) (Hex.Endpoint.map f a) (Hex.Endpoint.map f b) ↔ x ∈ List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out) ∧ (List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out).Nodup ∧ List.Pairwise (fun x1 x2 => x1 < x2) (List.map (fun d => Hex.SignDet.Descriptor.root f hz h1 ha hs hm hnat hsign d) out)
On every valid domain, the actual producer returns every mathematical root exactly once and in strictly increasing order. The domain may use finite or infinite endpoints; coefficient storage need not be injective.
Interpretation laws are explicit arguments, including separate source and target laws for conversion. The required laws and their positional order vary with the theorem. Use named arguments for these laws, as below, so the application records their meaning without depending on a shared argument order.
The following specialization reuses the same complete-producer theorem as the downstream sign consumer. Given a mathematical root in a valid domain, it obtains a descriptor from the actual returned list without assuming that production succeeded.
open HexPolyTheory.Interpret
open HexRealRootsTheory
open scoped Classical
namespace RootCoverage
noncomputable section
def value (d : Descriptor ℝ Nat
Sturm.orderSign 7) : ℝ :=
d.root (f := id)
(hz := fun _ => Iff.rfl) (h1 := rfl)
(ha := fun _ _ => rfl)
(hs := fun _ _ => rfl)
(hm := fun _ _ => rfl)
(hnat := fun _ => rfl)
(hsign := HexSturmTheory.orderSign_eq)
variable (p : DensePoly ℝ)
variable (a b : Endpoint ℝ)
variable
(domain : HexSturmTheory.Domain
id (fun _ => Iff.rfl) p a b)
variable (x : ℝ)
example (member : x ∈ Tarski.rootsIn
(interpret id (fun _ => Iff.rfl) p)
(a.map id) (b.map id)) :
∃ out,
Descriptor.buildRoots
Sturm.orderSign 7 p a b =
.ok (some out) ∧
∃ d ∈ out, value d = x := p:DensePoly ℝa:Endpoint ℝb:Endpoint ℝdomain:HexSturmTheory.Domain id ⋯ p a bx:ℝmember:x ∈ Tarski.rootsIn (interpret id ⋯ p) (Endpoint.map id a) (Endpoint.map id b)⊢ ∃ out, Descriptor.buildRoots Sturm.orderSign 7 p a b = Except.ok (some out) ∧ ∃ d ∈ out, value d = x
p:DensePoly ℝa:Endpoint ℝb:Endpoint ℝdomain:HexSturmTheory.Domain id ⋯ p a bx:ℝmember:x ∈ Tarski.rootsIn (interpret id ⋯ p) (Endpoint.map id a) (Endpoint.map id b)out:List (Descriptor ℝ ℕ Sturm.orderSign 7)produced:Descriptor.buildRoots Sturm.orderSign 7 p a b = Except.ok (some out)coverage:∀ (x : ℝ),
x ∈ Tarski.rootsIn (interpret id ⋯ p) (Endpoint.map id a) (Endpoint.map id b) ↔
x ∈ List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) outleft✝:(List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) out).Nodupright✝:List.Pairwise (fun x1 x2 => x1 < x2) (List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) out)⊢ ∃ out, Descriptor.buildRoots Sturm.orderSign 7 p a b = Except.ok (some out) ∧ ∃ d ∈ out, value d = x
p:DensePoly ℝa:Endpoint ℝb:Endpoint ℝdomain:HexSturmTheory.Domain id ⋯ p a bx:ℝmember:x ∈ Tarski.rootsIn (interpret id ⋯ p) (Endpoint.map id a) (Endpoint.map id b)out:List (Descriptor ℝ ℕ Sturm.orderSign 7)produced:Descriptor.buildRoots Sturm.orderSign 7 p a b = Except.ok (some out)coverage:∀ (x : ℝ),
x ∈ Tarski.rootsIn (interpret id ⋯ p) (Endpoint.map id a) (Endpoint.map id b) ↔
x ∈ List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) outleft✝:(List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) out).Nodupright✝:List.Pairwise (fun x1 x2 => x1 < x2) (List.map (fun d => Descriptor.root id ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ d) out)⊢ ∃ d ∈ out, value d = x
All goals completed! 🐙
end
end RootCoverage
The owning conformance suites separately guard ordinary-kernel axioms and check the table, descriptor, selected-sign, replay and codec contracts. Exact Z3 and python-flint oracles check emitted fixtures. The retained BKR/Thom performance reports distinguish computation, replay and witness growth; neither the examples here nor theorem-application timings supply computational performance evidence.