Local Validity Checker #
A computable, pure-ℚ checker that verifies whether a decision-tree row
satisfies the preconditions of the rational local theorem. Everything
here is computable — no noncomputable keyword.
Equations
Instances For
Equations
Instances For
Spanning condition: hoisted trig, scalarized applied vectors #
The rational matrix form of the ε-κ-spanning condition on the triangle T
for angles (θ, φ) (cf. Local.Triangle.κSpanning). Named so that its
Decidable instance (via Spanningℚ.check) can hoist the trig entries of
rotMℚ_mat θ φ out of the i-loop and bind the applied vectors' components
as scalars; the generic mulVec/dotProduct instances would re-evaluate the
trig partial sums on every component access.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Bool-valued Spanningℚ check: trig partial sums are evaluated once per
pose and everything the i-loop touches is bound as a scalar.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Equations
- One or more equations did not get rendered due to their size.
Instances For
The δ bound for a row: max_i ‖R·M₁·P_i − M₂·Q_i‖ / 2 + 3κ.
Equivalent to Finset.max' (Finset.image BoundDeltaℚi univ) _ (see
Row.δ_eq_max'_BoundDeltaℚi), but the trig partial sums are hoisted once
per pose for a ~6× runtime speedup.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Precomputed pairwise vertex-difference norms for Bεℚ #
The n_dv term of Bεℚ.check — sqrtApprox16.upper_sqrt.norm (Q_i − v_k) —
is pose-independent, but costs a sqrtℚUp16 call on a denominator-10³²
input for each of the 270 (i, k) pairs of every local row. sqrtDv reads
all 90 × 90 pairs from the source-literal table sqrtDvCurried (generated,
see Checker/SqrtDvLiterals.lean), and BεℚPy.check is the
pythonVertexA/sqrtApprox16 specialization of Bεℚ.check that reads it
(the Bεℚ predicate itself is unchanged). The curried-literal form keeps
the table cheap for the kernel too: an access walks a few dozen Fin.cons
cells, where reducing an equivalent 8100-entry Array.ofFn push chain made
a single high-index access cost tens of gigabytes under decide +kernel.
Table-backed pairwise vertex-difference norm: equal to
sqrtApprox16.upper_sqrt.norm (pythonVertexA a - pythonVertexA b) by sqrtDv_eq.
Equations
- Noperthedron.Solution.sqrtDv a b = Noperthedron.Solution.sqrtDvCurried a.ℓ a.i a.k b.ℓ b.i b.k
Instances For
Runtime lookup table for sqrtDv, built once per process from the
sqrtDvCurried literals; indexed by the flat pair index flat a * 90 + flat b
with flat ⟨k, ℓ, i⟩ = 45·ℓ + 15·i + k.
Equations
- Noperthedron.Solution.sqrtDvTable = Array.ofFn fun (j : Fin 8100) => Noperthedron.Solution.sqrtDv (Noperthedron.Solution.ofFlat (↑j / 90) ⋯) (Noperthedron.Solution.ofFlat (↑j % 90) ⋯)
Instances For
Array-backed implementation of sqrtDv: a per-pair curried lookup costs
~40 Fin.cons dispatches plus a Rat renormalization, which measurably slows
the compiled hot loop, so sqrtDv_eq_sqrtDvImpl (@[csimp]) substitutes this
O(1) array read in compiled code. The kernel keeps reducing the
curried-literal sqrtDv itself.
Equations
Instances For
Per-pose table of the row dot products ((M₂ vⱼ)₀, (M₂ vⱼ)₁) (unrounded)
for all 90 vertices, indexed by flat ⟨k, ℓ, i⟩ = 45·ℓ + 15·i + k. check
computes it once per pose; by linearity M₂(v₁ - v₂) = M₂v₁ - M₂v₂, each
(i, k) dot then costs one lookup and one subtraction instead of three
products.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Bεℚ.check specialized to pythonVertexA and sqrtApprox16, with the
per-pose work hoisted out of the k-loop:
- the pose-independent
n_dvnorms come from thesqrtDvCurriedliterals; - the unrounded row dots
M₂vⱼcome from the per-poserowDotstable, so a pair'sd-vector is one lookup and one subtraction (M₂(v₁-v₂) = M₂v₁-M₂v₂); - the scalars
F2,cD,eterm,tenκ,twoκ,bdare loop-invariant.
Each (i, k) pair first tries a cheap sufficient test (the left disjunct)
that avoids the per-pair upper_sqrt.f call on the denominator-10²⁶ input
d0² + d1²: by Cauchy–Schwarz, d0² + d1² ≤ (F·n_dv + 2·10⁻¹³)² where F
is a per-pose Frobenius-norm bound (one sqrt call per pose), so the
fixed-point accuracy bound sqrtℚUp16 x ≤ Y + 2·10⁻¹⁶ caps the exact
denom2 by F·n_dv + 2·10⁻¹³ + 2·10⁻¹⁶ + 2·√⁺2·ε + 6κ
(see cheap_sufficient). Only pairs
that fail the cheap test — binding or near-binding k — fall back to the
exact test in the right disjunct; the Or/And Decidable instances are
macro_inline, so evaluation short-circuits.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Specialized decision procedure for the Bεℚ conjunct of Row.ValidLocal;
the priority bump makes Row.ValidLocal's Decidable instance pick it over
the generic Bεℚ.instDecidable.
Equations
- Noperthedron.Solution.BεℚPy.instDecidablePy Qi p ε δ r = decidable_of_iff (Noperthedron.Solution.BεℚPy.check Qi p ε δ r = true) ⋯
Kernel-path vertex reads for the remaining Row.ValidLocal conjuncts #
The Aεℚσ/Spanningℚ/BoundRℚ conjuncts read vertices through
pythonVertexA; under decide +kernel its backing Array.ofFn push chain
re-reduces as a quadratic List.concat walk (~150k list-step unfoldings per
local row — the dominant cost, per kernel diagnostics). These instances
transport each conjunct to the curried pythonVertex, whose lookups cost the
kernel a few dozen Fin.cons steps; compiled code still gets O(1) array
reads via pythonVertex's @[csimp].
Equations
- Noperthedron.Solution.Aεℚσ.instDecidablePyV X idx ε σ approx = decidable_of_iff (Local.TriangleQ.Aεℚσ X (Noperthedron.pythonVertex ∘ idx) ε σ approx) ⋯
Equations
- Noperthedron.Solution.Spanningℚ.instDecidablePyV θ φ ε idx = decidable_of_iff (Noperthedron.Solution.Spanningℚ θ φ ε (Noperthedron.pythonVertex ∘ idx)) ⋯
Equations
- Noperthedron.Solution.BoundRℚ.instDecidablePyV r ε p idx approx = decidable_of_iff (RationalApprox.LocalTheorem.BoundRℚ r ε p (Noperthedron.pythonVertex ∘ idx) approx) ⋯
Assertion that a row constitutes a valid application of the rational global theorem.
The vertex functions are the table-backed pythonVertexA (equal to
pythonVertex by pythonVertexA_eq), so the hot loops of the Decidable
instance read precomputed coordinates instead of re-dividing on every access.
- exists_symmetry : ∃ (s : TriangleSymmetry), s.applicable row.Qi ∧ ∀ (i : Fin 3), row.Pi i = s.apply (row.Qi i)
- X₁_inner_gt : Local.TriangleQ.Aεℚσ row.X₁ (pythonVertexA ∘ row.Pi) row.epsilon 0 RationalApprox.sqrtApprox16
- X₂_inner_gt : Local.TriangleQ.Aεℚσ row.X₂ (pythonVertexA ∘ row.Qi) row.epsilon (↑row.sigma_Q) RationalApprox.sqrtApprox16
- r_valid : RationalApprox.LocalTheorem.BoundRℚ row.r row.epsilon row.interval.centerPose (pythonVertexA ∘ row.Qi) RationalApprox.sqrtApprox16
- Bεℚ : Local.TriangleQ.Bεℚ row.Qi pythonVertexA row.interval.centerPose row.epsilon row.δ row.r RationalApprox.sqrtApprox16
Instances For
Equations
- One or more equations did not get rendered due to their size.
Smoke test #
Row 245 from data/solution_tree_300.csv — the first local leaf.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.