Documentation

CsdLean4.Mathlib.QuantumInfo.Reversible.ModularAddCtrl

Reversible controlled modular addition — (ctrl, a, b) ↦ if ctrl then (a+b) mod N else b (ECDLP Phase 2, Stage S6.3c) #

Category: 1-Mathlib (CSD-free; staged as a Mathlib-upstream candidate).

This module verifies the controlled modular-addition VALUE primitive — the controlled analogue of S6.3b's modAdd — by chaining two already-verified blocks:

cModAdd L = cRippleCirc L.cAddStep ++ modReduce L.reduceStep

So the headline value is B ← if ctrl then (a + b) mod N else b.

Carve line (what this is, and is NOT) #

This VERIFIES the controlled modular-addition value primitive B ← if ctrl then (a+b) mod N else b by chaining the verified cRippleCirc (S2) with S6.3a's modReduce; the unconditional reduce is correct in both branches because b < N is already a valid residue. This is / mod N bit arithmetic — NO field / group semantics are in play.

This is the inner-loop primitive of the interleaved MSB-first modular MULTIPLY over 𝔽_p (the next stage, S6.3d), which also needs a modular DOUBLING gadget (2·acc mod N, the register-to-itself add) and the Horner loop invariant. This module is NOT the multiply.

Named residue (same as S6.3b; name it): the carry chains Ccadd, C1, C2 and the comparison flag C1 n are left DIRTY after cModAdd. Correctness holds because the layout supplies fresh wires per use (cModAdd_correct requires C* / anc initialised false). In-place reuse across the many additions of a modular multiply needs carry-clean / ancilla-restoring adders (Cuccaro-style inline carry-uncompute, or reversing carry generation) which the corpus's rippleCirc / cRippleCirc do NOT provide. That carry-clean adder is the genuine orthogonal residue, NOT built here.

Honest cost #

cModularAdd_toffoli derives 18n Toffolis from the exhibited gate list: controlled add step 8n (cRippleCirc_toffoli, the quantum×quantum overhead) + reduce step 10n (modReduceCtrl_toffoli), composed through cost_comp_toffoli_count. (Heavier than S6.3b's uncontrolled 12n precisely by the quantum×quantum cost of the controlled add, 8n vs 2n.)

structure Reversible.CModAddLayout (m n : ) :

A controlled-modular-addition layout on Fin m for n-bit registers. Like ModAddLayout but the add step is a CRippleLayout: it bundles the operand register Aop (read-only addend a), the accumulator B (holds b, overwritten with if ctrl then (a+b) mod N else b), the controlled-add step's own carry chain Ccadd, the control wire ctrl, the cRipple shared ancilla ancC, and the reduce sub-data (A1, A2, C1, C2, anc).

The geometry fields give: (i) cAddStep : CRippleLayout well-formed (Aop, B, Ccadd, ctrl, ancC pairwise disjoint + bounded-injective), (ii) reduceStep : ModReduceLayout well-formed, and (iii) Ccadd, Aop, ctrl, ancC all disjoint from every reduce-step wire so the controlled-add step's carries / ancilla are fresh and the operand + control bit survive the whole circuit.

Injectivity fields are bounded (< n for registers, < n + 1 for carry chains), exactly as ModAddLayout / ModReduceLayout / MulLayout: an unbounded ℕ → Fin m injectivity field is uninhabitable and would make the theorems vacuous.

Instances For

    The controlled add step as a CRippleLayout: operand Aop + accumulator B + add-carry chain Ccadd, controlled on ctrl, with shared ancilla ancC.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For

      The reduce step as a ModReduceLayout (S6.3a).

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        def Reversible.cModAdd {m n : } (L : CModAddLayout m n) :

        The controlled modular-addition circuit. Controlled register add (cRippleCirc) followed by the S6.3a single-step modular reduction (modReduce), the latter run unconditionally.

        Equations
        Instances For

          Frame: a wire disjoint from cAddStep's wires survives the controlled add step #

          cRippleCirc L.cAddStep touches only {ctrl, ancC} ∪ {Aop k, B k, Ccadd k}. Any wire distinct from all of those passes through unchanged (cRippleCirc_preserves_external). The four corollaries below specialise it to the reduce step's A1 / A2 / C1 / C2 / anc wires.

          theorem Reversible.cModAdd_cAddStep_preserves_A1 {m n : } {L : CModAddLayout m n} (s : State m) (j : ) :
          denote (cRippleCirc L.cAddStep) s (L.A1 j) = s (L.A1 j)

          After the controlled add step, A1 is unchanged on every wire (disjoint from the add step).

          theorem Reversible.cModAdd_cAddStep_preserves_A2 {m n : } {L : CModAddLayout m n} (s : State m) (j : ) :
          denote (cRippleCirc L.cAddStep) s (L.A2 j) = s (L.A2 j)

          After the controlled add step, A2 is unchanged on every wire.

          theorem Reversible.cModAdd_cAddStep_preserves_C1 {m n : } {L : CModAddLayout m n} (s : State m) (j : ) :
          denote (cRippleCirc L.cAddStep) s (L.C1 j) = s (L.C1 j)

          After the controlled add step, C1 is unchanged on every wire.

          theorem Reversible.cModAdd_cAddStep_preserves_C2 {m n : } {L : CModAddLayout m n} (s : State m) (j : ) :
          denote (cRippleCirc L.cAddStep) s (L.C2 j) = s (L.C2 j)

          After the controlled add step, C2 is unchanged on every wire.

          After the controlled add step, anc is unchanged.

          Frame: the operand Aop and the control bit ctrl survive the reduce step #

          modReduce L.reduceStep touches only {A1, A2, C1, C2, anc, B} (and the flag C1 n). Since Aop and ctrl are disjoint from all of these, they pass through the reduce step unchanged.

          theorem Reversible.cModAdd_reduceStep_preserves_Aop {m n : } {L : CModAddLayout m n} (s : State m) (j : ) :
          denote (modReduce L.reduceStep) s (L.Aop j) = s (L.Aop j)

          Operand frame through the reduce step. Aop j is untouched by modReduce L.reduceStep.

          Control frame through the reduce step. ctrl is untouched by modReduce L.reduceStep.

          Value correctness #

          theorem Reversible.cModAdd_correct {m n : } (L : CModAddLayout m n) (s : State m) (hCcadd : ∀ (j : ), s (L.Ccadd j) = false) (hancC : s L.ancC = false) (hC1 : ∀ (j : ), s (L.C1 j) = false) (hC2 : ∀ (j : ), s (L.C2 j) = false) (hanc : s L.anc = false) {N a b : } (h2N : 2 * N 2 ^ n) (hA1 : regValRange L.A1 s n = 2 ^ n - N) (hA2 : regValRange L.A2 s n = N) (hAop : regValRange L.Aop s n = a) (hB : regValRange L.B s n = b) (haN : a < N) (hbN : b < N) :
          regValRange L.B (denote (cModAdd L) s) n = if s L.ctrl = true then (a + b) % N else b

          The verified controlled modular-addition value primitive. For a disjoint-wire CModAddLayout with all carry chains (Ccadd, C1, C2) and both ancillas (ancC, anc) initialised false, register A1 preset to 2ⁿ − N, register A2 preset to N, operand register Aop holding a, accumulator B holding b, with a < N, b < N, 2N ≤ 2ⁿ: cModAdd L leaves register B holding if ctrl then (a + b) mod N else b.

          Proof. The controlled add step (cRippleCirc_correct) writes if ctrl then (a + b) mod 2ⁿ else b = if ctrl then a + b else b to B (no wrap, since a + b < 2N ≤ 2ⁿ), preserving Aop = a and — via the frame lemmas — the reduce step's presets A1 = 2ⁿ − N, A2 = N and clean carries C1 = C2 = false, anc = false. In both control branches B < 2N (ctrl: a + b < 2N; ¬ctrl: b < N < 2N), so the unconditional reduce step (modReduce_correct, S6.3a) maps B to B mod N: (a + b) mod N in the ctrl branch, and b mod N = b in the ¬ctrl branch (b < N, Nat.mod_eq_of_lt). The reduce being unconditional is the whole trick: b is already a valid residue.

          theorem Reversible.cModAdd_preserves_operand {m n : } (L : CModAddLayout m n) (s : State m) (hCcadd : ∀ (j : ), s (L.Ccadd j) = false) (hancC : s L.ancC = false) {a : } (hAop : regValRange L.Aop s n = a) :

          The operand register is intact. cModAdd L leaves Aop holding a (read-only addend). The controlled add step preserves Aop (P2 of the controlled-ripple invariant) and the reduce step is disjoint from Aop.

          theorem Reversible.cModAdd_preserves_ctrl {m n : } (L : CModAddLayout m n) (s : State m) (hCcadd : ∀ (j : ), s (L.Ccadd j) = false) (hancC : s L.ancC = false) :
          denote (cModAdd L) s L.ctrl = s L.ctrl

          The control bit is preserved. cModAdd L leaves ctrl at its initial value (it is read by the controlled add step, never written, and the reduce step is disjoint from it). The interleaved modular multiply needs this to keep each partial-product's control bit equal to the original register bit across the accumulation loop.

          theorem Reversible.cModAdd_in_range {m n : } (L : CModAddLayout m n) (s : State m) (hCcadd : ∀ (j : ), s (L.Ccadd j) = false) (hancC : s L.ancC = false) (hC1 : ∀ (j : ), s (L.C1 j) = false) (hC2 : ∀ (j : ), s (L.C2 j) = false) (hanc : s L.anc = false) {N a b : } (h2N : 2 * N 2 ^ n) (hA1 : regValRange L.A1 s n = 2 ^ n - N) (hA2 : regValRange L.A2 s n = N) (hAop : regValRange L.Aop s n = a) (hB : regValRange L.B s n = b) (haN : a < N) (hbN : b < N) :
          regValRange L.B (denote (cModAdd L) s) n < N

          The controlled modular-addition output is a genuine residue in [0, N). In both branches: (a + b) % N < N (ctrl set) and b < N (ctrl clear). Corollary of cModAdd_correct.

          Derived cost #

          Derived Toffoli cost of the controlled modular adder: 18n Toffolis, from the exhibited gate list. Controlled add step 8n (cRippleCirc_toffoli, the quantum×quantum overhead) + reduce step 10n (modReduceCtrl_toffoli), composed through cost_comp_toffoli_count. Heavier than S6.3b's uncontrolled 12n precisely by the cost of the controlled add (8n vs 2n).

          Non-vacuity witness #

          A concrete 3-bit controlled-modular-addition layout on Fin 27:

          (n = 3 is needed, as in S6.3b: the modular adder requires 2N ≤ 2ⁿ so the controlled add does not wrap; for N = 3 that forces 2ⁿ ≥ 6, i.e. n ≥ 3.) This exhibits that CModAddLayout is inhabited, so the headlines are not vacuously quantified. The concrete runs below exercise both control branches at fully-specified input states: a = 2, b = 2, N = 3, ctrl = true ↦ (2+2) mod 3 = 1, and the same a, b with ctrl = false ↦ B stays b = 2.

          A concrete 3-bit controlled-modular-addition layout on Fin 27.

          Equations
          • One or more equations did not get rendered due to their size.
          Instances For

            Interface lemmas (CONVENTIONS §9.1, F1): the wire assignments of the concrete layout, one lemma per field.

            cModAddLayout2's operand register wires.

            cModAddLayout2's accumulator wires.

            cModAddLayout2's controlled-add carry-chain wires.

            cModAddLayout2's controlled-add clean-ancilla wire.

            cModAddLayout2's step-1 constant-register wires.

            theorem Reversible.cModAddLayout2_C1 (i : ) :
            cModAddLayout2.C1 i = if i = 0 then 13 else if i = 1 then 14 else if i = 2 then 15 else 16

            cModAddLayout2's step-1 carry-chain wires.

            cModAddLayout2's step-3 constant-register wires.

            theorem Reversible.cModAddLayout2_C2 (i : ) :
            cModAddLayout2.C2 i = if i = 0 then 20 else if i = 1 then 21 else if i = 2 then 22 else 23

            cModAddLayout2's step-3 carry-chain wires.

            def Reversible.cModAddState2 (a0 a1 a2 b0 b1 b2 c : Bool) :

            Concrete input state for n = 3, N = 3: operand Aop = a (wires 0,1,2), accumulator B = b (wires 3,4,5), control wire 25 = ctrl, A1 = 5 = 2³ − 3 (wires 10,12), A2 = 3 (wires 17,18), all carries / ancillas false. Parameterised by the data bits of a, b, and the control bit.

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              theorem Reversible.cModAddState2_apply (a0 a1 a2 b0 b1 b2 c : Bool) (w : Fin 27) :
              cModAddState2 a0 a1 a2 b0 b1 b2 c w = if w = 0 then a0 else if w = 1 then a1 else if w = 2 then a2 else if w = 3 then b0 else if w = 4 then b1 else if w = 5 then b2 else if w = 10 then true else if w = 12 then true else if w = 17 then true else if w = 18 then true else if w = 25 then c else false

              The concrete input state at a wire, as its defining case chain (interface lemma, §9.1).

              theorem Reversible.cModAddState2_pre (a0 a1 a2 b0 b1 b2 c : Bool) :
              (∀ (j : ), cModAddState2 a0 a1 a2 b0 b1 b2 c (cModAddLayout2.Ccadd j) = false) cModAddState2 a0 a1 a2 b0 b1 b2 c cModAddLayout2.ancC = false (∀ (j : ), cModAddState2 a0 a1 a2 b0 b1 b2 c (cModAddLayout2.C1 j) = false) (∀ (j : ), cModAddState2 a0 a1 a2 b0 b1 b2 c (cModAddLayout2.C2 j) = false) cModAddState2 a0 a1 a2 b0 b1 b2 c cModAddLayout2.anc = false regValRange cModAddLayout2.A1 (cModAddState2 a0 a1 a2 b0 b1 b2 c) 3 = 2 ^ 3 - 3 regValRange cModAddLayout2.A2 (cModAddState2 a0 a1 a2 b0 b1 b2 c) 3 = 3

              The hypotheses of cModAdd_correct hold at cModAddState2 (carries/ancillas clear, A1 = 5, A2 = 3), for any data / control bits. The regValRange register-value preconditions are concrete sums, discharged by decide.