-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix moment commutation detection for group-commuting operations (#6659) #7082
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 moment commutation detection for group-commuting operations (#6659) #7082
Conversation
Add pairwise commuting checks and, when inconclusive, fall back to full unitary commutator. Includes new tests showing Z⊗Z commutes with RXX. Fixes quantumlib#6659.
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
cirq-core/cirq/circuits/moment.py
Outdated
return True | ||
|
||
# If individual operations don't commute or we couldn't determine, | ||
# try checking if the full moments commute using unitary matrices |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this could be part of protocols.commutes
itself. If that was the case then we'd have full coverage of stuff that commutes or not, at least for unitary things, but we can still override _commutes_
like here for perf reasons. @pavoljuhas wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
working on it today, update soon ...
* prune duplicate or redundant test cases * reuse cirq.AmplitudeDampingChannel to test with non-unitary * move commute-related test functions together
Also check `measurement_key_objs` and `control_keys` active for checked Moments as in the Operation commutes protocol.
Adapt `cirq.ops.classically_controlled_operation_test.test_commute`
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7082 +/- ##
==========================================
- Coverage 98.13% 98.13% -0.01%
==========================================
Files 1093 1093
Lines 95528 95579 +51
==========================================
+ Hits 93746 93796 +50
- Misses 1782 1783 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The PR was failing some tests as they were initially on the main branch
The Operation.commutes function is already doing some clever things like checking the measurement and control keys, as well, as making sure calculation of unitaries would not take too much memory. I decided to reuse that code by converting Moment to CircuitOperation if needed and then falling back to the commutes evaluation for operations. Here is my take on it, @chamodtharakaperera and @daxfohl - please let me know if this looks OK |
Should that logic from |
Generalize `Operation._commutes_` in a shared internal function `_operations_commutes_impl`
No change in code function.
Also adjust `_operations_commutes_impl` to assume equal Moment-s and Operation-s commute.
@daxfohl - I feel it is better to keep the protocol implementation at its top level general and isolated from the details (and import dependencies) of Operation / Moment classes. The second suggestion sounds very good, here is my take on it - 2fee594...a55b675. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I added a note, but may be out of scope here. But if it's a simple change I think it'd be worth it.
return NotImplemented | ||
|
||
return np.allclose(m12, m21, atol=atol) | ||
return _operations_commutes_impl([self], [other], atol=atol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also check commutes(other, self) for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT, the _operations_commutes_impl
is symmetric in its arguments.
The protocol.commutes
will also do it for us anyway.
- frozenset().union(*tuples) is faster than iterating over all items in every tuple to construct a frozenset. - base class Operation does not have `__hash__` method, therefore we cannot use `set(operations)`.
Thank you @chamodtharakaperera and @daxfohl ! |
…tumlib#6659) (quantumlib#7082) * Fix Moment.commutes_ to handle multi-qubit unitaries (quantumlib#6659) Add pairwise commuting checks and, when inconclusive, fall back to full unitary commutator. Includes new tests showing Z⊗Z commutes with RXX. Fixes quantumlib#6659. * Put back pre-existing commutation tests * prune duplicate or redundant test cases * reuse cirq.AmplitudeDampingChannel to test with non-unitary * move commute-related test functions together * Refactor `Moment._commutes_` to convert to CircuitOperation if necessary Also check `measurement_key_objs` and `control_keys` active for checked Moments as in the Operation commutes protocol. * Test commutation of moments with measurement keys and controls Adapt `cirq.ops.classically_controlled_operation_test.test_commute` * Small tweak of docstring * Add shared internal function _operations_commutes_impl Generalize `Operation._commutes_` in a shared internal function `_operations_commutes_impl` * Sync module variable name with circuit module name No change in code function. * Use shared _operations_commutes_impl for Moment._commutes_ Also adjust `_operations_commutes_impl` to assume equal Moment-s and Operation-s commute. * Few optimizations in _operations_commutes_impl - frozenset().union(*tuples) is faster than iterating over all items in every tuple to construct a frozenset. - base class Operation does not have `__hash__` method, therefore we cannot use `set(operations)`. --------- Co-authored-by: Pavol Juhas <juhas@google.com>
Fixes #6659
This PR fixes an issue where cirq.commutes() incorrectly returns False for moments that commute as a whole even when their individual operations don't commute. For example, given two Z gates and an RXX gate, [Z⊗Z, RXX] = 0 even though neither Z commutes with RXX individually.
The solution:
Added comprehensive test cases covering:
Test outputs demonstrate correct behavior for all cases including the original issue where Z⊗Z should commute with RXX.