Skip to content

Conversation

mtreinish
Copy link
Member

@mtreinish mtreinish commented Aug 7, 2025

Summary

This commit ports the implementation of the Unroll3qOrMore transpiler
pass to Rust. Functionally in Python we don't use this pass by default
anymore by default because it's been superseded by HighLevelSynthesis
which does unrolling of custom operations for us. However, in the C
transpilation API we don't expose high level synthesis because we don't
expose custom operations to C yet. So to handle multiqubit gates in the
circuit we need the unroll 3q or more pass to serve the purpose it did
before high level synthesis. The first step for that is porting the
implementation of the pass to rust which will then let us call it from C
without Python.

Details and comments

Fixes #12247

This PR is based on #14766 and it will need to be rebased after #14766 merges this will need to be rebased. In the meantime you can view the contents of just this PR by looking at the HEAD commit: b5b94bd This has been rebased now.

@mtreinish mtreinish added this to the 2.2.0 milestone Aug 7, 2025
@mtreinish mtreinish requested a review from a team as a code owner August 7, 2025 18:13
@mtreinish mtreinish added performance Changelog: None Do not include in changelog Rust This PR or issue is related to Rust code in the repository mod: transpiler Issues and PRs related to Transpiler labels Aug 7, 2025
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@mtreinish mtreinish added the on hold Can not fix yet label Aug 7, 2025
@coveralls
Copy link

coveralls commented Aug 7, 2025

Pull Request Test Coverage Report for Build 16920565451

Details

  • 50 of 57 (87.72%) changed or added relevant lines in 4 files are covered.
  • 11 unchanged lines in 4 files lost coverage.
  • Overall coverage decreased (-0.008%) to 87.667%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/transpiler/src/passes/unroll_3q_or_more.rs 38 45 84.44%
Files with Coverage Reduction New Missed Lines %
crates/circuit/src/dag_circuit.rs 1 85.37%
crates/circuit/src/parameter/symbol_expr.rs 1 74.38%
crates/qasm2/src/lex.rs 3 92.01%
crates/qasm2/src/parse.rs 6 97.56%
Totals Coverage Status
Change from base Build 16920055933: -0.008%
Covered Lines: 82433
Relevant Lines: 94030

💛 - Coveralls

@mtreinish mtreinish changed the title Unroll 3q or rust Port Unroll3qOrMore to Rust Aug 7, 2025
@mtreinish mtreinish removed the on hold Can not fix yet label Aug 12, 2025
@mtreinish
Copy link
Member Author

With #14766 merging this is now unblocked and ready to review.

This commit ports the implementation of the Unroll3qOrMore transpiler
pass to Rust. Functionally in Python we don't use this pass by default
anymore by default because it's been superseded by HighLevelSynthesis
which does unrolling of custom operations for us. However, in the C
transpilation API we don't expose high level synthesis because we don't
expose custom operations to C yet. So to handle multiqubit gates in the
circuit we need the unroll 3q or more pass to serve the purpose it did
before high level synthesis. The first step for that is porting the
implementation of the pass to rust which will then let us call it from C
without Python.

Fixes Qiskit#12247
Copy link
Member

@alexanderivrii alexanderivrii left a comment

Choose a reason for hiding this comment

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

This looks great. I just had one minor question (inline).

Comment on lines +27 to +28
#[error("Failed to substitute the definition")]
SubstitutionError(PyErr),
Copy link
Member

Choose a reason for hiding this comment

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

I may not have fully understood the discussion around using PyErr for the C API, is it fine to keep the PyErr here?

Copy link
Member Author

Choose a reason for hiding this comment

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

The issue with PyErr for the C API is that we can't get any an error message or anything to return to see from it. It is a pure rust error type, but it's opaque without the GIL. It's fine to return it as long as we don't need to introspect the error for any details. In this case I put an error message on the error type here which we can use for returning to the user in C if needed ("Failed to substitute the definition"), although I'm not sure we'll need to return it to C, it's not really recoverable. This will let us keep the the original PyErr opaque and untouched in a C context. But for a Python context we can return the python space error returned.

More generally the use of PyErr is in a lot of the C API right now and will need to be cleaned up in a larger refactor.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the explanation.

Comment on lines +46 to +49
if target is None:
self.target = Target.from_configuration(
[x for x in basis_gates if x not in CONTROL_FLOW_OP_NAMES]
)
Copy link
Member

Choose a reason for hiding this comment

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

This is nice, and explains why the Rust version of the pass does not need basis gates.

@alexanderivrii alexanderivrii added this pull request to the merge queue Aug 17, 2025
Merged via the queue into Qiskit:main with commit ec33c11 Aug 17, 2025
26 checks passed
@mtreinish mtreinish deleted the unroll-3q-or-RUST branch August 17, 2025 11:25
@mtreinish mtreinish mentioned this pull request Aug 17, 2025
13 tasks
littlebullGit pushed a commit to littlebullGit/qiskit that referenced this pull request Sep 5, 2025
This commit ports the implementation of the Unroll3qOrMore transpiler
pass to Rust. Functionally in Python we don't use this pass by default
anymore by default because it's been superseded by HighLevelSynthesis
which does unrolling of custom operations for us. However, in the C
transpilation API we don't expose high level synthesis because we don't
expose custom operations to C yet. So to handle multiqubit gates in the
circuit we need the unroll 3q or more pass to serve the purpose it did
before high level synthesis. The first step for that is porting the
implementation of the pass to rust which will then let us call it from C
without Python.

Fixes Qiskit#12247
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in changelog mod: transpiler Issues and PRs related to Transpiler performance Rust This PR or issue is related to Rust code in the repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Port Unroll3qOrMore to Rust
4 participants