Skip to content

Split two qubit decomposer file into separate files#15833

Merged
alexanderivrii merged 2 commits intoQiskit:mainfrom
mtreinish:split-two-q-org
Mar 22, 2026
Merged

Split two qubit decomposer file into separate files#15833
alexanderivrii merged 2 commits intoQiskit:mainfrom
mtreinish:split-two-q-org

Conversation

@mtreinish
Copy link
Copy Markdown
Member

Summary

This commit takes the single crates/synthesis/src/two_qubit_decompose.rs file and splits it into a directory that contains several submodule files. The original file kind of organically mirrored the python structure which was to have all the two qubit decomposer implementations in a single giant file. This was an anti-pattern in python and has led to us missing many details over time because it was impossible to keep the entire contents of the file in your head or on screen. This has also translated to the Rust version of this module as I recently discovered during the development of #13419 that there is a duplicated method with two different names on the two qubit basis decomposer. The implementations actually are right next to each other in the impl block. Nobody noticed because the file was too big. This commit doesn't fix this as I wanted this migration to not change any code if possible. The new structure of this module is to break out each decomposer implementation into a standalone file. If we add new decomposers in the future they will naturally fit into a new file.

The only small changes made to the code in this commit are mostly about visibility of functions and structs because things need to be at least pub(super) if they cross a file boundary now. A few places were made fully pub or pub(crate) depending on how they're used. Python things were made full pub to indicate that even if pyo3 doesn't require it. There was one small code change made as part of this in the TwoQubitBasisDecomposer::__getnewargs__ method it was previously accessing the TwoQubitWeylDecomposer's unitary_matrix field and then converting that to a python array and finally a Py. However there was a dedicated method for that already
TwoQubitWeylDecomposer::unitary_matrix(), I switched the implementation to just use that method instead. I originally did this in order to avoid changing the visibility on the unitary_matrix field, but I had to do that for other places, but I decided not to change this back because it's a more natural fit.

Details and comments

This commit takes the single crates/synthesis/src/two_qubit_decompose.rs
file and splits it into a directory that contains several submodule
files. The original file kind of organically mirrored the python
structure which was to have all the two qubit decomposer implementations
in a single giant file. This was an anti-pattern in python and has led
to us missing many details over time because it was impossible to keep
the entire contents of the file in your head or on screen. This has also
translated to the Rust version of this module as I recently discovered
during the development of Qiskit#13419 that there is a duplicated method with
two different names on the two qubit basis decomposer. The
implementations actually are right next to each other in the impl block.
Nobody noticed because the file was too big. This commit doesn't fix
this as I wanted this migration to not change any code if possible. The
new structure of this module is to break out each decomposer
implementation into a standalone file. If we add new decomposers in the
future they will naturally fit into a new file.

The only small changes made to the code in this commit are mostly about
visibility of functions and structs because things need to be at least
pub(super) if they cross a file boundary now. A few places were made
fully pub or pub(crate) depending on how they're used. Python things
were made full pub to indicate that even if pyo3 doesn't require it.
There was one small code change made as part of this in the
`TwoQubitBasisDecomposer::__getnewargs__` method it was previously
accessing the `TwoQubitWeylDecomposer`'s `unitary_matrix` field and then
converting that to a python array and finally a Py<PyAny>. However there
was a dedicated method for that already
`TwoQubitWeylDecomposer::unitary_matrix()`, I switched the
implementation to just use that method instead. I originally did this in
order to avoid changing the visibility on the unitary_matrix field, but
I had to do that for other places, but I decided not to change this back
because it's a more natural fit.
@mtreinish mtreinish added the Changelog: None Do not include in the GitHub Release changelog. label Mar 18, 2026
@mtreinish mtreinish requested a review from a team as a code owner March 18, 2026 22:43
@mtreinish mtreinish added the Rust This PR or issue is related to Rust code in the repository label Mar 18, 2026
@qiskit-bot
Copy link
Copy Markdown
Collaborator

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

  • @Qiskit/terra-core
  • @levbishop

mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Mar 19, 2026
This commit removes a duplicated method implementation on the
TwoQubitBasisDecomposer. The struct had two methods, call_inner and
generate_sequences, which were almost line for line identical. I believe
this occured during a rebase when two concurrently developed PRs were
touching the same file and the rebase was a bit off after one merged
which resulted in the methods being duplicated. This was missed for
quite some time and is what prompted Qiskit#15833 because the original
two_qubit_decompose.rs file was so big it was very easy to overlook this
duplication. This commit deletes the generate_sequence implementation
and just uses the call_inner function.
@ShellyGarion ShellyGarion added this to the 2.5.0 milestone Mar 19, 2026
Copy link
Copy Markdown
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.

Thanks Matthew - splitting this absolutely gigantic file into multiple smaller files makes a lot of sense. I could spot several functions that could probably be moved to a more common place, but it can be postponed till we need to use these functions from other files.

Comment on lines +43 to +46
/// invert 1q gate sequence
fn invert_1q_gate(
gate: (StandardGate, SmallVec<[f64; 3]>),
) -> (PackedOperation, SmallVec<[f64; 3]>) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Minor: this function should probably be in common.rs, but we can move it later when we need it from a different file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure since we don't use it in the basis decomposer.

Ok((real_map, circ))
}

fn compute_unitary(sequence: &TwoQubitSequenceVec, global_phase: f64) -> Array2<Complex64> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This function as well could be moved to common.rs, but we don't need to do this right away.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

by the comments inside it, it seems too specific for x,sx,rz synthesis, so I left it where it is.

@alexanderivrii alexanderivrii added this pull request to the merge queue Mar 22, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Mar 22, 2026

const PI2: f64 = PI / 2.;
const PI4: f64 = PI / 4.;
const TWO_PI: f64 = 2.0 * PI;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why don't we use here FARC_PI_2, FARC_PI_4 etc.? this can be done in a follow-up.

const PI4: f64 = PI / 4.;
const PI32: f64 = 3.0 * PI2;
const TWO_PI: f64 = 2.0 * PI;
const C1: c64 = c64 { re: 1.0, im: 0.0 };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same comment about the constants, but can be also done in a follow-up

@alexanderivrii alexanderivrii added this pull request to the merge queue Mar 22, 2026
Merged via the queue into Qiskit:main with commit 7c0cd53 Mar 22, 2026
25 checks passed
@github-project-automation github-project-automation Bot moved this from Ready to Done in Qiskit 2.5 Mar 22, 2026
@mtreinish mtreinish deleted the split-two-q-org branch March 22, 2026 15:09
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Mar 23, 2026
This commit removes a duplicated method implementation on the
TwoQubitBasisDecomposer. The struct had two methods, call_inner and
generate_sequences, which were almost line for line identical. I believe
this occured during a rebase when two concurrently developed PRs were
touching the same file and the rebase was a bit off after one merged
which resulted in the methods being duplicated. This was missed for
quite some time and is what prompted Qiskit#15833 because the original
two_qubit_decompose.rs file was so big it was very easy to overlook this
duplication. This commit deletes the generate_sequence implementation
and just uses the call_inner function.
github-merge-queue Bot pushed a commit that referenced this pull request Mar 23, 2026
This commit removes a duplicated method implementation on the
TwoQubitBasisDecomposer. The struct had two methods, call_inner and
generate_sequences, which were almost line for line identical. I believe
this occured during a rebase when two concurrently developed PRs were
touching the same file and the rebase was a bit off after one merged
which resulted in the methods being duplicated. This was missed for
quite some time and is what prompted #15833 because the original
two_qubit_decompose.rs file was so big it was very easy to overlook this
duplication. This commit deletes the generate_sequence implementation
and just uses the call_inner function.
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 the GitHub Release changelog. Rust This PR or issue is related to Rust code in the repository

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants