Open-source SDK for neutral atom quantum computing

← All posts

Tsim: Faster near-Clifford simulation with active statevectors and a new ZX engine

We are releasing Tsim 1.0.0, our first major version release. Building on key advances by Clifft and SymFT,[1,2] we have added a new active statevector backend, which replaces stabilizer-rank decomposition as the default for sampling. Together with a rewrite of the ZX engine in Rust, this allows Tsim to scale to much larger near-Clifford circuits and significantly reduces compilation times.

For example, Tsim samples the 463-qubit end-to-end magic-state cultivation circuit of Gidney et al.[3] five times faster than Stim[4] samples its Clifford version, in which every T gate is replaced by an S gate, a much easier problem.

Cultivation
Measure
Postselection

Cultivation d=5, end-to-end463 qubits · 53 T gates · 2,744 detectors, 107 postselected (injection and cultivation)

Tsim 1.0.0
Clifft 0.12.0
SymFT 0.1.1
Stim 1.16.0 (T→S, Clifford only)

Run details
Machine
One AMD Ryzen 9 9900X (12 cores, 24 threads, 64 GB) running Linux; every measurement runs in a fresh process, pinned to a single core with taskset, with a budget of 1 thread.
Stim
Stim cannot simulate T gates, so it samples the Clifford version of each circuit: T made S, T† made S†, with its frame simulator. Its line is dashed: it shows what a Clifford simulator costs on a circuit of the same size, not a simulation of the measured circuit. Stim cannot postselect either, so like SymFT where it cannot, its lane shows its rate without postselection when postselection is on.
Sampling
Attempted shots per second, median of 3 timed repetitions of at least 5 s each, after compilation and one untimed warm-up call. Shots rejected by postselection count as attempted, so a rate with postselection on is a cost per attempt, not per accepted shot. The rate covers the simulator's own call, which returns its shot data; Tsim and Stim return bit-packed detector rows, Clifft and SymFT survivor counts. Tsim samples with trajectory sharing on; Clifft with the batch size it calibrates during the warmup call (batch_size="tune").
Compilation
Wall time from circuit text to a sampler ready to sample, median over 3 fresh processes, with imports done before the clock starts, shown with postselection off. Stim's includes the T-to-S text substitution. Clifft runs its default optimization passes plus its opt-inActiveWidthSchedulePass.
Postselection
With postselection on, every detector is postselected, except on Cultivation d=5, end-to-end, where only the injection and cultivation detectors are (the convention of Gidney et al.). SymFT can only postselect on all detectors, so it does not support this setting; there its lane shows its rate without postselection. Compare draws each lane from postselection off (open mark) to on (filled mark); Stim, and SymFT where it cannot postselect, keep a single mark at their rate without postselection.
K
The largest number of qubits held in a dense statevector at once, as each simulator reports it. Sampling cost grows as 2K.
Versions
Tsim 1.0.0: bloqade-tsim 0.1.5 @ git 5af2731, numpy 2.4.4, numba 0.65.0, stim 1.15.0 · Clifft 0.12.0: clifft 0.12.0, numpy 2.5.4 · SymFT 0.1.1: symft 0.1.1, numpy 2.5.4 · Stim 1.16.0 (T→S, Clifford only): stim 1.16.0, numpy 2.4.4, numba 0.65.0
Circuits
Gidney et al. cultivation circuits, as used by the Clifft paper; SymFT benchmark suite.

From ZX diagrams to small statevectors

Tsim represents circuits as ZX diagrams, where Pauli noise appears as parameterized vertices. It then simplifies the diagram using the rules of the ZX calculus. This often significantly reduces the number of non-Clifford gates. Importantly, the ZX diagram often splits into two parts: a small connected component that represents the logical circuit (which requires far fewer qubits than the physical circuit) and a large number of individual detector components that represent the stabilizer measurements. The reduction is performed once and reused across shots, as described in the original Tsim paper.[5]

Previously, the remaining quantum component was decomposed into a sum of Clifford diagrams using stabilizer-rank decomposition.[6] In practice, this produces exponentially many terms as the non-Clifford gate count increases, making both compilation and sampling expensive. With the active statevector backend, Tsim instead applies key insights from Clifft and SymFT.[1,2] The small ZX diagram is converted back into a quantum circuit that represents a Pauli-based computation (PBC): all of its instructions are either Pauli-product measurements or Pauli-product rotations, where the signs of the rotation angles depend on the noise configuration of each shot.

1 / 8Stim circuit

The input is the Steane-encoded 5-to-1 magic-state distillation from the benchmarks above: five noisy magic states, each encoded in a 7-qubit code, distilled with transversal gates and measured.

  • 35 qubits
  • 10 non-Clifford gates
  • 15 detectors
  • 5 observables
R 6 13 20 27 34
R_X(-0.3040867239846964) 6 13 20 27 34
T_DAG 6 13 20 27 34
DEPOLARIZE1(0.05) 6 13 20 27 34
R 0 7 14 21 28 1 8 15 22 29 2 9 16 23 30 3 10 17 24 31 4 11 18 25 32 5 12 19 26 33
TICK
SQRT_Y_DAG 0 7 14 21 28 1 8 15 22 29 2 9 16 23 30 3 10 17 24 31 4 11 18 25 32 5 12 19 26 33
TICK
CZ 1 2 8 9 15 16 22 23 29 30 3 4 10 11 17 18 24 25 31 32 5 6 12 13 19 20 26 27 33 34
TICK
SQRT_Y 6 13 20 27 34
TICK
CZ 0 3 7 10 14 17 21 24 28 31 2 5 9 12 16 19 23 26 30 33 4 6 11 13 18 20 25 27 32 34
TICK
SQRT_Y 2 9 16 23 30 3 10 17 24 31 4 11 18 25 32 5 12 19 26 33 6 13 20 27 34
TICK
CZ 0 1 7 8 14 15 21 22 28 29 2 3 9 10 16 17 23 24 30 31 4 5 11 12 18 19 25 26 32 33
TICK
SQRT_Y 1 8 15 22 29 2 9 16 23 30 4 11 18 25 32
TICK
X 3 10 17 24 31
Z 5 12 19 26 33 1 8 15 22 29
TICK
SQRT_X 0 1 2 3 4 5 6 7 8 9 10 11 12 13 28 29 30 31 32 33 34
DEPOLARIZE1(0.01) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 28 29 30 31 32 33 34
CZ 0 7 1 8 2 9 3 10 4 11 5 12 6 13 14 21 15 22 16 23 17 24 18 25 19 26 20 27
DEPOLARIZE2(0.01) 0 7 1 8 2 9 3 10 4 11 5 12 6 13 14 21 15 22 16 23 17 24 18 25 19 26 20 27
SQRT_Y 0 1 2 3 4 5 6 21 22 23 24 25 26 27
DEPOLARIZE1(0.01) 0 1 2 3 4 5 6 21 22 23 24 25 26 27
CZ 0 14 1 15 2 16 3 17 4 18 5 19 6 20 21 28 22 29 23 30 24 31 25 32 26 33 27 34
DEPOLARIZE2(0.01) 0 14 1 15 2 16 3 17 4 18 5 19 6 20 21 28 22 29 23 30 24 31 25 32 26 33 27 34
TICK
SQRT_X_DAG 0 1 2 3 4 5 6
DEPOLARIZE1(0.01) 0 1 2 3 4 5 6
CZ 0 28 1 29 2 30 3 31 4 32 5 33 6 34
DEPOLARIZE2(0.01) 0 28 1 29 2 30 3 31 4 32 5 33 6 34
TICK
CZ 7 21 8 22 9 23 10 24 11 25 12 26 13 27
DEPOLARIZE2(0.01) 7 21 8 22 9 23 10 24 11 25 12 26 13 27
TICK
SQRT_X_DAG 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
DEPOLARIZE1(0.01) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
M 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
DETECTOR rec[-35] rec[-34] rec[-33] rec[-32]
DETECTOR rec[-34] rec[-33] rec[-31] rec[-30]
DETECTOR rec[-33] rec[-32] rec[-31] rec[-29]
DETECTOR rec[-28] rec[-27] rec[-26] rec[-25]
DETECTOR rec[-27] rec[-26] rec[-24] rec[-23]
DETECTOR rec[-26] rec[-25] rec[-24] rec[-22]
DETECTOR rec[-21] rec[-20] rec[-19] rec[-18]
DETECTOR rec[-20] rec[-19] rec[-17] rec[-16]
DETECTOR rec[-19] rec[-18] rec[-17] rec[-15]
DETECTOR rec[-14] rec[-13] rec[-12] rec[-11]
DETECTOR rec[-13] rec[-12] rec[-10] rec[-9]
DETECTOR rec[-12] rec[-11] rec[-10] rec[-8]
DETECTOR rec[-7] rec[-6] rec[-5] rec[-4]
DETECTOR rec[-6] rec[-5] rec[-3] rec[-2]
DETECTOR rec[-5] rec[-4] rec[-3] rec[-1]
OBSERVABLE_INCLUDE(0) rec[-35] rec[-34] rec[-30]
OBSERVABLE_INCLUDE(1) rec[-28] rec[-27] rec[-23]
OBSERVABLE_INCLUDE(2) rec[-21] rec[-20] rec[-16]
OBSERVABLE_INCLUDE(3) rec[-14] rec[-13] rec[-9]
OBSERVABLE_INCLUDE(4) rec[-7] rec[-6] rec[-2]

Importantly, the final PBC often requires far fewer qubits than the original circuit, so it can be simulated with a statevector simulator. As in Clifft,[1] we call the number of qubits of the PBC its active width.

Compressing Circuits

The active width of common QEC circuits can be surprisingly small. For end-to-end magic-state cultivation, for example, the 463-qubit circuit is compressed into a statevector with an active width of 6. Tsim’s ZX reduction is particularly effective at reaching a low active width. In the d=7 cultivation workload from SymFT [2], Tsim reaches a peak width of 8, compared with 19 for Clifft and SymFT, as shown in the table below. This means that a statevector with 256 coefficients is enough to represent the circuit instead of 524,288 - a reduction by a factor of 2,048.

K per circuit for Tsim 1.0.0, Clifft 0.12.0, SymFT 0.1.1; lowest per row marked
Active width K
CircuitQubitsTsim 1.0.0Clifft 0.12.0SymFT 0.1.1
Distillation d=5853 (lowest)3 (lowest)5
Cultivation d=5426 (lowest)1010
Cultivation d=5, end-to-end4636 (lowest)1010
Cultivation d=7 (SymFT)808 (lowest)1919
Coherent surface d=3, r=1260 (lowest)0 (lowest)4
Coherent surface d=3, r=3264 (lowest)4 (lowest)7
Coherent surface d=5, r=1640 (lowest)0 (lowest)12
Coherent surface d=5, r=56411 (lowest)1322

Benchmarks

Tsim’s ZX engine has been rewritten in Rust, which makes compilation significantly faster. Additionally, Tsim can speed up sampling by sharing statevectors between shots whose noise configurations have the same effect. In our benchmarks, this trajectory sharing approach makes sampling more than an order of magnitude faster on small circuits. Below, we compare Tsim 1.0.0 with Clifft 0.12.0 and SymFT 0.1.1 on 10 circuits from the Clifft and SymFT benchmark suites.

Measure
Threads
Postselection
Trajectory sharing (Tsim)
View
Surface code d=7, r=7118 qubits · Clifford
Distillation d=585 qubits · 5 T gates · 5 rotations
Cultivation d=542 qubits · 91 T gates
Cultivation d=5, end-to-end463 qubits · 53 T gates
Cultivation d=7 (SymFT)80 qubits · 127 T gates

Run details
Machine
One AMD Ryzen 9 9900X (12 cores, 24 threads, 64 GB) running Linux; every measurement runs in a fresh process.
Sampling
Attempted shots per second, median of 3 timed repetitions of at least 5 s each, after compilation and one untimed warm-up call. Shots rejected by postselection count as attempted, so a rate with postselection on is a cost per attempt, not per accepted shot. Clifft samples with the batch size it calibrates during the warmup call (batch_size="tune"), as its own benchmark suite does.
Compilation
Wall time from circuit text to a sampler ready to sample, median over 3 fresh processes, with imports done before the clock starts, shown at 1 thread with postselection off. First-call JIT compilation inside sampling is not included. Clifft runs its default optimization passes plus its opt-in ActiveWidthSchedulePass (a search over operation orderings) with default settings, on every circuit, for both compilation and sampling.
Threads
Every engine gets the same budget, 1 or 10 threads: the harness caps the OpenMP and numba thread pools and passes the budget to engines that take a threads argument.
Postselection
With postselection on, every detector is postselected, except on Cultivation d=5, end-to-end, where only the injection and cultivation detectors are (the convention of Gidney et al.). SymFT can only postselect on all detectors, so it has no number there. Circuits without detectors show their postselection-off measurement in both views.
Output
Output contracts differ: Tsim returns full detector and observable arrays, bit-packed (8 detectors per byte) and counted inside the timed region; Clifft and SymFT return survivor counts.
Views
One row per circuit, one lane per simulator, on a shared log axis. Relative view puts the slowest engine in each row at 1×. Compare draws each lane from the baseline setting (open mark: 1 thread, postselection off, sharing off) to the target (filled mark) and labels it with how many times faster the target is. Hover or focus a row for details, or download the CSV.
K
The largest number of qubits held in a dense statevector at once, as each simulator reports it (Tsim: component width; Clifft: peak_active_width; SymFT: max_active_qubits). Sampling cost grows as 2K.
Versions
Tsim 1.0.0: bloqade-tsim 0.1.5 @ git 73656a2, numpy 2.4.4, numba 0.65.0, stim 1.15.0 · Clifft 0.12.0: clifft 0.12.0, numpy 2.5.4 · SymFT 0.1.1: symft 0.1.1, numpy 2.5.4
Circuits
Each circuit name links to its source on GitHub, at the commit measured. Sources: Clifft paper benchmarks; Gidney et al. cultivation circuits, as used by the Clifft paper; SymFT benchmark suite.

Simulators as compilers

We are excited about the recent advances in universal near-Clifford simulation. In particular, we want to emphasize the close connection between simulators and compilers, a point first made by Clifft: compiler passes transform an intermediate representation of the quantum program before the simulator executes it. By reducing the active width, such passes can bring circuits within reach that would otherwise be too expensive to simulate.

The clifft-bench project tracks these improvements across releases. For example, Clifft 0.10’s compiler improvements reduced the active width of the coherent surface-code d=5, r=5 benchmark from 24 to 13. This illustrates how much can be gained by simplifying the program before optimizing its numerical execution. We are working to contribute Tsim’s ZX-based compiler pass to Clifft, to bring similar speedups to other widely used simulators as well.

Summary

Tsim 1.0.0 introduces some key advances:

  • Active statevector backend. Building on Clifft and SymFT, Tsim compresses a circuit into an equivalent circuit on far fewer qubits. It replaces stabilizer-rank decomposition as the default for sampling.
  • ZX simplification first. Tsim’s ZX reduction reaches the lowest active width of the three simulators on every circuit in our benchmark, which translates directly into faster sampling.
  • Trajectory sharing. Shots whose noise affects the circuit in the same way share one statevector, which reduces both the work per shot and the memory needed.
  • A ZX engine rewritten in Rust, which makes compilation significantly faster.

Tsim now achieves state-of-the-art performance for near-Clifford circuits with Pauli noise. More accurate noise models include atom loss and leakage, which Tsim currently does not support. QEC programs beyond the gadget level also require real-time decoding. These call for different simulation strategies, such as those in PPVM, our first step toward a quantum digital twin. To build circuits with feedforward and real-time decoding, try QEC Studio.

Acknowledgements

We thank Bradley A. Chase for insightful discussions. We also thank Bradley A. Chase and Farrokh Labib for building and open-sourcing Clifft, and Wang Fang, Huazhe Lou and Riling Li for building and open-sourcing SymFT. Their work provided the foundation for Tsim’s new backend.

Cite this post

@misc{haenel2026tsim,
  author         = {Rafael Haenel and Xiu-Zhe Luo},
  title          = {Tsim: Faster near-Clifford simulation with active statevectors and a new {ZX} engine},
  howpublished   = {Bloqade blog, QuEra Computing},
  year           = {2026},
  month          = {nov},
  url            = {https://bloqade.quera.com/blog/introducing-tsim-1-0-0/},
}

References

  1. B. A. Chase and F. Labib, “Clifft: Fast Exact Simulation of Near-Clifford Quantum Circuits,” arXiv:2604.27058 (2026). ↩︎ ↩︎2 ↩︎3
  2. W. Fang, H. Lou, and R. Li, “SymFT: Universal Fault-Tolerant Quantum Circuit Simulation via Symbolic Clifford–Pauli Frames and Stabilizer Coordinates,” arXiv:2607.28600 (2026). ↩︎ ↩︎2 ↩︎3
  3. C. Gidney, N. Shutty, and C. Jones, “Magic State Cultivation: Growing T States as Cheap as CNOT Gates,” arXiv:2409.17595 (2024). ↩︎
  4. C. Gidney, “Stim: A Fast Stabilizer Circuit Simulator,” Quantum 5, 497 (2021). ↩︎
  5. R. Haenel, X.-Z. Luo, and C. Zhao, “Tsim: Fast Universal Simulator for Quantum Error Correction,” arXiv:2604.01059 (2026). ↩︎
  6. S. Bravyi et al., “Simulation of Quantum Circuits by Low-Rank Stabilizer Decompositions,” Quantum 3, 181 (2019). ↩︎