Skip to main content

A search-based decoder for quantum error correction (QEC).

Project description

Tesseract Decoder

A Search-Based Decoder for Quantum Error Correction.

Licensed under the Apache 2.0 open-source license C++

InstallationUsagePython InterfacePaperHelpCitationContact

Tesseract is a Most Likely Error decoder designed for Low Density Parity Check (LDPC) quantum error-correcting codes. It applies pruning heuristics and manifold orientation techniques during a search over the error subsets to identify the most likely error configuration consistent with the observed syndrome. Tesseract achieves significant speed improvements over traditional integer programming-based decoders while maintaining comparable accuracy at moderate physical error rates.

We tested the Tesseract decoder for:

  • Surface codes
  • Color codes
  • Bivariate-bicycle codes
  • Transversal CNOT protocols for surface codes

Features

  • A* search: deploys A* search while running a Dijkstra algorithm with early stop for high performance.
  • Stim and DEM Support: processes Stim circuit files and Detector Error Model (DEM) files with arbitrary error models. Zero-probability error instructions are automatically removed when a DEM is loaded.
  • Parallel Decoding: uses multithreading to accelerate the decoding process, making it suitable for large-scale simulations.
  • Efficient Beam Search: implements a beam search algorithm to minimize decoding cost and enhance efficiency. Sampling and Shot Range Processing: supports sampling shots from circuits. When a detection error model is provided without an accompanying circuit, Tesseract requires detection events from files using --in. The decoder can also process specific shot ranges for flexible experiment setups.
  • Detailed Statistics: provides comprehensive statistics output, including shot counts, error counts, and processing times.
  • Heuristics: includes flexible heuristic options: --beam, --det-penalty, --beam-climbing, --no-revisit-dets, --at-most-two-errors-per-detector, and --pqlimit to improve performance while maintaining a low logical error rate. To learn more about these options, use ./bazel-bin/src/tesseract --help
  • Visualization tool: open the viz directory in your browser to view decoding results. See viz/README.md for instructions on generating the visualization JSON.

Installation

Tesseract relies on the following external libraries:

  • argparse: For command-line argument parsing.
  • nlohmann/json: For JSON handling (used for statistics output).
  • Stim: For quantum circuit simulation and error model handling.

Build Instructions

Tesseract uses Bazel as its build system. To build the decoder:

bazel build src:all

Running Tests

Unit tests are executed with Bazel. Run the quick test suite using:

bazel test //src:all

By default the tests use reduced parameters and finish in under 30 seconds. To run a more exhaustive suite with additional shots and larger distances, set:

TESSERACT_LONG_TESTS=1 bazel test //src:all

Usage

The file tesseract_main.cc provides the main entry point for Tesseract Decoder. It can decode error events from Stim circuits, DEM files, and pre-existing detection event files.

Basic Usage:

./tesseract --circuit CIRCUIT_FILE.stim --sample-num-shots N --print-stats

To decode pre-generated detection events, provide the input file using --in SHOTS_FILE --in-format FORMAT.

Example with Advanced Options:

./tesseract \
        --pqlimit 1000000 \
        --at-most-two-errors-per-detector \
        --det-order-seed 232852747 \
        --circuit circuit_file.stim \
        --sample-seed 232856747 \
        --sample-num-shots 10000 \
        --threads 32 \
        --print-stats \
        --beam 23 \
        --num-det-orders 1 \
        --shot-range-begin 582 \
        --shot-range-end 583

Example Usage

Sampling Shots from a Circuit:

./tesseract --circuit surface_code.stim --sample-num-shots 1000 --out predictions.01 --out-format 01

Using a Detection Event File:

./tesseract --in events.01 --in-format 01 --dem surface_code.dem --out decoded.txt

Using a Detection Event File and Observable Flips:

./tesseract --in events.01 --in-format 01 --obs_in obs.01 --obs-in-format 01 --dem surface_code.dem --out decoded.txt

Tesseract supports reading and writing from all of Stim's standard output formats.

Performance Optimization

Here are some tips for improving performance:

  • Parallelism over shots: increase --threads to leverage multicore processors for faster decoding.
  • Beam Search: use --beam to control the trade-off between accuracy and speed. Smaller beam sizes result in faster decoding but potentially lower accuracy.
  • Beam Climbing: enable --beam-climbing for enhanced cost-based decoding.
  • At most two errors per detector: enable --at-most-two-errors-per-detector to improve performance.
  • Priority Queue limit: use --pqlimit to limit the size of the priority queue.

Output Formats

  • Observable flips output: predictions of logical errors.
  • DEM usage frequency output: if --dem-out is specified, outputs estimated error frequencies.
  • Statistics output: includes number of shots, errors, low confidence shots, and processing time.

Python Interface

Full Python wrapper documentation

This repository contains the C++ implementation of the Tesseract quantum error correction decoder, along with a Python wrapper. The Python wrapper/interface exposes the decoding algorithms and helper utilities, allowing Python users to leverage this high-performance decoding algorithm.

For installation:

pip install tesseract-decoder

The following example demonstrates how to create and use the Tesseract decoder using the Python interface.

from tesseract_decoder import tesseract
import stim
import numpy as np


# 1. Define a detector error model (DEM)
dem = stim.DetectorErrorModel("""
    error(0.1) D0 D1 L0
    error(0.2) D1 D2 L1
    detector(0, 0, 0) D0
    detector(1, 0, 0) D1
    detector(2, 0, 0) D2
""")

# 2. Create the decoder configuration
config = tesseract.TesseractConfig(dem=dem, det_beam=50)

# 3. Create a decoder instance
decoder = config.compile_decoder()

# 4. Simulate detector outcomes
syndrome = np.array([0, 1, 1], dtype=bool)

# 5a. Decode to observables
flipped_observables = decoder.decode(syndrome)
print(f"Flipped observables: {flipped_observables}")

# 5b. Alternatively, decode to errors
decoder.decode_to_errors(syndrome)
predicted_errors = decoder.predicted_errors_buffer
# Indices of predicted errors
print(f"Predicted errors indices: {predicted_errors}")
# Print properties of predicted errors
for i in predicted_errors:
    print(f"    {i}: {decoder.errors[i]}")

Using Tesseract with Sinter

Tesseract can be easily integrated into Sinter workflows. Sinter is a tool for running and organizing quantum error correction simulations.

Here's an example of how to use Tesseract as a decoder for multiple Sinter tasks:

import stim
import sinter
from tesseract_decoder import make_tesseract_sinter_decoders_dict, TesseractSinterDecoder
import tesseract_decoder

if __name__ == "__main__":  
    # Define a list of Sinter task(s) with different circuits/decoders.
    tasks = []
    # Depolarizing noise probability.
    p = 0.005
    # These are the sensible defaults given by make_tesseract_sinter_decoders_dict().
    # Note that `tesseract-short-beam` and `tesseract-long-beam` are the two sets of parameters used in the [Tesseract paper](https://arxiv.org/pdf/2503.10988).
    decoders = ['tesseract', 'tesseract-long-beam', 'tesseract-short-beam']
    decoder_dict = make_tesseract_sinter_decoders_dict()
    # You can also make your own custom Tesseract Decoder to-be-used with Sinter.
    decoders.append('custom-tesseract-decoder')
    decoder_dict['custom-tesseract-decoder'] = TesseractSinterDecoder(
        det_beam=10,
        beam_climbing=True,
        no_revisit_dets=True,
        merge_errors=True,
        pqlimit=1_000,
        num_det_orders=5,
        det_order_method=tesseract_decoder.utils.DetOrder.DetIndex,
        seed=2384753,
    )

    for distance in [3, 5, 7]:
        for decoder in decoders:
            circuit = stim.Circuit.generated(
                "surface_code:rotated_memory_x",
                distance=distance,
                rounds=3,
                after_clifford_depolarization=p
            )
            tasks.append(sinter.Task(
                circuit=circuit,
                decoder=decoder,
                json_metadata={"d": distance, "decoder": decoder},
            ))

    # Collect decoding outcomes per task from Sinter.
    results = sinter.collect(
        num_workers=8,
        tasks=tasks,
        max_shots=10_000,
        decoders=decoders,
        custom_decoders=decoder_dict,
        print_progress=True,
    )

    # Print samples as CSV data.
    print(sinter.CSV_HEADER)
    for sample in results:
        print(sample.to_csv_line())

should get something like:

    shots,    errors,  discards, seconds,decoder,strong_id,json_metadata,custom_counts  
    10000,        42,         0,   0.071,tesseract,1b3fce6286e438f38c00c8f6a5005947373515ab08e6446a7dd9ecdbef12d4cc,"{""d"":3,""decoder"":""tesseract""}",  
    10000,        49,         0,   0.546,custom-tesseract-decoder,7b082bec7541be858e239d7828a432e329cd448356bbdf051b8b8aa76c86625a,"{""d"":3,""decoder"":""custom-tesseract-decoder""}", 
    10000,        13,         0,    7.64,tesseract-long-beam,217a3542f56319924576658a6da7081ea2833f5167cf6d77fbc7071548e386a9,"{""d"":5,""decoder"":""tesseract-long-beam""}",  
    10000,        42,         0,   0.743,tesseract-short-beam,cf4a4b0ce0e4c7beec1171f58eddffe403ed7359db5016fca2e16174ea577057,"{""d"":3,""decoder"":""tesseract-short-beam""}",  
    10000,        34,         0,   0.924,tesseract-long-beam,8cfa0f2e4061629e13bc98fe213285dc00eb90f21bba36e08c76bcdf213a1c09,"{""d"":3,""decoder"":""tesseract-long-beam""}",  
    10000,        10,         0,   0.439,tesseract,8274ea5ffec15d6e71faed5ee1057cdd7e497cbaee4c6109784f8a74669d7f96,"{""d"":5,""decoder"":""tesseract""}",  
    10000,         8,         0,    3.93,custom-tesseract-decoder,8e4f5ab5dde00fec74127eea39ea52d5a98ae6ccfc277b5d9be450f78acc1c45,"{""d"":5,""decoder"":""custom-tesseract-decoder""}",  
    10000,        10,         0,    5.74,tesseract-short-beam,bf696535d62a25720c3a0c624ec5624002efe3f6cb0468963eee702efb48abc1,"{""d"":5,""decoder"":""tesseract-short-beam""}",  
    10000,         5,         0,    1.27,tesseract,3f94c61f1503844df6cf0d200b74ac01bfbc5e29e70cedbfc2faad67047e7887,"{""d"":7,""decoder"":""tesseract""}",  
    10000,         4,         0,    25.0,tesseract-long-beam,4d510f0acf511e24a833a93c956b683346696d8086866fadc73063fb09014c23,"{""d"":7,""decoder"":""tesseract-long-beam""}",  
    10000,         1,         0,    18.6,tesseract-short-beam,75782ce4593022fcedad4c73104711f05c9c635db92869531f78da336945b121,"{""d"":7,""decoder"":""tesseract-short-beam""}",  
    10000,         4,         0,    11.6,custom-tesseract-decoder,48f256a28fff47c58af7bffdf98fdee1d41a721751ee965c5d3c5712ac795dc8,"{""d"":7,""decoder"":""custom-tesseract-decoder""}",  

This example runs simulations for a repetition code with different distances [3, 5, 7] with different Tesseract default decoders.

Sinter can also be used at the command line. Here is an example of this using Tesseract:

sinter collect \
    --circuits "example_circuit.stim" \
    --decoders tesseract \
    --custom_decoders_module_function "tesseract_decoder:make_tesseract_sinter_decoders_dict" \
    --max_shots 100_000 \
    --max_errors 100
    --processes auto \
    --save_resume_filepath "stats.csv" \

Sinter efficiently manages the execution of these tasks, and Tesseract is used for decoding. For more usage examples, see the tests in src/py/tesseract_sinter_compat_test.py.

Good Starting Points for Tesseract Configurations:

The Tesseract paper recommends two setup for starting your exploration with tesseract:

(1) Long-beam setup:

tesseract_config = tesseract.TesseractConfig(
    dem=dem,
    pqlimit=1_000_000,
    det_beam=20,
    beam_climbing=True,
    num_det_orders=21,
    det_order=tesseract_decoder.utils.DetOrder.DetIndex,
    no_revisit_dets=True,
)

(2) Short-beam setup:

tesseract_config = tesseract.TesseractConfig(
    dem=dem,
    pqlimit=200_000,
    det_beam=15,
    beam_climbing=True,
    num_det_orders=16,
    det_order=tesseract_decoder.utils.DetOrder.DetIndex,
    no_revisit_dets=True,
)

For det_order, you can use two other options of DetIndex and DetCoordinate as well. These values balance decoding speed and accuracy across the benchmarks reported in the paper and can be adjusted for specific use cases.

Help

We are committed to providing a friendly, safe, and welcoming environment for all. Please read and respect our Code of Conduct.

Citation

When publishing articles or otherwise writing about Tesseract Decoder, please cite the following:

@misc{beni2025tesseractdecoder,
    title={Tesseract: A Search-Based Decoder for Quantum Error Correction},
    author = {Aghababaie Beni, Laleh and Higgott, Oscar and Shutty, Noah},
    year={2025},
    eprint={2503.10988},
    archivePrefix={arXiv},
    primaryClass={quant-ph},
    doi = {10.48550/arXiv.2503.10988},
    url={https://arxiv.org/abs/2503.10988},
}

Contact

For any questions or concerns not addressed here, please email tesseract-decoder-dev@google.com.

Disclaimer

Tesseract Decoder is not an officially supported Google product. This project is not eligible for the Google Open Source Software Vulnerability Rewards Program.

Copyright 2025 Google LLC.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded Python 3.13manylinux: glibc 2.39+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl (3.6 MB view details)

Uploaded Python 3.13manylinux: glibc 2.35+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py313-none-macosx_11_0_arm64.whl (3.2 MB view details)

Uploaded Python 3.13macOS 11.0+ ARM64

tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded Python 3.12manylinux: glibc 2.39+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl (3.6 MB view details)

Uploaded Python 3.12manylinux: glibc 2.35+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py312-none-macosx_11_0_arm64.whl (3.2 MB view details)

Uploaded Python 3.12macOS 11.0+ ARM64

tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded Python 3.11manylinux: glibc 2.39+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl (3.6 MB view details)

Uploaded Python 3.11manylinux: glibc 2.35+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py311-none-macosx_11_0_arm64.whl (3.2 MB view details)

Uploaded Python 3.11macOS 11.0+ ARM64

tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded Python 3.10manylinux: glibc 2.39+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl (3.6 MB view details)

Uploaded Python 3.10manylinux: glibc 2.35+ x86-64

tesseract_decoder-0.1.1.dev20251110191347-py310-none-macosx_11_0_arm64.whl (3.2 MB view details)

Uploaded Python 3.10macOS 11.0+ ARM64

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f2ec22145f1d021fe86e8a66d047ae014019aee4a87e03f9e9f2105d44ba921a
MD5 e8c735ca1f3a23fc52524cf1e1f49a1a
BLAKE2b-256 d7e26f729119bc24d94eaf7fc7c235b26382b99b5170d9125a9b006fb2a49a01

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py313-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 aa102c4c716f0729710e5db09607cfb118cd39316efeb1f64f32086b9324dd3b
MD5 34a5e7802947bb43a744f526f3635fbd
BLAKE2b-256 541f5b0813f080c3db5844eb95d6d3c124226e921d4642f1f026a902e62a024f

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py313-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py313-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1809a78ea16d42b69bcc13d7bc795a0616edb5295bc7dba2ab85ae1681cda9b3
MD5 beb3ae87c6fc89dd2fed11dde63929e5
BLAKE2b-256 a5bfab0154d80577c0612ce2b49b2321fdc8f7db819fd1efb5d517c86f45e864

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c0b3c526e6ad47270cc77c3967abc59cb0ccb2dcf78d31496f813689ed026e56
MD5 fde80fd695152c20d785d7710e6d6608
BLAKE2b-256 70f688013265f27df39ce871f5f425d8364f47c499b6878bfe23369ed2316457

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py312-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4aef4e13f7b9263f89fcb453739e6286d458bc9886e00799b37500d4d2db1642
MD5 0293f9657ace86e596cba12033faca74
BLAKE2b-256 04da90d8d030a33ed2fbe7cb492ba6b0c936f70792cf7bc3be99729e949871c2

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py312-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py312-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4355c29458089bd0a451040f548eb9e6587ba42067e71e950d52fb1fd9dda5a9
MD5 a613d81a4e7f300b5b81dd671d15bc4b
BLAKE2b-256 1e90dda794f1fad8fced41e188b6c8cb3f5a7a72c1cdc9bd3eff67a4536e5add

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 de0404732ce9e2696cac58d80432b0a7646ee39f01604d504f2a80013ef0f86a
MD5 8b75dc48c7e115c67bf031626f1130d2
BLAKE2b-256 d0a34e8fa0a9494f61c9b99bcd1dfd62a06ee012bb7a1680cfe7d4febaad552d

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py311-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ee2a165c76ca546e389930e8a252d39e87ddb1ff6bfd29f38333bcc279999403
MD5 608f54be2e6a31bdaaf618ea302945c7
BLAKE2b-256 8c221908dfe7e43d473d3981c24e7aaf0ae86eb4e47c22e186b27fddd699f462

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py311-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py311-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 20b367cd7d0d18e6396bc2606829260f0f50ea7e066820ef88a909c6cad87914
MD5 b9bbfb4d57bd77c3bd7dd3e801efdc6e
BLAKE2b-256 ad24af36c5ffecabdfe5a26c5a30ffef3caec950c59cd1d61c7006d32b82e962

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_39_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6216eb538fac5607a9eaabc7b93e97ed406df2b9fab3bfec8fa2f8dea9921d40
MD5 33750eda1319cc793d9d277b3094e6d7
BLAKE2b-256 6c97aa91e2c7ff3c52115ad81c1826a33309fa770c42a85a5b54332a58df896a

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py310-none-manylinux_2_35_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c37bf980dffc0635804b0550da02f2e2b95b31bd5eff2bcc50aec05f5a4cb0e7
MD5 df1a3b01623b37415e6a735ff42f82c1
BLAKE2b-256 3bc1b6b677c980785e5b364c7f6f86ff0a4a1d23c524c3d6e1b206b8ca4a7afe

See more details on using hashes here.

File details

Details for the file tesseract_decoder-0.1.1.dev20251110191347-py310-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tesseract_decoder-0.1.1.dev20251110191347-py310-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 41b6ac10630dbee5aad776b46c429a1cad970e98abf626c367a03c738c78c531
MD5 b8783a332a306a300d92ec5a70e43f5e
BLAKE2b-256 9f11ce0fee878888f9915ced1f9be4f0ee784ec4ce4795ac6495a058ca1c1719

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page