-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add commutes protocol #1853
Add commutes protocol #1853
Conversation
cirq/protocols/commutes.py
Outdated
return NotImplemented | ||
|
||
|
||
def _strat_commutes_from_matrix(left_val: Any, right_val: Any, atol: Union[int, float] = 1e-8 |
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.
This doesn't appear to take into consideration the possibility that left_val
and right_val
are operations that act on different qubits.
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.
As an extension to this train of thought, I think that if one is a Gate_Operation
and the other is a Gate
then the protocol should treat it as a strictest case scenario where the Gate
acts on the same qubits as the Gate_Operation
.
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.
The more I think about it, the less I think this general strategy is worth it. Makes more sense to have all the logic in the _commutes_with_
method of the various objects. For example, qubit order using the unitary protocol is tricky with circuits.
) -> Union[NotImplementedType, bool]: | ||
"""Attempts to determine commutativity via the objects' _commutes_ method.""" | ||
for a, b in [(left_val, right_val), (right_val, left_val)]: | ||
getter = getattr(a, '_commutes_', None) |
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.
+1 on changing to _commutes_with_
and refactoring classes that already have this semantics.
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.
Done
|
||
This is determined by any one of the following techniques: | ||
|
||
- Either value has a `_commutes_` method that returns something besides |
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.
note that left_val is considered first
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.
Done
cirq/protocols/commutes.py
Outdated
|
||
- Either value has a `_commutes_` method that returns something besides | ||
NotImplemented. The return value is whatever the method returned. | ||
- Each value is either a matrix or defines one via the unitary protocol. |
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.
split this into two cases? 1. is a matrix 2. defines one via unitary protocol
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.
Obsoleted (delegation to unitary moved to Gate._commutes_with_
)
cirq/protocols/commutes.py
Outdated
This is determined by any one of the following techniques: | ||
|
||
- Either value has a `_commutes_` method that returns something besides | ||
NotImplemented. The return value is whatever the method returned. |
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.
"whatever the method returned" -> "the boolean result from this function" or something to emphasize that you can't return whatever you want in _commutes_
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.
Done
cirq/protocols/commutes.py
Outdated
result = strat(left_val, right_val, atol) | ||
if result is not NotImplemented: | ||
return result | ||
return False |
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.
is this a sensible default? Why not raise a NotImplementedError
or return NotImplemented
all the way up to the caller? cirq.unitary
doesn't return the identity matrix if it can't figure out the unitary representation of an object :)
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.
I imagine this being used for circuit reordering, where what you want to know whether two things definitely commute. (Note that this is the documented behavior.)
Do you have an example where false negatives would be problematic?
cirq/protocols/commutes.py
Outdated
getter = getattr(a, '_commutes_', None) | ||
if getter is None: | ||
continue | ||
val = getter(right_val, 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.
this should be b
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.
Done
I'd advocate for adding underscores, keeping the old signature which dispatches to the underscore version with a deprecation warning for ~1 release cycle |
Done |
Ready for re-review. |
What should (1) They have the same (2) They commute for all possible qubits. For example |
Good question. I think I like (1) best. Specifically:
|
@Strilanc This is what
|
adds Gate._commutes_on_qids_
and coverage
@Strilanc PTAL |
Automerge cancelled: A status check is failing. |
Minimal version so far. Wanted to get some feedback.
Some thoughts:
values_equality
being the name of both a module and a method, so we should probably change at least one of those forcommutes
._commutes_with_
for the magic method? (I just went with convention in the initial issue for now.)cirq.commutes
to be the protocol, which delegates tocirq.linalg.commutes
in the relevant cases. Shouldn't be a problem, but may cause confusion.commute_with
method. Should I add some underscores to that or add a new method that delegates to the existing one?Gate
andGateOperation
whose gate commutes with theGate
, what should be returned?Fixes #1125