Kernel-fast ℤ-list dot products for certificate data #
The pooled 49-dim scorecard (LipschitzCertScorecard.lean) evaluates its
rational dot products by simp [Fin.sum_univ_succ] <;> norm_num — fine at 49
terms, but quadratic in the sum length and ~15–20 s per 784-term dot, which
priced a FULL-INPUT (un-pooled, 784-dim) scorecard out of CI.
This file is the fix, in three parts:
- certificate data lives in
List ℤ(weightsk/2⁸, pixelsk/255— store the integer numerators; negatives asInt.negSuccliterals, which dodges a ~15 ms/elementNeg-elaboration tax); - the 784-term arithmetic is ONE kernel evaluation per dot:
dotZ xs ys = v := by decide +kernel— the kernel foldszipWith (·*·)with GMP integer ops, ~0.1 s per dot,propext-only (noofReduceBool:+kernelis the kernel evaluator, NOTnative_decide); sum_getD_div(proved once, by induction) transports the integer fact to the∑ j : Fin n, (xs.getD j 0 : ℝ)/c * ((ys.getD j 0 : ℝ)/d)sums thatdenseE-level certificate statements actually quantify over.
Used by LipschitzCertScorecardFull*.lean (generated by
scripts/lipschitz_cert_scorecard_full.py). All 3-axiom clean.
Integer dot product of two lists — the shape the kernel evaluates fast
(decide +kernel: pointer-shared tails, GMP mul/add, no Fin indexing).
Equations
- Proofs.dotZ xs ys = (List.zipWith (fun (x1 x2 : ℤ) => x1 * x2) xs ys).sum
Instances For
The scaled form the certificate files instantiate: rows stored as ℤ-lists
of numerators over denominators c, d; once dotZ xs ys = v is checked
in the kernel, the ℝ-level dense-layer dot is v/(c·d).
Integer absolute row sum — the ℓ1 weight of a row, kernel-evaluable
(decide +kernel). Feeds the IBP uniform-radius layer bound
denseLo/Hi (x ∓ ε) = ⟨w,x⟩ ∓ ε·Σ|w| (IntervalBound.lean).