Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix post-oxidization change in ConsolidateBlocks behavior #13450

Merged
merged 4 commits into from
Nov 18, 2024

Conversation

ElePT
Copy link
Contributor

@ElePT ElePT commented Nov 18, 2024

Summary

Fixes the behavioral difference introduced by #13368 that caused #13438.

The original implementation of the pass used to set the ConsolidateBlocks internal decomposer calling unitary_synthesis._decomposer_2q_from_basis_gates, which, when kak_basis wasn't found, would return None. During the oxidization efforts, unitary_synthesis._decomposer_2q_from_basis_gates was replaced with inline code that didn't contemplate this path (always set a default decomposer), which in the reproducing example lead to a longer output circuit (the gates were collected into a unitary block and then decomposed differently).

Details and comments

Technically not a bugfix because the change wasn't released yet.

Using the example shown in the issue ->

ConsolidateBlocks output dag with 1.2.4:
image

ConsolidateBlocks output dag with 1.3.0rc1:
image

ConsolidateBlocks output dag after this fix:
image

@ElePT ElePT added this to the 1.3.0 milestone Nov 18, 2024
@ElePT ElePT requested a review from a team as a code owner November 18, 2024 12:40
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core

mtreinish
mtreinish previously approved these changes Nov 18, 2024
Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

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

Ah, good catch.it was a change in behavior on my consolidate blocks pr not unitary synthesis. I remember changing that logic at the time and thinking it wouldn't impact anything. I was coming at it from the mindset that consolidate blocks is too likely to skip consolidation when it shouldn't.

Realistically we should be relying on the xx decomposer with the rzz in the basis gates list, but there isn't an interface in rust yet to tell us the estimated number of 2q basis gates needed for a unitary, which is why I changed the logic here. Also that is not really a good meteic anyway, just more reason for me to keep working on #13419 and introduce a better approach.

@mtreinish mtreinish added stable backport potential The bug might be minimal and/or import enough to be port to stable Changelog: None Do not include in changelog labels Nov 18, 2024
@ElePT
Copy link
Contributor Author

ElePT commented Nov 18, 2024

Changing the "default" to None now left the paths for rzz and rzx gates unaccounted for. That broke the unit test that was fixed in e3124a6. So, questions:

  1. any specific reason we had not to have rzz in the list? (because I just re-added it)
  2. assuming that we don't want to use the XXDecomposer for rzx. What do we want to have then, None or TwoQubitBasisDecomposer(CXGate())? It currently doesn't break any test but just to confirm.

@coveralls
Copy link

coveralls commented Nov 18, 2024

Pull Request Test Coverage Report for Build 11898770714

Details

  • 4 of 5 (80.0%) changed or added relevant lines in 1 file are covered.
  • 4 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.01%) to 88.954%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/transpiler/passes/optimization/consolidate_blocks.py 4 5 80.0%
Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 92.2%
qiskit/transpiler/passes/optimization/consolidate_blocks.py 1 96.36%
crates/qasm2/src/lex.rs 2 92.48%
Totals Coverage Status
Change from base Build 11842392021: 0.01%
Covered Lines: 79420
Relevant Lines: 89282

💛 - Coveralls

@@ -27,6 +29,7 @@
"cz": CZGate(),
"iswap": iSwapGate(),
"ecr": ECRGate(),
"rxx": RXXGate(pi / 2),
Copy link
Member

Choose a reason for hiding this comment

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

why is the angle here fixed to pi/2 ?

Copy link
Member

Choose a reason for hiding this comment

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

It's because that's what UnitarySynthesis uses if it's a basis_gates only setup: https://github.com/Qiskit/qiskit/blob/main/qiskit/transpiler/passes/synthesis/unitary_synthesis.py#L98 the idea is that it's trying to match the decomposer used for estimating to what the synthesis pass will use later.

The whole logic between the passes is more than a bit hacky. ConsolidateBlocks tries to guess how many 2q gates will be used to decide whether to consolidate the block into a unitary or not. This is strongly coupled to the behavior of UnitarySynthesis because that's what actually does the synthesis later. But none of this actually takes into account multiple possible decomposers/synthesis methods being supported by a target, or the presence of a non-default plugin being used.

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, I did some testing locally with this and in some cases using TwoQubitBasisDecomposer(RXXGate(pi/2)) under estimates what the XXDecomposer estimates, 3 vs 4 gates. This might result in some blocks not getting consolidated which were before, but in practice I find it probably pretty unlikely since it only counts rzz gates when evaluating if the block's gates are more than the expected synthesis output.

@ElePT
Copy link
Contributor Author

ElePT commented Nov 18, 2024

I added a small refactoring on top of the previous changes to make the new implementation hopefully closer to the old one. Now:

  • The default decomposer is None when no basis_gates/kak_gates are found (same as OG). This includes the rzz gate from the issue [EDIT: didn't work. Reverted that change]
  • If an rxx gate is found, the decomposer will be the TwoQubitBasisDecomposer with a RXX(pi/2) (same as OG)
  • If an rzx gate is found, the decomposer will be the TwoQubitBasisDecomposer with a CXGate (same as backup decomposer from OG implementation)

I also added a comment that mentions the previous use of the XXDecomposer for the rzx case for clarity.

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

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

I'm fine with this it returns the previous state of logic. There might be some subtle differences in what gets consolidated or not with rzx based on differences between XXDecomposer.num_basis_gates and TwoQubitBasisDecomposer's logic, but it should be close enough to the 1.2.x state of the logic that I'm not worried.

I think this whole exercise reinforces for me how we need to improve the logic around block consolidation. #13419 will do this for the optimization loop, but we will need to think what makes the most sense for when we run ConsolidateBlocks prior to layout in the init stage.

@mtreinish mtreinish added this pull request to the merge queue Nov 18, 2024
Merged via the queue into Qiskit:main with commit 94cea41 Nov 18, 2024
17 checks passed
mergify bot pushed a commit that referenced this pull request Nov 18, 2024
* Set decomposer to None if kak_gates not found during ConsolidateBlocks initialization.

* Add test that reproduces issue

* Re-add rzz to list of kak gates

* Add path for rzx gate.

(cherry picked from commit 94cea41)
github-merge-queue bot pushed a commit that referenced this pull request Nov 19, 2024
…13453)

* Set decomposer to None if kak_gates not found during ConsolidateBlocks initialization.

* Add test that reproduces issue

* Re-add rzz to list of kak gates

* Add path for rzx gate.

(cherry picked from commit 94cea41)

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
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 stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optimization level 2 and 3 result in a deeper circuit with 1.3.0rc1 and main branch
5 participants