Skip to content

✨ Add error correction module with Shor and Steane logical circuit transpilers - #930

Open
Felix-Gundlach wants to merge 293 commits into
munich-quantum-toolkit:mainfrom
emilkanic0909:feature/ErrorCorrection_MergePrep
Open

Felix-Gundlach wants to merge 293 commits into
munich-quantum-toolkit:mainfrom
emilkanic0909:feature/ErrorCorrection_MergePrep

Conversation

@Felix-Gundlach

@Felix-Gundlach Felix-Gundlach commented Jun 13, 2026 •

Copy link
Copy Markdown

Description

Adds an error correction module that encodes benchmark circuits into logical circuits using the 7-qubit Steane code or the 9-qubit Shor code. Encoding is exposed via a new encoding parameter on get_benchmark() and get_benchmark_alg(), accepting "", "steane", or "shor":

qc = get_benchmark(benchmark="ghz", level=BenchmarkLevel.ALG, circuit_size=3, encoding="steane")

error_correction/ec_transpiler.py holds the code-agnostic ECTranspiler base class. It decomposes the circuit into the code's basis, replaces every logical qubit with a data register plus syndrome ancillas, substitutes each gate by its logical equivalent, and appends a syndrome extraction and correction cycle after every logical operation. SteaneTranspiler and ShorTranspiler only declare their code parameters and supply the encoding, decoding, and syndrome circuits.

Since MQT Bench targets circuit structure rather than exact behaviour, gates without a fault-tolerant transversal realization (t/tdg for both codes, plus h for Shor) are emitted as opaque placeholder instructions named {code}_ideal_logical_{gate} rather than as full magic-state constructions.

The encoding, decoding, syndrome, and correction circuits shared with the existing seven_qubit_steane_code and shors_nine_qubit_code benchmarks moved into a new components module.

Limitations: encoding is only applied at BenchmarkLevel.ALG (a UserWarning is raised otherwise), control-flow operations are rejected with a ValueError, and basis decomposition uses approximation_degree=0.95, so encoded circuits are approximations.

AI assistance: this description was drafted by an LLM from the current diff and reviewed by us. Various docstrings were generated by an LLM and reviewed & edited by us.

Checklist

  • The pull request only contains commits that are focused and relevant to this change.
  • We have added appropriate tests that cover the new/changed functionality.
  • We have updated the documentation to reflect these changes.
  • We have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • We have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • We have reviewed our own code changes.

If PR contains AI-assisted content:

  • Any agent that created, edited, or submitted GitHub content was explicitly authorized for that scope, as required by our [AI Usage Guidelines](https://github.com/munich-quantum-toolkit/bench/blob/main/docs/ai_usage.md).
  • Every agent-authored or agent-edited public text body begins with the visible disclosure 🤖 *AI text below* 🤖 (titles are exempt).
  • We have disclosed AI assistance in the PR description.
  • We confirm that we have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

SalehAlsherif and others added 30 commits June 6, 2026 13:40
…c0909/MQT_Bench_ErrorCorrectionCodes into feature/ErrorCorrection_SubMain
…c0909/MQT_Bench_ErrorCorrectionCodes into feature/ErrorCorrection_SubMain
+ early gate_counts.json, counts for steane are not yet correct
…c0909/MQT_Bench_ErrorCorrectionCodes into feature/ErrorCorrection_SubMain
Felix Gundlach and others added 3 commits October 24, 2026 19:15
The EC transpiler now checks the Qiskit version, so the minimum stays at 2.2.3.

- Qiskit 2.5.0 and newer: Qiskit's Clifford+T compilation with `approximation_degree=0.95` (unchanged output).
- Older versions: each RZ rotation is replaced by Solovay-Kitaev at recursion degree 0 (at most 12 H/T/Tdg gates), with only RZ gates changed.

The threshold is 2.5.0 instead of 2.4.2 because gridsynth in Qiskit 2.4.0–2.4.2 panics for about a third of rotation angles at this approximation degree. Only its default precision works there, and that makes encoded circuits 40–80x larger. The EC tests pass on every Qiskit release from 2.2.3 to 2.6.1.
@Felix-Gundlach

Copy link
Copy Markdown
Author

Because I should've put this as a comment, not a commit message, in the first place:

🤖 AI text below 🤖

The EC transpiler now checks the Qiskit version, so the minimum stays at 2.2.3.

  • Qiskit 2.5.0 and newer: Qiskit's Clifford+T compilation with approximation_degree=0.95 (unchanged output).
  • Older versions: each RZ rotation is replaced by Solovay-Kitaev at recursion degree 0 (at most 12 H/T/Tdg gates), with only RZ gates changed.

The threshold is 2.5.0 instead of 2.4.2 because gridsynth in Qiskit 2.4.0–2.4.2 panics for about a third of rotation angles at this approximation degree. Only its default precision works there, and that makes encoded circuits 40–80x larger. The EC tests pass on every Qiskit release from 2.2.3 to 2.6.1.

@Felix-Gundlach

Copy link
Copy Markdown
Author

@simon1hofmann We no use different transpilation passes depending on qiskit version as requested. While not quite the same as the switch quoted in #930 now on main, they work well with the tests. Some oddities may remain™.

Apart from the currently failing test case ("changes can be cleanly merged"...), is there anything else we can still help with?

@simon1hofmann

Copy link
Copy Markdown
Collaborator

Hey @Felix-Gundlach

A few things still need fixing before merging:

  1. Preserve metadata when encoding. ✨ Improve CLI generation and make file exports atomic #1115 added generation settings to circuit metadata and export headers. get_benchmark_alg() records them before replacing the circuit with the encoded result, losing the seed, mirror flag, and caller metadata. Please preserve that metadata and record the encoding name as well.

  2. Fix the CI test input. 🐛 Validate benchmark inputs and document factory options #1108 added the minimum-size check for Bernstein–Vazirani. test_get_benchmark_alg_encoding_parameters still requests one qubit. Use two and check the resulting width: 26 for Steane and 34 for Shor.

  3. Remove the obsolete Qiskit upgrade note. ✨ Add fractional Heron compilation targets #1087 established the current minimum of Qiskit 2.2.3. This PR now retains that support through its fallback, so the new “Qiskit 2.4 minimum” section and the corresponding PR-description claim can be removed.

Please also finish the documentation cleanup:

  • Correct the Steane docstring that still mentions SWAP/DCX/CY.
  • In the changelog, define the [#930] link.
  • Document that circuits containing opaque logical gadgets require QPY export: Shor-encoded GHZ currently fails QASM 3 export, while QPY round-trips successfully.

@Felix-Gundlach

Felix-Gundlach commented Oct 26, 2026 •

Copy link
Copy Markdown
Author

Alright. The PR description has been updated and the requested changes from #930 (comment) implemented by 46394a0. The tests also seem to be passing.

@simon1hofmann Because I felt like the number of tests had grown a bit bloated, I had claude consolidate them a little. Same thing goes for the docstrings, which had grown inconsistent and needlessly precise over the different iterations. I hope that's fine?

Next up is porting changes in the components from main to their new location in this branch and maybe going over the PR description again.

Anything else I can help with?

…pers and applied the same to steane helpers
@Felix-Gundlach

Copy link
Copy Markdown
Author

🤖 AI text below 🤖

Synced the moved Shor's code and Steane code components with main.

  • The function bodies in components/shor_circuit_components.py and components/steane_circuit_components.py match the private helpers on main. Only the docstrings differed.
  • Ported 📝 Fix API documentation markup and notebook builds #1088 to the moved Shor helpers. In the docstrings of get_three_qubit_bit_flip_encoding_decoding_circuit and get_three_qubit_phase_flip_encoding_circuit, the kets are now RST literals (``|0>``). A bare |0> causes "substitution_reference start-string without end-string" warnings.
  • Applied the same markup to get_seven_qubit_steane_code_encoding_circuit. On main this helper is private, so the API docs skip it. In mqt.bench.components it is public, and its docstring produced 18 RST warnings.
  • Restored the indentation from main in the bullet lists of the shors_nine_qubit_code.create_circuit docstring. An extra space made Sphinx render each bullet as a definition list. The create_circuit docstrings of both benchmarks now match main.
  • Replaced the last Arguments: with Args: in shor_circuit_components.py. All component docstrings now use Args:.

This branch has not been deployed

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

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants