mimiqcircuits.decomposition.basis.stim

Stim stabilizer simulator decomposition basis.

Classes

StimBasis()

Decomposition basis targeting the Stim stabilizer simulator gate set.

class mimiqcircuits.decomposition.basis.stim.StimBasis[source]

Bases: DecompositionBasis

Decomposition basis targeting the Stim stabilizer simulator gate set.

Stim is a high-performance stabilizer circuit simulator by Craig Gidney. It supports only Clifford gates, stabilizer operations, noise channels, and quantum error correction annotations.

Decomposition Pipeline

The decomposition follows this priority order:

  1. A GateU whose angles are all zero (a pure global phase) is dropped.

  2. ZYZRewrite: GateU -> RZ * RY * RZ

  3. SpecialAngleRewrite (Clifford-only): Rotations at k*pi/2 -> Clifford gates

  4. CanonicalRewrite: Fallback for other gates

Non-Clifford rotations (angles not multiples of pi/2) will raise a DecompositionError.

Terminal Operations

Single-qubit Clifford gates:
  • GateID

  • Pauli: GateX, GateY, GateZ

  • Hadamard: GateH, GateHXY, GateHYZ

  • Phase gates: GateS, GateSDG

  • Square root gates: GateSX, GateSXDG, GateSY, GateSYDG

Two-qubit Clifford gates:
  • Controlled Pauli: GateCX, GateCY, GateCZ

  • Swap family: GateSWAP, GateISWAP, ISWAP†

  • GateDCX, GateECR

Pauli rotations by +-pi/2:
  • GateRXX, GateRYY, GateRZZ with angle +-pi/2

  • RPauli with angle +-pi/2 and a non-identity Pauli string

Angles are compared modulo 2*pi, since a rotation by 3*pi/2 equals a rotation by -pi/2 up to a global phase. Other angles are decomposed.

Feedback:
  • IfStatement of GateX, GateY or GateZ conditioned on a single bit being 1. The same gate conditioned on the bit being 0 is decomposed into the gate followed by the gate conditioned on 1. Any other conditional operation has its body decomposed while staying conditional, and raises a DecompositionError if that does not lead to a conditional Pauli.

Measurements (all Pauli bases):
  • Measure, MeasureX, MeasureY

  • Two-qubit parities: MeasureXX, MeasureYY, MeasureZZ

  • Pauli products: MeasurePauli

Resets (all Pauli bases):
  • Reset, ResetX, ResetY

Measure-and-reset (all Pauli bases):
  • MeasureReset, MeasureResetX, MeasureResetY

Noise channels:
  • PauliX, PauliY, PauliZ

  • Depolarizing1, Depolarizing2

  • PauliNoise

QEC annotations:
  • Detector, ObservableInclude, QubitCoordinates

  • Barrier

Stim Gate Mapping

MIMIQ Operation

Stim Operation

GateID

I

GateX

X

GateY

Y

GateZ

Z

GateH

H

GateHXY

H_XY

GateHYZ

H_YZ

GateS

S

GateSDG

S_DAG

GateSX

SQRT_X

GateSXDG

SQRT_X_DAG

GateSY

SQRT_Y

GateSYDG

SQRT_Y_DAG

GateCX

CNOT / CX

GateCY

CY

GateCZ

CZ

GateSWAP

SWAP

GateISWAP

ISWAP

ISWAP†

ISWAP_DAG

GateDCX

DCX (custom)

GateECR

ECR (custom)

GateRXX(+-pi/2)

SQRT_XX / SQRT_XX_DAG

GateRYY(+-pi/2)

SQRT_YY / SQRT_YY_DAG

GateRZZ(+-pi/2)

SQRT_ZZ / SQRT_ZZ_DAG

RPauli(P, +-pi/2)

SPP / SPP_DAG

IfStatement(GateX(), 1)

CX rec[-k] q

IfStatement(GateY(), 1)

CY rec[-k] q

IfStatement(GateZ(), 1)

CZ rec[-k] q

Measure

M

MeasureX

MX

MeasureY

MY

MeasureXX

MXX

MeasureYY

MYY

MeasureZZ

MZZ

MeasurePauli

MPP

Reset

R

ResetX

RX

ResetY

RY

MeasureReset

MR

MeasureResetX

MRX

MeasureResetY

MRY

PauliX

X_ERROR

PauliY

Y_ERROR

PauliZ

Z_ERROR

Depolarizing1

DEPOLARIZE1

Depolarizing2

DEPOLARIZE2

PauliNoise

PAULI_CHANNEL_1, PAULI_CHANNEL_2 or E / ELSE_CORRELATED_ERROR

Detector

DETECTOR

ObservableInclude

OBSERVABLE_INCLUDE

QubitCoordinates

QUBIT_COORDS

Example

>>> from mimiqcircuits import Circuit, GateH, GateS, GateCX
>>> from mimiqcircuits.decomposition import decompose, StimBasis
>>> from symengine import pi
>>> # Decompose Clifford circuit to Stim-compatible gates
>>> c = Circuit()
>>> c.push(GateH(), 0)
1-qubit circuit with 1 instruction:
└── H @ q[0]

>>> c.push(GateS(), 0)
1-qubit circuit with 2 instructions:
├── H @ q[0]
└── S @ q[0]

>>> c.push(GateCX(), 0, 1)
2-qubit circuit with 3 instructions:
├── H @ q[0]
├── S @ q[0]
└── CX @ q[0], q[1]

>>> decomposed = decompose(c, StimBasis())
>>> # RZ(pi/2) = S is Clifford, so this works
>>> from mimiqcircuits import GateRZ
>>> c2 = Circuit()
>>> c2.push(GateRZ(pi/2), 0)
1-qubit circuit with 1 instruction:
└── RZ((1/2)*pi) @ q[0]

>>> decomposed2 = decompose(c2, StimBasis())

Note

Non-Clifford rotations will raise a DecompositionError::
>>> from mimiqcircuits import *
>>> c3 = Circuit()
>>> c3.push(GateRZ(pi/4), 0)  # T gate is non-Clifford
1-qubit circuit with 1 instruction:
└── RZ((1/4)*pi) @ q[0]

>>> decompose(c3, StimBasis())  # raises DecompositionError doctest: +ELLIPSIS
Traceback (most recent call last):
...
mimiqcircuits.decomposition.abstract.DecompositionError: Rotation RZ cannot be decomposed into the Stim basis. Only rotations with angles that are multiples of pi/2 are Clifford gates.

See also

CliffordTBasis, QASMBasis, CanonicalBasis

isterminal(op)[source]

Check if an operation is terminal in the Stim basis.

Parameters:

op (Operation) – The operation to check.

Returns:

True if the operation is in the Stim Clifford gate set.

Return type:

bool

decompose(op, qubits, bits, zvars)[source]

Decompose a non-terminal operation toward the Stim Clifford gate set.

Applies rules in priority order:
  1. Drops a GateU whose angles are all zero (a global phase)

  2. ZYZRewrite for GateU

  3. SpecialAngleRewrite (Clifford-only) for rotations at k*pi/2

  4. CanonicalRewrite as fallback

Non-Clifford rotations (angles not multiples of pi/2) will raise an error.

Parameters:
  • op (Operation) – The operation to decompose.

  • qubits (Sequence[int]) – Qubit indices for the operation.

  • bits (Sequence[int]) – Classical bit indices for the operation.

  • zvars (Sequence[int]) – Z-variable indices for the operation.

Returns:

A Circuit containing the decomposed instructions.

Raises:

DecompositionError – If the operation cannot be decomposed to Clifford gates.

Return type:

Circuit