Reversible classical circuits — the gate-list DSL #
Category: 1-Mathlib (CSD-free; staged as a Mathlib-upstream candidate).
A minimal, derived-cost abstraction for reversible classical circuits. The design
choice is deliberate: a circuit is a list of gates, its action is the fold of the per-gate
semantics, and (in Cost.lean) its resource cost is a function of the gate list. Resource
bounds are therefore theorems about an exhibited circuit, not numbers annotated onto an opaque
Equiv — the prerequisite for cost accounting to be genuinely machine-checked. (The
reversible-arithmetic application this substrate was built for lives in the Ecdsafail
repository, specs/ecdsa/ecdlp-resource-plan.md there.)
Each primitive gate (X flip, CX = CNOT, CCX = Toffoli, swap) is an involution:
degenerate forms (control = target) act as the identity, so every gate is its own inverse
unconditionally. Hence a circuit's inverse is the reversed gate list (inverse = List.reverse),
and denote is a bijection. State is Fin n → Bool; the bridge to the quantum register
QReg n (basis states indexed by Fin n → Fin 2) is kept out of this classical layer — it is
the embedding Reversible/Lift.lean provides (basis-state permutation semantics).
A reversible classical gate on n wires (state Fin n → Bool).
- X
{n : ℕ}
(i : Fin n)
: Gate n
Flip wire
i. - CX
{n : ℕ}
(c t : Fin n)
: Gate n
CNOT: if wire
cis set, flip wiret. Acts as the identity ifc = t. - CCX
{n : ℕ}
(c₁ c₂ t : Fin n)
: Gate n
Toffoli: if wires
c₁andc₂are both set, flip wiret. Identity ift ∈ {c₁, c₂}. - swap
{n : ℕ}
(i j : Fin n)
: Gate n
Exchange wires
iandj.
Instances For
Equations
- One or more equations did not get rendered due to their size.
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.X a) (Reversible.Gate.X b) = if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.X i) (Reversible.Gate.CX c t) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.X i) (Reversible.Gate.CCX c₁ c₂ t) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.X i) (Reversible.Gate.swap i_1 j) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CX c t) (Reversible.Gate.X i) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CX a a_1) (Reversible.Gate.CX b b_1) = if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CX c t) (Reversible.Gate.CCX c₁ c₂ t_1) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CX c t) (Reversible.Gate.swap i j) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CCX c₁ c₂ t) (Reversible.Gate.X i) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CCX c₁ c₂ t) (Reversible.Gate.CX c t_1) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.CCX c₁ c₂ t) (Reversible.Gate.swap i j) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.swap i j) (Reversible.Gate.X i_1) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.swap i j) (Reversible.Gate.CX c t) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.swap i j) (Reversible.Gate.CCX c₁ c₂ t) = isFalse ⋯
- Reversible.instDecidableEqGate.decEq (Reversible.Gate.swap a a_1) (Reversible.Gate.swap b b_1) = if h : a = b then h ▸ if h : a_1 = b_1 then h ▸ isTrue ⋯ else isFalse ⋯ else isFalse ⋯
Instances For
The Boolean state of n wires.
Equations
- Reversible.State n = (Fin n → Bool)
Instances For
Semantics of a single gate as a state transformation. Degenerate forms (control = target) are the identity, which keeps every gate an involution.
Equations
- Reversible.denoteGate (Reversible.Gate.X i) x✝ = Function.update x✝ i !x✝ i
- Reversible.denoteGate (Reversible.Gate.CX c t) x✝ = if c = t then x✝ else Function.update x✝ t (x✝ c ^^ x✝ t)
- Reversible.denoteGate (Reversible.Gate.CCX c₁ c₂ t) x✝ = if t = c₁ ∨ t = c₂ then x✝ else Function.update x✝ t (x✝ t ^^ x✝ c₁ && x✝ c₂)
- Reversible.denoteGate (Reversible.Gate.swap i j) x✝ = x✝ ∘ ⇑(Equiv.swap i j)
Instances For
Every gate is an involution (its own inverse).
A reversible circuit on n wires: a list of gates applied left to right.
Equations
Instances For
The action of a circuit: fold the per-gate semantics over the list (first gate first).
Equations
- Reversible.denote c s = List.foldl (fun (s : Reversible.State n) (g : Reversible.Gate n) => Reversible.denoteGate g s) s c
Instances For
The inverse circuit: the reversed gate list (each gate is its own inverse).
Equations
Instances For
reversible_inverse_correct (left): the inverse circuit undoes the circuit.
reversible_inverse_correct (right): the circuit undoes its inverse.
A circuit's denotation is a bijection (it has the inverse circuit as a two-sided inverse).
Wire support and the frame (locality) lemma #
A gate only touches the wires in gateWires; every other wire is preserved. Lifted to circuits,
this is the frame lemma denote_apply_of_forall_not_mem — the reusable primitive for transporting a
gadget's correctness from a concrete wire layout to arbitrary Fin n wires (consumed by the
ModAdd / ModMul arithmetic proofs).
The set of wires a gate acts on. A wire outside this set is preserved by denoteGate
(denoteGate_apply_of_not_mem).
Equations
- Reversible.gateWires (Reversible.Gate.X i) = {i}
- Reversible.gateWires (Reversible.Gate.CX c t) = {c, t}
- Reversible.gateWires (Reversible.Gate.CCX c₁ c₂ t) = {c₁, c₂, t}
- Reversible.gateWires (Reversible.Gate.swap i j) = {i, j}
Instances For
Interface lemmas (CONVENTIONS §9.1, F1): per-constructor wire sets, stated once. Not
@[simp] — existing proofs unfold by name and must keep their behaviour.
Frame lemma (single gate). A wire outside gateWires g is left unchanged by denoteGate g.
Frame lemma (circuit). A wire untouched by every gate of c is unchanged by denote c.
Stated with the per-gate membership hypothesis (the form the gadget proofs consume).