Skip to content

Error correction and mitigation

PauliPropagation.jl

Maintained by MSRudolph

A Julia library for Pauli propagation simulation of quantum circuits and quantum systems.

JuliaApache-2.0
PauliPropagation.jl illustration

Resource snapshot

Category

Error correction and mitigation

Stars

138

Last pushed

Apr 17, 2026Updated 4mo ago

Open issues

9

Quickstart

Get running in a few lines.

Quickstart
using PauliPropagation

nqubits = 32

observable = PauliString(nqubits, :Z, 16) # I...IZI...I

What it is

PauliPropagation.jl is maintained by MSRudolph and sits in the Error correction and mitigation lane of the open-source quantum map.

A Julia library for Pauli propagation simulation of quantum circuits and quantum systems.

Last verified by Qtangl generator on May 27, 2026

Who it's for

Researchers and advanced developers working on noise, reliability, and the realities of imperfect quantum hardware.

What you can build or learn

  • Learn how this project frames error handling or mitigation.
  • Compare whether it targets analysis, simulation, or production-minded workflows.
  • Understand where noise-aware tooling fits in a modern stack.

Code samples

Examples from the repository.

1-Basic-Example (examples/1-basic-example.ipynb)
# input_psum = PauliSum(nq)
# add!(input_psum, :Z, 32)
# add!(input_psum, [:X, :X], [1, 64])
# add!(input_psum, [:X, :Y, :Z], [1, 4, 7], 1.3)
2-Datatypes (examples/2-datatypes.ipynb)
add!(psum, :X, 2)  # this adds 1.0 * IXI
add!(psum, [:Y, :Z], [1, 3], 0.5)  # this adds 0.5 * YIZ

psum  # the display order usually does not match the order in which you added the terms, but that is fine.
3-Utility-Example (examples/3-utility-example.ipynb)
IBM_mitigated_vals = [1.01688859, 1.00387483, 0.95615886, 0.95966435, 0.83946763,
    0.81185907, 0.54640995, 0.45518584, 0.19469377, 0.01301832,0.01016334]
IBM_angles = [0.    , 0.1   , 0.2   , 0.3   , 0.4   , 0.5   , 0.6   , 0.7   , 0.8   , 1.    , 1.5707]

tn_vals = [9.99999254e-01,  9.99593653e-01,  9.95720077e-01,  9.88301532e-01,
        9.78553511e-01,  9.58023054e-01,  9.21986059e-01,  8.81726079e-01,
        8.49816779e-01,  8.24900527e-01,  7.91257641e-01,  7.37435202e-01,
        6.68573798e-01,  5.88096040e-01,  4.81874079e-01,  3.50316579e-01,
        2.26709331e-01,  1.39724659e-01,  7.86639143e-02,  4.24124371e-02,
        1.90595136e-02,  6.18879050e-03, -8.27168956e-04, -4.63372099e-03,
       -7.05202121e-03, -7.68387421e-03, -6.33121142e-03, -4.32594440e-03,
        6.52050191e-04,  1.72598340e-04,  5.64696020e-05, -7.70582375e-07]
tn_angles = LinRange(0, π/2, length(tn_vals));


google_vals = [1, 0.9957248494988796,0.9785691808859784,0.9227771228638144,0.8549387301071374,
    0.7790027681081058,0.6093954499261214,0.4257824480390532,0.2090085348069826,0.0116245678393245, -4.8872551798147e-09]
google_angles = [0.000, 0.100, 0.200, 0.300, 0.400,0.500,0.600,0.700,0.800,1.000,1.571];

License

Apache-2.0

SPDX identifier detected from the repository metadata or license files.

Repository README

Preview from the project README.

Rendered as Markdown inside a scrollable preview. Long READMEs stay contained; expand or open on GitHub for the full document.

~1,277 words · about 6 min readOpen on GitHub
DocumentationPaper

PauliPropagation.jl

PauliPropagation.jl is a Julia package for simulating Pauli propagation in quantum circuits and systems. It focuses on simulating the evolution of observables expressed in the Pauli basis under the action of unitary gates and non-unitary channels in a quantum circuit.

Unlike traditional simulators which simulate a circuit $\mathcal{E}$ evolving the state $\rho$ in the Schrödinger picture, Pauli propagation often adopts the Heisenberg picture, evolving an observable $O$ under $\mathcal{E}^\dagger$. This can be particularly efficient when the observables remain sparse or structured under evolution, and is useful for estimating expectation values such as $\text{Tr}\left[\rho \mathcal{E}^{\dagger}(O)\right]$, studying operator dynamics, and computing correlation functions.

Pauli propagation is related to the so-called (extended) stabilizer simulation, but is fundamentally different from, for example, tensor networks. It offers a distinct approach that can handle different regimes of quantum dynamics.

Implemented in Julia, PauliPropagation.jl combines high-performance computation (using features such as multiple dispatch) with an accessible and high-level interface.

Installation

Note the current package requires Julia 1.10+.

The PauliPropagation.jl package is registered and can be installed into your environment in the following way:

using Pkg
Pkg.add("PauliPropagation")

Install from GitHub

If you want to install the latest code, you can install the package directly from the Github link. For example, if you are working with a Jupyter notebook, run

using Pkg
Pkg.add(url="https://github.com/MSRudolph/PauliPropagation.jl.git", rev="branchname")

where you can use the keyword rev="branchname" to install development versions of the package. We don't recommend using branches other than main or dev.

A note on installing Julia

It is recommended to install julia using juliaup with instructions from here. Then, Julia's long-term support version (currently a 1.10 version) can be installed via

juliaup add lts

To get started running Jupyter notebooks, start a Julia session and install the IJulia package.

If you are working on several projects with potentially conflicting packages, it is recommended to work with within local environments or projects.

For more details, we refer to this useful guide.

Quick Start

You can find detailed example notebooks in the examples folder. We provide a brief example of how to use PauliPropagation.jl.

Consider simulating the dynamics of an operator $O=Z_{16}$ under the evolution of a unitary channel $\mathcal{E}(\cdot) = U^\dagger \cdot U$ in a $n=32$ qubits system.

using PauliPropagation

nqubits = 32

observable = PauliString(nqubits, :Z, 16) # I...IZI...I

Our goal is to compute

\text{Tr}[U^\dagger O U \rho].

A simple unitary $U$ is the brickwork circuit, composed of two qubit gates alternating neighbouring sites. We define the circuit connectivity by

topology = bricklayertopology(nqubits; periodic=true)

where periodic specifies the boundary condition of the gates. The library has built-in circuits with e.g. a circuit containing alternating RX and RZZ Pauli gates on the topology. This can be defined by Trotterization of a transverse field Ising Hamiltonian with $l$ steps

U = \prod_{a=1}^{l} \prod_{j=1}^n e^{-i dt   X_j} e^{-i dt Z_j Z_{j+1}}.
nlayers = 32 # l as above

circuit = tfitrottercircuit(nqubits, nlayers; topology=topology)

In our simulations, we can choose the circuit parameter $dt$

dt = 0.1 # time step

parameters = ones(countparameters(circuit)) * dt # all parameters

Important: The circuit and parameters are defined in the order that they would act in the Schrödinger picture. Within our propagate() function, the order will be reversed to act on the observable.

During the propagation via propagate(), we employ truncation strategies such as coefficient or weight truncations, these options can be specified as keywords.

## the truncations
max_weight = 6 # maximum Pauli weight

min_abs_coeff = 1e-4 # minimal coefficient magnitude

## propagate through the circuit
pauli_sum = propagate(circuit, observable, parameters; max_weight, min_abs_coeff)

The output pauli_sum gives us an approximation of propagated Pauli strings

U^\dagger O U \approx \sum_{\alpha} c_{\alpha} P_{\alpha}

Finally we can compute expectation values with an initial state such as $\rho = (|0 \rangle \langle 0 |)^{\otimes n}$

## overlap with the initial state
overlapwithzero(pauli_sum)
# yields 0.154596728241...

This computation is efficient because the initial state can be written in terms of only $\mathbb{I}$ and $Z$ strings

\rho = \left(\frac{\mathbb{I} + Z}{2}\right)^{\otimes n}

Therefore, the trace is equivalent to the sum over the coefficients of Pauli strings containing only I and Z Paulis,

\mathrm{Tr}[U^\dagger O U \rho] \approx \sum_{\alpha \in \{\mathbb{I}, Z\}\, \text{strings}} c_{\alpha}.

Important Notes and Caveats

  • Circuits are specified in the Schrödinger picture, as if operated upon states. Behind the scenes, propagate() will (by default) apply the adjoint circuit upon the passed PauliSum which is treated as the observable operator. The default can be changed by passing heisenberg=false to propagate(), though it will not make simulating dense quantum states efficient.
  • Schrödinger propagation via heisenberg=false is supported since version 0.7, but not for all gates. So far, we natively support PauliRotation, CliffordGate, and <:PauliNoise gates. ImaginaryPauliRotation is only supported with heisenberg=false.
  • While Pauli propagation can, in principle, be used for extended stabilizer simulation, we do not currently support sub-exponential strong simulation of stabilizer states.
  • Sampling quantum states is currently not supported, but is coming soon.
  • Many underlying data structures and functions can be used for other purposes involving Pauli operators.

All of the above can be addressed by writing the additional missing code due to the nice extensibility of Julia.

Upcoming Features

This package is still work-in-progress. You will probably find certain features that you would like to have and that are currently missing.
Here are some features that we want to implement in the future. Feel free to contribute!

  • GPU acceleration. Since version 0.7, we provide a PauliPropagationCUDA extension in ext/. So far, it only works with PauliRotation gates and is not yet maximally performant.
  • Stochastic evolution. Propagation methods are mainly memory-limited. We aim to change this and introduce time vs memory trade-offs.

How to contribute

We have a Slack channel #pauli-propagation in the Julia Slack.

If something bothers you or you want to propose an enhancement, please open an Issue describing everything in detail.

For a concrete change of code, please fork this GitHub repository and submit a Pull Request.

Otherwise, feel free to reach out to the developers!

Authors

The main developer of this package is Manuel S. Rudolph in the Quantum Information and Computation Laboratory of Prof. Zoë Holmes at EPFL, Switzerland. Contact Manuel via manuel.rudolph@epfl.ch.

Further contributors to this package include Yanting Teng, Tyson Jones, and Su Yeon Chang. This package is the derivative of ongoing work at the Quantum Information and Computation lab at EPFL, supervised by Prof. Zoë Holmes.

For more specific code issues, bug fixes, etc. please open a GitHub issue.

Citation

If you are publishing research using PauliPropagation.jl, please cite this library and our paper:

@article{rudolph2025pauli,
  title={Pauli Propagation: A Computational Framework for Simulating Quantum Systems},
  author={Rudolph, Manuel S and Jones, Tyson and Teng, Yanting and Angrisani, Armando and Holmes, Zoe},
  journal={arXiv preprint arXiv:2501.13101},
  year={2025},
  url={https://arxiv.org/abs/2501.13101}
}

Related publications

Some of the developers of this package are co-authors in the following papers using Pauli propagation and (at least parts of) this code. If you are using our package, please consider citing some of these works:

And more are coming up.

Read on GitHub

Activity

Latest release

—

Watchers

3

Python support

—

Learn digest

Get monthly updates when library entries change.

Monthly digest: new library entries, updated flagships, and one editorial pick.

Related resources

Keep exploring nearby tools.

quantumlib

Cirq

Python framework for creating, editing, and running Noisy Intermediate-Scale Quantum (NISQ) circuits.

PythonApache-2.0Flagship

4,971 stars · Updated 3mo ago

unitaryfund

mitiq

Mitiq is an open source toolkit for implementing error mitigation techniques on most current intermediate-scale quantum computers.

PythonGPL-3.0Flagship

432 stars · Updated 3mo ago

QISKit

qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.

PythonApache-2.0FlagshipQtangl relevant

7,412 stars · Updated 3mo ago

jacobmarks

QTop

Topological Quantum Computing Simulator

PythonGPL-3.0

38 stars · Updated 6y ago

Microsoft

QuantumKatas

Tutorials and programming exercises for learning Q# and quantum computing

Jupyter NotebookMITFlagshipArchive

4,862 stars · Updated 2y ago

quantumlib

Stim

A fast stabilizer circuit library.

C++Apache-2.0Flagship

736 stars · Updated 3mo ago