python v~0.38

Mitiq

Error mitigation for quantum computers

Quick install

pip install mitiq

Background and History

Mitiq was created by the Unitary Fund, a non-profit organization dedicated to supporting the open-source quantum computing ecosystem. The project was first released in September 2020, with Ryan LaRose, Andrea Mari, and Nathan Shammah among the core developers. Mitiq was motivated by a practical problem facing anyone running algorithms on near-term quantum hardware: noise degrades results significantly, but full quantum error correction requires far more qubits than current devices provide. Error mitigation techniques offer a middle path, improving the quality of noisy results through classical post-processing rather than additional physical qubits.

The Unitary Fund, founded by Will Zeng in 2018, operated as a micro-grant program supporting open-source quantum software before expanding into direct software development. Mitiq was its flagship project. The initial release focused on zero-noise extrapolation (ZNE), a technique where noise is intentionally amplified at multiple levels and the zero-noise limit is extrapolated mathematically. Subsequent releases added probabilistic error cancellation (PEC), Clifford data regression (CDR), digital dynamical decoupling, and other techniques, building a comprehensive toolkit covering the major error mitigation methods from the research literature.

A key design decision was framework agnosticism. Mitiq accepts circuits from Cirq, Qiskit, PyQuil, and Amazon Braket, converting them internally as needed. Users supply an executor function that runs circuits and returns expectation values, and Mitiq handles the noise amplification, sampling, and extrapolation around that executor. This architecture means Mitiq can be inserted into existing workflows regardless of which quantum framework or hardware provider a team uses.

As of 2025, Mitiq is actively maintained with regular releases and has accumulated over 350 GitHub stars. It is the most widely used open-source error mitigation library and has been cited in numerous research papers. The Unitary Fund continues to support its development through grants and community contributions. Mitiq’s role in the ecosystem has become increasingly important as the quantum computing field focuses on extracting useful results from noisy intermediate-scale quantum (NISQ) hardware.

Installation

pip install mitiq

Mitiq works with Cirq, Qiskit, Amazon Braket, and PyQuil. It reduces noise on expectation values using classical post-processing and extra shots rather than logical qubit encoding.

Techniques

TechniqueFunctionOverhead
Zero-noise extrapolation (ZNE)zne.execute_with_zne3-5x shots
Probabilistic error cancellation (PEC)pec.execute_with_pecExponential in error rate
Clifford data regression (CDR)cdr.execute_with_cdrTraining circuit shots
Layerwise Richardson / PLMmitiq.lrePer-layer overhead

Zero-Noise Extrapolation (ZNE)

ZNE folds gates (G becomes G G-dagger G) to inflate noise at several scale factors, then extrapolates the expectation value back to zero.

import cirq
from mitiq import zne
from mitiq.zne.scaling import fold_gates_at_random

q = cirq.LineQubit.range(2)
circuit = cirq.Circuit([cirq.H(q[0]), cirq.CNOT(q[0], q[1])])

def execute(circuit):
    noise = cirq.ConstantQubitNoiseModel(cirq.depolarize(0.01))
    rho = cirq.DensityMatrixSimulator(noise=noise).simulate(circuit).final_density_matrix
    return rho[0, 0].real + rho[3, 3].real - rho[1, 1].real - rho[2, 2].real

mitigated = zne.execute_with_zne(circuit, execute)
scaled = fold_gates_at_random(circuit, scale_factor=3)

# Extrapolation factories (pass via factory= kwarg)
# zne.LinearFactory([1, 2, 3])
# zne.RichardsonFactory([1, 2, 3])
# zne.ExpFactory([1, 2, 3], asymptote=0.0)

Probabilistic Error Cancellation (PEC)

Requires a calibrated noise model; overhead grows exponentially with gate error rate.

from mitiq import pec
from mitiq.pec.representations import represent_operation_with_local_depolarizing_noise

representations = [
    represent_operation_with_local_depolarizing_noise(
        cirq.CNOT(q[0], q[1]), noise_level=0.01
    )
]
mitigated = pec.execute_with_pec(circuit, execute, representations=representations)

Qiskit Integration

from qiskit import QuantumCircuit
from mitiq import zne

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

def qiskit_executor(qc):
    from qiskit_aer import AerSimulator
    counts = AerSimulator().run(qc, shots=8192).result().get_counts()
    return (counts.get("00", 0) + counts.get("11", 0)) / 8192

mitigated = zne.execute_with_zne(qc, qiskit_executor)

All techniques improve expectation values only, not full output distributions.

Clifford Data Regression (CDR)

CDR uses near-Clifford training circuits that can be simulated classically to learn a correction model for noisy expectation values. The idea is straightforward: replace non-Clifford gates in your circuit with Clifford gates to create “training” circuits, run those circuits on both the noisy backend and a classical simulator, then fit a regression model that maps noisy values to ideal values. That learned correction is then applied to the noisy result of the original circuit.

import cirq
import numpy as np
from mitiq import cdr

# Build a circuit with non-Clifford gates (T gates are non-Clifford)
q = cirq.LineQubit.range(2)
circuit = cirq.Circuit([
    cirq.H(q[0]),
    cirq.T(q[0]),          # non-Clifford gate
    cirq.CNOT(q[0], q[1]),
    cirq.T(q[1]),          # non-Clifford gate
])

# Noisy executor (simulates hardware noise)
def noisy_executor(circuit):
    noise = cirq.ConstantQubitNoiseModel(cirq.depolarize(0.02))
    rho = cirq.DensityMatrixSimulator(noise=noise).simulate(circuit).final_density_matrix
    obs = np.diag([1, -1, -1, 1])  # ZZ observable
    return np.real(np.trace(rho @ obs))

# Ideal executor for training circuits (noiseless classical simulation)
def ideal_executor(circuit):
    rho = cirq.DensityMatrixSimulator().simulate(circuit).final_density_matrix
    obs = np.diag([1, -1, -1, 1])
    return np.real(np.trace(rho @ obs))

# Run CDR: Mitiq generates near-Clifford training circuits automatically
mitigated = cdr.execute_with_cdr(
    circuit,
    noisy_executor,
    simulator=ideal_executor,
    num_training_circuits=20,  # more training circuits = better fit
)
print(f"CDR mitigated value: {mitigated:.4f}")

CDR works best when the circuit has a small number of non-Clifford gates relative to total gate count. If most gates are already Clifford, the training circuits closely resemble the original, and the regression model generalizes well.

Digital Dynamical Decoupling (DDD)

Dynamical decoupling inserts identity-equivalent gate sequences into idle windows of a circuit to suppress low-frequency noise. Rather than modifying the logical operation of the circuit, DDD fills gaps where qubits sit idle with pulse sequences (like XX or XYXY) that average out coherent errors.

import cirq
from mitiq import ddd
from mitiq.ddd.rules import xx, xyxy

q = cirq.LineQubit.range(2)
circuit = cirq.Circuit([
    cirq.H(q[0]),
    # q[1] is idle here, a prime target for DD insertion
    cirq.CNOT(q[0], q[1]),
    cirq.measure(*q, key="result"),
])

def noisy_executor(circuit):
    noise = cirq.ConstantQubitNoiseModel(cirq.depolarize(0.01))
    result = cirq.DensityMatrixSimulator(noise=noise).simulate(
        cirq.drop_terminal_measurements(circuit)
    ).final_density_matrix
    return result[0, 0].real + result[3, 3].real

# Using the XX rule (two X gates = identity)
mitigated_xx = ddd.execute_with_ddd(
    circuit,
    noisy_executor,
    rule=xx,
)

# Using the XYXY rule (more robust against certain noise channels)
mitigated_xyxy = ddd.execute_with_ddd(
    circuit,
    noisy_executor,
    rule=xyxy,
)

print(f"XX mitigated: {mitigated_xx:.4f}")
print(f"XYXY mitigated: {mitigated_xyxy:.4f}")

The XYXY sequence provides better suppression of both dephasing and amplitude damping compared to XX, at the cost of inserting more gates. For hardware with fast single-qubit gates relative to idle time, XYXY is typically the better choice.

Combining Techniques

Mitiq techniques can be layered. A common pattern is to apply DDD at the circuit level (to suppress coherent errors during idle periods) and then wrap the whole execution in ZNE (to extrapolate away the remaining incoherent noise). Here is an example using a Qiskit circuit on a noisy Aer simulator.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error
from mitiq import zne
from mitiq.zne.scaling import fold_global

# Build a small Qiskit circuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.rz(0.3, 0)
qc.cx(0, 1)

# Set up a noisy Aer backend
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(depolarizing_error(0.02, 1), ["h", "rz"])
noise_model.add_all_qubit_quantum_error(depolarizing_error(0.04, 2), ["cx"])

noisy_sim = AerSimulator(noise_model=noise_model)

def noisy_qiskit_executor(qc):
    """Execute on the noisy simulator and return P(00) + P(11) as proxy."""
    qc_meas = qc.copy()
    qc_meas.measure_all()
    counts = noisy_sim.run(qc_meas, shots=8192).result().get_counts()
    total = sum(counts.values())
    return (counts.get("00", 0) + counts.get("11", 0)) / total

# Layer ZNE with global folding and Richardson extrapolation
factory = zne.RichardsonFactory(scale_factors=[1.0, 2.0, 3.0])

mitigated = zne.execute_with_zne(
    qc,
    noisy_qiskit_executor,
    scale_noise=fold_global,
    factory=factory,
)

unmitigated = noisy_qiskit_executor(qc)
print(f"Unmitigated: {unmitigated:.4f}")
print(f"ZNE mitigated: {mitigated:.4f}")

When combining techniques, apply circuit-level methods (DDD) first, then wrap the executor with shot-level methods (ZNE, PEC). This ordering matters because ZNE needs to control noise scaling, and it should scale the already-decoupled circuit rather than the raw one.

When to Use Each Technique

TechniqueBest forOverheadRequires calibration?
ZNEGeneral-purpose mitigation; first thing to try on any NISQ workload3-5x shots (one run per scale factor)No
PECHigh-accuracy results when a precise noise model is availableExponential in circuit error rate; can require millions of shotsYes, needs a full noise characterization
CDRCircuits with few non-Clifford gates (e.g., variational ansatze with limited T-gate depth)Linear in number of training circuits (typically 10-40 extra runs)Partially; needs a noiseless simulator for training
DDDSuppressing coherent idle errors on hardware with significant T1/T2 decay during wait timesNear zero; only adds single-qubit gates in idle slotsNo
LRE (Layerwise Richardson)Deep circuits where per-layer noise characterization is feasiblePer-layer shot overhead, similar to ZNE applied layer by layerPartially; benefits from per-layer noise estimates

For most users starting out, ZNE is the recommended first step. It requires no noise model, works with any executor, and typically improves results by 20-60% on current hardware. Add DDD if your circuits have significant idle time. Move to PEC or CDR when you need tighter accuracy and can invest in calibration.

Mitiq vs Alternatives

Mitiq vs manual noise calibration. Without Mitiq, you would implement Richardson extrapolation or similar methods from scratch: manually folding circuits, collecting data at multiple noise levels, and fitting the extrapolation curve yourself. Mitiq automates this entire pipeline and handles edge cases (circuit conversion, factory selection, convergence checks). For one-off experiments, manual calibration is fine. For anything reproducible or production-adjacent, Mitiq saves significant engineering time.

Mitiq vs Qiskit Runtime error mitigation. IBM’s Qiskit Runtime Estimator includes built-in ZNE, PEC, and other mitigation options through the resilience_level parameter. These are tightly integrated with IBM hardware and benefit from backend-specific noise data that IBM collects automatically. The tradeoff: Qiskit Runtime mitigation only works on IBM backends, while Mitiq is hardware-agnostic. If you run exclusively on IBM hardware, Qiskit Runtime’s built-in options are convenient and well-tuned. If you work across multiple providers, or want full control over the mitigation strategy, Mitiq is the better choice.

Mitiq vs PEC at scale. PEC is the most theoretically rigorous technique (it can fully remove noise in principle), but its sampling overhead grows exponentially with the total noise in the circuit. For circuits with more than roughly 50-100 noisy gates, PEC becomes impractical because the number of required shots exceeds what is feasible. ZNE and CDR scale much more gracefully and are better suited to larger circuits, even though their error bounds are weaker. Mitiq implements all of these, so switching between them as circuit size changes is straightforward.

Learning Resources