Documentation

LeanPool.LowWeightPauliDynamics.Pauli.Basic

Pauli strings: the binary symplectic representation, with phase #

The paper describes an n-qubit Pauli operator as an element of {I,X,Y,Z}^{⊗n} and, in def:pauli_basis, takes the 2^{-n/2}-normalized version of that set as an orthonormal basis of operators. This file supplies a combinatorial representation of such operators — pairs of bit vectors with an explicit phase — on which the group law, the adjoint and the commutation relation are computable, and proves that any two Pauli strings either commute or anticommute.

What is defined here is the phase-extended Pauli group, not the basis of def:pauli_basis. PauliString n has 4 · 4^n elements, four phase variants of each of the 4^n signless strings, and those variants are scalar multiples of one another: toMatrix (phaseMul 1 s) = i · toMatrix s. So the image of toMatrix is not linearly independent, and toMatrix_injective — which is about the group — must not be read as saying it is. Cutting the group down to a canonical 4^n basis needs a phase normalization (phase = #{Y-sites} mod 4, so that the operator is the positive tensor product) and the 2^{-n/2} normalization. Pauli/Tensor.lean supplies the representatives with that phase and their exact Kronecker-product interpretation; Pauli/Trace.lean proves the unnormalized trace pairing, and Pauli/Coeff.lean uses the normalized Pauli 2-norm.

The representation #

A Pauli string is a pair of bit vectors together with a phase,

s = i^{phase} · X^{x} Z^{z}, x z : Fin n → ZMod 2, phase : ZMod 4.

This is the binary symplectic representation with the phase carried explicitly — the same design as inQWIRE/LeanQuantum's Pauli n = {m : ZMod 4, z x : BitVec n}, up to which of X and Z sits on the left. Stavan-Jain/QECLean makes a different choice for its Pauli group: an inductive {I,X,Y,Z}-valued function with a Fin 4 phase, from which it derives a separate, phase-forgetting symplectic vector for check matrices.

The phase is not optional bookkeeping: X * Z = -i · (i X Z) = -i Y, so the product of two elements of {I,X,Y,Z}^{⊗n} is only in that set up to a fourth root of unity, and a phaseless representation is a group only modulo phase. Carrying ZMod 4 makes the product law exact, which is what lets Pauli/Matrix.lean build a representation that is a monoid homomorphism on the nose rather than projectively.

Main definitions #

Main results #

Pauli/Weight.lean adds the weight; Pauli/Matrix.lean adds the matrix model and transports the dichotomy to operators, where Rotation.lean can consume it.

Conventions #

The phase convention i^{phase} X^x Z^z with product phase p_s + p_t + 2⟪z_s, x_t⟫ is the standard one; it is forced by Z^{z_s} X^{x_t} = (-1)^{z_s · x_t} X^{x_t} Z^{z_s}, which is what has to be paid to push the X-parts of a product to the left. Hermiticity is then phase ≡ z ⬝ᵥ x (mod 2) (isSelfAdjoint_iff_phase). Note what that does and does not fix: it pins the phase's parity, and the two admissible phases differ by 2, giving A and −A. Both are self-adjoint, so this criterion does not select a canonical sign — at one qubit it admits both Y and −Y. The canonical signless representative needs phase = #{Y-sites} mod 4, which is a finer condition than the parity one and is not used here.

The sign-to-phase embedding #

(-1)^a = i^{2a}, so a sign bit enters the phase group doubled. Every lemma here is a finite check over ZMod 2, discharged by decide.

signPhase a is the ZMod 4 phase exponent of the sign (-1)^a, defined as 2a.

Equations
Instances For
    @[simp]

    Bit vectors #

    Fin n → ZMod 2 is the vector space the x- and z-parts live in. Only characteristic two is needed from it.

    theorem Lean4LPD.bits_add_self {n : ℕ} (v : Fin n → ZMod 2) :
    v + v = 0

    Addition of bit vectors is its own inverse.

    theorem Lean4LPD.bits_add_eq_zero_iff {n : ℕ} {u v : Fin n → ZMod 2} :
    u + v = 0 ↔ u = v

    In characteristic two, u + v = 0 says u = v.

    Pauli strings #

    structure Lean4LPD.PauliString (n : ℕ) :

    An n-qubit Pauli string, written i^{phase} · X^{x} Z^{z}.

    This is a definition of a representation, not a theorem about one: Pauli/Matrix.lean supplies the operator toMatrix s this notation denotes and proves the product law below matches operator multiplication (toMatrix_mul).

    • x : Fin n → ZMod 2

      The X-part: x i = 1 where the string carries an X or a Y.

    • z : Fin n → ZMod 2

      The Z-part: z i = 1 where the string carries a Z or a Y.

    • phase : ZMod 4

      The phase exponent: the string is i^{phase} X^{x} Z^{z}.

    Instances For
      theorem Lean4LPD.PauliString.ext' {n : ℕ} {s t : PauliString n} (hx : s.x = t.x) (hz : s.z = t.z) (hp : s.phase = t.phase) :
      s = t
      theorem Lean4LPD.PauliString.ext'_iff {n : ℕ} {s t : PauliString n} :
      s = t ↔ s.x = t.x ∧ s.z = t.z ∧ s.phase = t.phase
      @[instance_reducible]

      Equality is decidable, so concrete Pauli strings can be checked by decide. Kept explicit rather than deriving, because the x and z fields are functions and the derived handler does not find Fintype.decidablePiFintype on its own.

      Equations

      The group law #

      @[instance_reducible]

      Multiplication: bit vectors add, and the phase picks up 2⟪z_s, x_t⟫ from commuting the Z-part of s past the X-part of t.

      Equations
      @[simp]
      theorem Lean4LPD.PauliString.mul_x {n : ℕ} (s t : PauliString n) :
      (s * t).x = s.x + t.x
      @[simp]
      theorem Lean4LPD.PauliString.mul_z {n : ℕ} (s t : PauliString n) :
      (s * t).z = s.z + t.z
      @[instance_reducible]

      The identity operator.

      Equations
      @[simp]
      theorem Lean4LPD.PauliString.one_x {n : ℕ} :
      x 1 = 0
      @[simp]
      theorem Lean4LPD.PauliString.one_z {n : ℕ} :
      z 1 = 0
      @[simp]
      @[instance_reducible]

      The inverse. star below is defined to be this, and star_eq_inv is therefore rfl; the theorem with content — that this really is the operator adjoint — is toMatrix_star in Pauli/Matrix.lean.

      Equations
      @[simp]
      theorem Lean4LPD.PauliString.inv_x {n : ℕ} (s : PauliString n) :
      s⁻¹.x = s.x
      @[simp]
      theorem Lean4LPD.PauliString.inv_z {n : ℕ} (s : PauliString n) :
      s⁻¹.z = s.z
      @[instance_reducible]

      The n-qubit Pauli group.

      The group law is (s * t).phase = s.phase + t.phase + signPhase (s.z ⬝ᵥ t.x) on phases and addition of bit vectors on the x- and z-parts; the inverse keeps the bit vectors and has phase -s.phase + signPhase (s.z ⬝ᵥ s.x).

      At the revision pinned by this library Mathlib has no Pauli group, no Pauli matrices and no Anticommute predicate. The Pauli group is not new to Lean: Stavan-Jain/QECLean carries NQubitPauliGroupElement, a Fin 4 phase over an inductive {I,X,Y,Z}-valued function, and proves the same commute-or-anticommute dichotomy. It is prior art to read rather than a dependency of this library.

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

      The adjoint #

      @[instance_reducible]

      The adjoint of a Pauli string, defined to be its group inverse. That this is the operator adjoint is not an assumption: Pauli/Matrix.lean proves star (toMatrix s) = toMatrix (star s) (toMatrix_star), which is where the content sits.

      Equations

      Pauli strings are unitary: the adjoint is the inverse. Definitional here, given how star is defined; the theorem with content is toMatrix_star.

      @[instance_reducible]
      Equations

      The symplectic form and the commutation dichotomy #

      The symplectic form ⟪s,t⟫ = ∑ᵢ (x_s(i) z_t(i) + z_s(i) x_t(i)) over ZMod 2, written with Mathlib's dotProduct. It is the obstruction to commuting: see commute_iff_sympForm_eq_zero.

      Equations
      Instances For
        theorem Lean4LPD.PauliString.sympForm_eq_sum {n : ℕ} (s t : PauliString n) :
        s.sympForm t = ∑ i : Fin n, (s.x i * t.z i + s.z i * t.x i)

        The symplectic form is bilinear on the right: ⟪u, s t⟫ = ⟪u, s⟫ + ⟪u, t⟫.

        The symplectic form is bilinear on the left.

        @[simp]

        The form is alternating: every Pauli string commutes with itself.

        phaseMul k s is i^k · s: the same bit vectors, the phase shifted by k.

        Equations
        Instances For
          @[simp]
          theorem Lean4LPD.PauliString.phaseMul_x {n : ℕ} (k : ZMod 4) (s : PauliString n) :
          (phaseMul k s).x = s.x
          @[simp]
          theorem Lean4LPD.PauliString.phaseMul_z {n : ℕ} (k : ZMod 4) (s : PauliString n) :
          (phaseMul k s).z = s.z
          @[simp]
          theorem Lean4LPD.PauliString.phaseMul_phase {n : ℕ} (k : ZMod 4) (s : PauliString n) :
          (phaseMul k s).phase = s.phase + k
          @[simp]

          The partner still anticommutes with the generator: ⟪G, G s⟫ = ⟪G, s⟫, by bilinearity and ⟪G, G⟫ = 0. The proof of apd:thm:local_flow_k_local pairs each Pauli s anticommuting with the generator with a partner s' = ±i G s and uses that s' is again a Hermitian Pauli anticommuting with G. This lemma is the anticommutation half (the phase ±i does not affect sympForm, see sympForm_phaseMul_right); the Hermiticity half is isSelfAdjoint_phaseMul_one_mul.

          @[simp]
          @[simp]
          theorem Lean4LPD.PauliString.phaseMul_eq_self_iff {n : ℕ} {k : ZMod 4} {s : PauliString n} :
          phaseMul k s = s ↔ k = 0

          The exact commutation law. Reversing a product multiplies it by (-1)^{⟪s,t⟫}. The two cases of apd:eq:pauli_rotation_branch, commuting and anticommuting, are the two values of this one sign.

          Two Pauli strings commute exactly when the symplectic form vanishes.

          Two Pauli strings anticommute exactly when the symplectic form is one.

          The dichotomy is exhaustive. The symplectic form takes only the values 0 and 1, so there is no third case beyond the two that apd:eq:pauli_rotation_branch lists.

          Any two Pauli strings either commute or anticommute. This is the fact that makes the two cases [G,P] = 0 and {G,P} = 0 of apd:eq:pauli_rotation_branch exhaustive, so that a Pauli rotation acting on a Pauli operator either leaves it unchanged or splits it into exactly two terms. Here anticommutation is spelled s * t = phaseMul 2 (t * s), that is s t = i² · t s = −t s.

          This is the hypothesis-level companion to Lean4LPD.rot_conj_of_commute and Lean4LPD.rot_conj_of_anticommute: those two theorems cover a commuting and an anticommuting generator, and without this lemma nothing rules out a pair of Paulis that is neither. Pauli/Matrix.lean transports it to operators as toMatrix_commute_or_anticommute, which is the form Rotation.lean consumes.

          Hermitian Pauli strings #

          Hermiticity and involutivity coincide for a Pauli string.

          Rotation.lean needs both G * G = 1 and star G = G, and in a general *-algebra the two are independent: a self-adjoint element need not square to one (take 2 in ℂ), and an element squaring to one need not be self-adjoint (take !![1,1;0,-1]). Rotation.lean notes the first of those. For a Pauli string they coincide, because star s = s⁻¹ (star_eq_inv): the string is unitary, so self-adjointness is involutivity, and one hypothesis discharges both.

          Hermiticity in coordinates: i^{phase} X^x Z^z is self-adjoint exactly when 2·phase = 2⟪z,x⟫ in ZMod 4 — equivalently, phase ≡ ⟪z,x⟫ (mod 2), the standard criterion.

          This fixes the parity of the phase and nothing more. Both solutions are admissible and they differ by 2, so a string and its negative are both self-adjoint; the criterion does not pick out a canonical sign.

          The partner Pauli i G s is again Hermitian, for Hermitian G and s with ⟪G,s⟫ = 1. Together with sympForm_mul_self_right this is the property of the partner s' = ±i G s used in the proof of apd:thm:local_flow_k_local.

          It is needed for the anticommuting branch to mean anything physically: cos(dt) s + i sin(dt) G s is an observable only if i G s is. Note the Hermitian Pauli strings are not closed under multiplication — G s itself is anti-Hermitian when G and s anticommute, which is exactly why the partner carries the factor i.

          theorem Lean4LPD.PauliString.sympForm_eq_zero_of_x_eq_zero_of_z_eq_zero {n : ℕ} {s t : PauliString n} (hx : s.x = 0) (hz : s.z = 0) :
          s.sympForm t = 0

          A Pauli string with neither an X- nor a Z-part is a phase, and a phase commutes with everything. Contrapositively: anything that anticommutes with some t has a non-trivial X- or Z-part. No self-adjointness is involved.

          Witnesses #

          Concrete elements, so that no hypothesis in this development is satisfiable only in principle. This matters twice over: sympForm G s = 1 is the hypothesis of every sharp weight bound and of the anticommuting branch, and at n = 0 it is unsatisfiable — Fin 0 → ZMod 2 is a singleton, every x and z is 0, and sympForm is identically zero, so the whole anticommuting branch is vacuous there. One qubit is enough to make it non-vacuous.

          The one-qubit X.

          Equations
          Instances For

            The one-qubit Z.

            Equations
            Instances For

              The one-qubit Y, whose phase is one of the two isSelfAdjoint_iff_phase admits. It is +Y rather than −Y; Pauli/Matrix.lean checks that entrywise.

              Equations
              Instances For

                X and Z anticommute, so the anticommuting branch has a witness and every theorem conditioned on sympForm G s = 1 says something.

                i times their product is the Hermitian partner Y, as isSelfAdjoint_phaseMul_one_mul predicts. The bare product is not: X Z = −i Y.