Skip to content

Conversation

@dandragona-dev
Copy link

build_det_orders() is now called within compile_decoder_for_dem() to ensure the right configuration (for the DEM) is being used in each Sinter task. Previously, the TesseractConfig would always be using a single det_orders despite it depending upon the DEM for the task.

  • Feature request for TesseractSinterDecoder requires DEM to be configured correctly #129.
  • Refactored TesseractSinterDecoder constructor to have parameters which are then passed to a TessertConfig during compile_decoder_for_dem().
  • Added test to cover the crash referenced in issues/129.
  • Uses default values from TesseractConfig when applicable, otherwise improvises for num_det_orders, det_order_method, and seed.

@dandragona-dev dandragona-dev force-pushed the sinter-compat-integration branch 2 times, most recently from e8dc93e to a686e65 Compare October 7, 2025 15:15
@oscarhiggott oscarhiggott self-requested a review October 17, 2025 19:00
@oscarhiggott
Copy link
Contributor

Thank you, this looks excellent!

I wonder if it might worth including the "tesseract-long-beam" and "tesseract-short-beam" sinter decoders from my issue (#129 ) in the dictionary returned by tesseract_decoder.tesseract_sinter_compat.make_tesseract_sinter_decoders_dict?

@oscarhiggott
Copy link
Contributor

We could also add a small example of how to use Tesseract with sinter in the main Tesseract README.md at the root of the directory (as is done in the chromobius repo, for example). This would make it much easier for new users to get started.

@dandragona-dev
Copy link
Author

Sounds good, I'll add those suggestions in!

@dandragona-dev dandragona-dev force-pushed the sinter-compat-integration branch from a686e65 to 2168aa5 Compare October 23, 2025 00:29
README.md Outdated
```
## Using Tesseract with Sinter

Tesseract can be easily integrated into [Sinter](https://github.com/quantumlib/Sinter) workflows. Sinter is a tool for running and organizing quantum error correction simulations. The `tesseract_sinter_compat` module provides the necessary interface.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Tesseract can be easily integrated into [Sinter](https://github.com/quantumlib/Sinter) workflows. Sinter is a tool for running and organizing quantum error correction simulations. The `tesseract_sinter_compat` module provides the necessary interface.
Tesseract can be easily integrated into [sinter](https://github.com/quantumlib/Stim/tree/main/glue/sample) workflows. Sinter is a tool for running and organizing quantum error correction simulations. The `tesseract_sinter_compat` module provides the necessary interface.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks.

README.md Outdated
# Logical error rate: 0.0153
```

This example runs simulations for a repetition code with different distances [3, 5, 7] with different Tesseract default decoders. 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`.
Copy link
Contributor

@oscarhiggott oscarhiggott Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could add a command line example here too, e.g.:

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-long-beam \
    --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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG I'll add that in.

TesseractSinterDecoder visible from the root module.
@dandragona-dev dandragona-dev force-pushed the sinter-compat-integration branch from 85b3230 to a1a42f3 Compare October 24, 2025 02:42
README.md Outdated
tasks=tasks,
max_shots=10000,
decoders=decoders,
custom_decoders=tesseract_module.make_tesseract_sinter_decoders_dict(),
Copy link
Contributor

@oscarhiggott oscarhiggott Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
custom_decoders=tesseract_module.make_tesseract_sinter_decoders_dict(),
custom_decoders=make_tesseract_sinter_decoders_dict(),

README.md Outdated
decoders=decoders,
custom_decoders=tesseract_module.make_tesseract_sinter_decoders_dict(),
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be good to include one example of using the tesseract_decoder.TesseractSinterDecoder constructor with a full set of custom arguments. E.g. here's a full example (though maybe could be made more concise if combined with the example above):

import stim
import sinter
from tesseract_decoder import TesseractSinterDecoder
import tesseract_decoder

if __name__ == "__main__":
    custom_sinter_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,
    )

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

    results = sinter.collect(
        num_workers=2,
        tasks=tasks,
        max_shots=10_000,
        decoders=["custom-tesseract-decoder"],
        custom_decoders={"custom-tesseract-decoder": custom_sinter_decoder},
        print_progress=True,
    )

README.md Outdated
decoder=decoders[i],
json_metadata={"d": distance, "decoder": decoders[i]},
))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that from here on needs to be after an:

if __name__ == "__main__":

Might be worth making sure that the example code works right away after copy-pasting (e.g. without the above fix the sinter error can be a bit confusing...)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some tweaks and tested it in a standalone python file.

bit of a refactor to make the code more concise. Tested it in a
standalone python file as well.
README.md Outdated
Comment on lines 273 to 328
for result in results:
print(f"task metadata = {result.json_metadata}")
print(f" Shots run: {result.shots}")
print(f" Observed errors: {result.errors}")
print(f" Logical error rate: {result.errors / result.shots}")

# Should get something like:
# task metadata = {'d': 3, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 48
# Logical error rate: 0.0048
# task metadata = {'d': 3, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 64
# Logical error rate: 0.0064
# task metadata = {'d': 5, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 13
# Logical error rate: 0.0013
# task metadata = {'d': 5, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 12
# Logical error rate: 0.0012
# task metadata = {'d': 3, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 42
# Logical error rate: 0.0042
# task metadata = {'d': 3, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 39
# Logical error rate: 0.0039
# task metadata = {'d': 5, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 15
# Logical error rate: 0.0015
# task metadata = {'d': 5, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 13
# Logical error rate: 0.0013
# task metadata = {'d': 7, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 5
# Logical error rate: 0.0005
# task metadata = {'d': 7, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 1
# Logical error rate: 0.0001
# task metadata = {'d': 7, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 3
# Logical error rate: 0.0003
# task metadata = {'d': 7, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 3
# Logical error rate: 0.0003
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just a nit: maybe we could just print out the csv instead as that will take up less vertical space on the README:

Suggested change
for result in results:
print(f"task metadata = {result.json_metadata}")
print(f" Shots run: {result.shots}")
print(f" Observed errors: {result.errors}")
print(f" Logical error rate: {result.errors / result.shots}")
# Should get something like:
# task metadata = {'d': 3, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 48
# Logical error rate: 0.0048
# task metadata = {'d': 3, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 64
# Logical error rate: 0.0064
# task metadata = {'d': 5, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 13
# Logical error rate: 0.0013
# task metadata = {'d': 5, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 12
# Logical error rate: 0.0012
# task metadata = {'d': 3, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 42
# Logical error rate: 0.0042
# task metadata = {'d': 3, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 39
# Logical error rate: 0.0039
# task metadata = {'d': 5, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 15
# Logical error rate: 0.0015
# task metadata = {'d': 5, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 13
# Logical error rate: 0.0013
# task metadata = {'d': 7, 'decoder': 'tesseract'}
# Shots run: 10000
# Observed errors: 5
# Logical error rate: 0.0005
# task metadata = {'d': 7, 'decoder': 'tesseract-long-beam'}
# Shots run: 10000
# Observed errors: 1
# Logical error rate: 0.0001
# task metadata = {'d': 7, 'decoder': 'tesseract-short-beam'}
# Shots run: 10000
# Observed errors: 3
# Logical error rate: 0.0003
# task metadata = {'d': 7, 'decoder': 'custom-tesseract-decoder'}
# Shots run: 10000
# Observed errors: 3
# Logical error rate: 0.0003
```
# 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""}",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants