Fast #eval-able reversible-circuit evaluation — the Array Bool bridge (ECDLP testing infra) #
Category: 1-Mathlib (CSD-free; staged as a Mathlib-upstream candidate). This is testing infrastructure, not part of the ECDLP cost / correctness claims.
Purpose #
A strict Array Bool-backed evaluator (runArr) for Reversible.Circuit, with a proven bridge
(runArr_apply, regValRangeArr_eq) to the reference denote semantics. The point is fast,
theorem-independent value cross-checks: #eval-ing runArr / regValRangeArr on a concrete
circuit witness produces a number that is certified equal (by the bridge lemmas) to the
denote / regValRange value the correctness theorems are stated about. So the #eval checks the
real denote-based semantics, not a separate evaluator.
The pathology it fixes #
The reference state is State n := Fin n → Bool and denoteGate uses Function.update (and, for
swap, Equiv.swap). Under #eval / native_decide these are lazy: reading one final-wire bit
of denote c s re-reads the inner state through the whole gate history. A CCX reads 3 bits, so a
single final-bit read recurses 3 ^ depth through the fold — exponential blowup. On the Fin 27,
61-gate cModAdd circuit this hangs.
runArr represents the state as a strict Array Bool: each gate is O(1) array work
(Array.set! / Array.getElem!), the whole run is O(gates), no re-reads. It evaluates instantly.
The bridge #
applyGate_apply— the step lemma:applyGate g amatchesdenoteGate g swire-for-wire, givenarepresentss(a.size = mand∀ j, a[j]! = s j), and preserves the representation.runArr_apply— headline:(runArr c (ofState s))[i]! = denote c s ifor alli. Induction onc, maintaining the representation invariant;ofStateseeds it viaArray.getElem_ofFn.regValRangeArr_eq— the consumer-facing bridge:regValRangeArr f (runArr c (ofState s)) k = regValRange f (denote c s) k(aFinset.sum_congroverrunArr_apply). So#eval regValRangeArr f (runArr c (ofState s)) kis a fast number, equal to theregValRange f (denote c s) kof the correctness theorems.
runArr_apply and regValRangeArr_eq are pure structural / arithmetic proofs (foundational triple
only); no native_decide appears in any proven lemma. The demonstration examples below use
decide / rfl on small witnesses to exhibit a green, fast, theorem-independent value check.
A single gate's action on a strict Array Bool state. Each gate is O(1) array work
(Array.getElem! / Array.set!). Degenerate forms (control = target) act as the identity, mirroring
denoteGate. Out-of-bounds indices are inert (set! = setIfInBounds); on a size-m array indexed
by Fin m every access is in bounds, which is what the bridge lemmas assume.
Equations
- Reversible.applyGate (Reversible.Gate.X i) a = a.set! ↑i !a[↑i]!
- Reversible.applyGate (Reversible.Gate.CX c t) a = if c = t then a else a.set! (↑t) (a[↑c]! ^^ a[↑t]!)
- Reversible.applyGate (Reversible.Gate.CCX c₁ c₂ t) a = if t = c₁ ∨ t = c₂ then a else a.set! (↑t) (a[↑t]! ^^ a[↑c₁]! && a[↑c₂]!)
- Reversible.applyGate (Reversible.Gate.swap i j) a = (a.set! (↑i) a[↑j]!).set! (↑j) a[↑i]!
Instances For
Run a circuit on a strict Array Bool state (fold applyGate over the gate list). O(gates).
Equations
- Reversible.runArr c a = List.foldl (fun (a : Array Bool) (g : Reversible.Gate m) => Reversible.applyGate g a) a c
Instances For
Seed the array representation of a State m. (ofState s).size = m and (ofState s)[j]! = s j.
Equations
Instances For
The representation predicate and the bridge #
Local getElem!-only rewrite lemmas for set! (= setIfInBounds). Stated purely in
Array.getElem! to keep proof terms term-independent (the dependent getElem bounds proof breaks
rw). Both route a[i]! through a[i]? via Array.getElem!_eq_getD.
The step lemma. If a represents s, then applyGate g a represents denoteGate g s:
the size is preserved and (applyGate g a)[i]! = denoteGate g s i wire-for-wire. Cased on g;
each case is Array.set! (= setIfInBounds) reasoning matched against Function.update /
Equiv.swap.
runArr preserves the representation invariant (fold of applyGate_apply).
Bridge headline. The strict Array Bool run of a circuit on ofState s reproduces the
reference denote semantics wire-for-wire: (runArr c (ofState s))[i]! = denote c s i. So an #eval
of runArr is a faithful, fast computation of denote.
The register-value bridge (regValRange) #
Consumer-facing bridge. The fast Array-backed register read equals the reference
regValRange of the denote semantics. Hence #eval regValRangeArr f (runArr c (ofState s)) k is a
fast number, certified equal to the regValRange f (denote c s) k the correctness theorems use.
Demonstration: a green, fast, theorem-independent value cross-check #
The Fin m denote evaluator blows up under #eval on a many-gate circuit (lazy Function.update
re-reads, exponential in depth). runArr evaluates instantly. The witness is the S6.3a 2-bit
reducer modReduceLayout2 : ModReduceLayout 13 2 at the x = 3 ↦ 0 subtract-branch state.
The #eval prints the fast Array-backed value; the example confirms — fast, via decide — that
the Array-backed register read equals that number; and regValRangeArr_eq certifies that this same
number is the regValRange (denote …) of modReduce_correct.