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

Enable simplifying 1q runs and 2q blocks in transpile() without target #9222

Merged

Conversation

mtreinish
Copy link
Member

Summary

This commit fixes an issue when transpile() was called with optimization enabled (optimization levels 1, 2, and 3) and no target (or basis gates) specified then 1q run or 2q block optimization was run. This would result in long series of gates that could be simplified being left in the output circuit. To address this, for 1q optimization the
Optimize1qGatesDecomposition pass (which is run at all 3 optimization levels) is updated so that if no target is specified we just try all decomposers as the default heuristic for the best output is the shortest sequence length (in the absense of error rates from the target) and if any output gate is valid that will either remove the 1q sequence if it's an identity sequence, or likely be a single gate. As no basis is specified this behavior is fine since the calculations are quick and any output basis will match the constraints the user provided the transpiler.

For optimization level 3 with it's 2q blcok optimization with the UnitarySynthesis pass it is a bit more involved though. The cost of doing the unitary synthesis is higher, the number of possible decompositions is larger, and we don't have a good heuristic measure of which would perform best without a target specified and it's not feasible to just try all supported basis by the synthesis module. This means for a non-identity 2 qubit block the output will be a UnitaryGate (which without a target specified is a valid output). However, to address the case when an identity block is present in the circuit this can be removed with very little overhead. To accomplish this the ConsolidateBlocks pass is updated to check if an identified 2 qubit block is equal the identity matrix and if so will remove that block from the circuit.

Details and comments

Fixes #9217

This commit fixes an issue when transpile() was called with optimization
enabled (optimization levels 1, 2, and 3) and no target (or basis gates)
specified then 1q run or 2q block optimization was run. This would result
in long series of gates that could be simplified being left in the output
circuit. To address this, for 1q optimization the
Optimize1qGatesDecomposition pass (which is run at all 3 optimization
levels) is updated so that if no target is specified we just try all
decomposers as the default heuristic for the best output is the
shortest sequence length (in the absense of error rates from the target)
and if any output gate is valid that will either remove the 1q sequence
if it's an identity sequence, or likely be a single gate. As no basis is
specified this behavior is fine since the calculations are quick and
any output basis will match the constraints the user provided the
transpiler.

For optimization level 3 with it's 2q blcok optimization with the
UnitarySynthesis pass it is a bit more involved though. The cost of
doing the unitary synthesis is higher, the number of possible
decompositions is larger, and we don't have a good heuristic measure
of which would perform best without a target specified and it's not
feasible to just try all supported basis by the synthesis module.
This means for a non-identity 2 qubit block the output will be a
UnitaryGate (which without a target specified is a valid output).
However, to address the case when an identity block is present in
the circuit this can be removed with very little overhead. To accomplish
this the ConsolidateBlocks pass is updated to check if an identified
2 qubit block is equal the identity matrix and if so will remove that
block from the circuit.

Fixes Qiskit#9217
@mtreinish mtreinish added Changelog: Bugfix Include in the "Fixed" section of the changelog mod: transpiler Issues and PRs related to Transpiler labels Dec 1, 2022
@mtreinish mtreinish added this to the 0.23.0 milestone Dec 1, 2022
@mtreinish mtreinish requested a review from a team as a code owner December 1, 2022 14:45
@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Dec 1, 2022

Pull Request Test Coverage Report for Build 3595486434

  • 24 of 24 (100.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.007%) to 84.586%

Totals Coverage Status
Change from base Build 3594877221: 0.007%
Covered Lines: 63069
Relevant Lines: 74562

💛 - Coveralls

@mtreinish mtreinish force-pushed the fix-identity-simplification-no-target branch from 3b078b8 to 7f687ae Compare December 1, 2022 15:16
Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

The principle of this looks fine to me.

Comment on lines +118 to +119
identity = np.eye(2**unitary.num_qubits)
if np.allclose(identity, unitary.to_matrix()):
Copy link
Member

Choose a reason for hiding this comment

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

allclose has an implicit tolerance built-in, so we're potentially removing things that aren't precisely the identity here. That's sensible, of course, but maybe it's worth making sure the way we handle the tolerance here is consistent with how we treat approximation_degree (especially since that's caused issues in the past) and anywhere else that might skip small values (CommutationAnalysis, maybe?).

Copy link
Member Author

Choose a reason for hiding this comment

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

Well I figured it was ok like this because there is a similar tolerance built-in to the synthesis routines that normally do this optimization that isn't really adjustable either. The approximation_degree usage for synthesis is used for the fidelity of the approximation of the synthesized circuit. I can try to wire the tolerance here in with the value for approximation_degree. I guess I'll just have to figure out what values make sense for a mapping of approximation degree which is from 0 to 1 to the tolerance parameters on allclose.

Copy link
Member

Choose a reason for hiding this comment

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

If an implicit tolerance is something we do elsewhere, I'm happy enough to leave it in place here - I was just concerned with making sure the type of behaviour we have is consistent with itself, whatever it is.

Copy link
Member Author

Choose a reason for hiding this comment

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

That makes sense, just for some references what I was talking about was:

test/python/circuit/test_circuit_qasm3.py Outdated Show resolved Hide resolved
test/python/transpiler/test_consolidate_blocks.py Outdated Show resolved Hide resolved
test/python/transpiler/test_consolidate_blocks.py Outdated Show resolved Hide resolved
This commit fixes an oversight in the previous commit for the 1q
decomposer pass when no basis gates are specified. Previously we were
setting the basis list to be the set of all the gates in the supported
euler basis for the decomposer. This had the unintended side effect of
breaking the heuristic for the decomposer as it would treat any 1q gate
outside of the supported euler basis as needing to be translated. This
was not the desired behavior as any gate is valid. This fixes the logic
to just treat no basis explicitly as everything being valid output and
weight the heuristic error only.
Copy link
Member

@jakelishman jakelishman 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 good now, thanks.

@mergify mergify bot merged commit fd85047 into Qiskit:main Dec 1, 2022
@mtreinish mtreinish deleted the fix-identity-simplification-no-target branch December 1, 2022 20:58
Cryoris pushed a commit to Cryoris/qiskit-terra that referenced this pull request Jan 12, 2023
Qiskit#9222)

* Enable simplifying 1q runs and 2q blocks in transpile() without target

This commit fixes an issue when transpile() was called with optimization
enabled (optimization levels 1, 2, and 3) and no target (or basis gates)
specified then 1q run or 2q block optimization was run. This would result
in long series of gates that could be simplified being left in the output
circuit. To address this, for 1q optimization the
Optimize1qGatesDecomposition pass (which is run at all 3 optimization
levels) is updated so that if no target is specified we just try all
decomposers as the default heuristic for the best output is the
shortest sequence length (in the absense of error rates from the target)
and if any output gate is valid that will either remove the 1q sequence
if it's an identity sequence, or likely be a single gate. As no basis is
specified this behavior is fine since the calculations are quick and
any output basis will match the constraints the user provided the
transpiler.

For optimization level 3 with it's 2q blcok optimization with the
UnitarySynthesis pass it is a bit more involved though. The cost of
doing the unitary synthesis is higher, the number of possible
decompositions is larger, and we don't have a good heuristic measure
of which would perform best without a target specified and it's not
feasible to just try all supported basis by the synthesis module.
This means for a non-identity 2 qubit block the output will be a
UnitaryGate (which without a target specified is a valid output).
However, to address the case when an identity block is present in
the circuit this can be removed with very little overhead. To accomplish
this the ConsolidateBlocks pass is updated to check if an identified
2 qubit block is equal the identity matrix and if so will remove that
block from the circuit.

Fixes Qiskit#9217

* Fix docs build

* Fix handling of 1q decomposer logic with no basis gates

This commit fixes an oversight in the previous commit for the 1q
decomposer pass when no basis gates are specified. Previously we were
setting the basis list to be the set of all the gates in the supported
euler basis for the decomposer. This had the unintended side effect of
breaking the heuristic for the decomposer as it would treat any 1q gate
outside of the supported euler basis as needing to be translated. This
was not the desired behavior as any gate is valid. This fixes the logic
to just treat no basis explicitly as everything being valid output and
weight the heuristic error only.

* Remove debug prints

* Remove unnecessary conditional 1q identity matrix creation

* Split out release notes for 1q and 2q cases

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Bugfix Include in the "Fixed" section of the changelog mod: transpiler Issues and PRs related to Transpiler
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unitaries equal to identity are not removed from circuit at optimization_level=3
4 participants