-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Assume PhasedXPowGate is different from XPowGate and YPowGate #7070
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
Conversation
…ue_equality protocol. A similar change was done for PhasedISwapPowGate. This addresses issue quantumlib#6528.
cirq-core/cirq/ops/phased_x_gate.py
Outdated
|
|
||
| return self._exponent % period | ||
|
|
||
| def _value_equality_values_cls_(self): |
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.
Can this be removed completely? I assume by the description in #4585, removing it entirely would have the same effect. But I could be wrong.
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 - the _value_equality_values_cls_ can be indeed removed provided manual_cls in the decorator is changed to the False default. The _value_equality_approximate_values_ defaults to _value_equality_values_ so it can be removed as well.
diff --git a/cirq-core/cirq/ops/phased_x_gate.py b/cirq-core/cirq/ops/phased_x_gate.py
index d769b863..51bc5f39 100644
--- a/cirq-core/cirq/ops/phased_x_gate.py
+++ b/cirq-core/cirq/ops/phased_x_gate.py
@@ -30,3 +30,3 @@ from cirq.ops import raw_types
-@value.value_equality(manual_cls=True, approximate=True)
+@value.value_equality(approximate=True)
class PhasedXPowGate(raw_types.Gate):
@@ -244,5 +244,2 @@ class PhasedXPowGate(raw_types.Gate):
- def _value_equality_values_cls_(self):
- return PhasedXPowGate
-
def _value_equality_values_(self):
@@ -250,5 +247,2 @@ class PhasedXPowGate(raw_types.Gate):
- def _value_equality_approximate_values_(self):
- return self.phase_exponent, self._canonical_exponent, self._global_shift
-
def _json_dict_(self) -> Dict[str, Any]:
|
Hi Dax and Pavol, Thank you a lot for your feedback! I updated the code following your suggestion. However, in the meantime I noticed that several tests were failing. I updated the tests so that you can see the effect, but I think this change is overall problematic.
all transform gates X and Y to PhasedXPowGate. This worked well until now because the gate was correctly interpreted as X or Y, for example when printing the circuit. However, with this change this is no longer the case. In particular, users will be surprised to optimize a circuit and instead of X, end up with a PhasedXPowGate(phase_exponent=0). It's harder to read, and it's a poor user experience. I am inclined to drop this pull request. Let me know what you think and if there is a way around this problem. |
|
Should an optimizer have a final stage where it puts all the gates in canonical form perhaps? |
Indeed, that would be nice. This change actually shows the affected transformations could work better. @tanujkhattar - would you have some tips for a transformer that does such conversion, Here is an example code adapted from a unit test - import cirq
q = cirq.q(0)
c0 = cirq.Circuit([cirq.Moment([cirq.Z(q) ** 0.5]), cirq.Moment([cirq.Y(q) ** 0.25])])
c1 = cirq.eject_z(c0)
print(repr(c1))output: |
|
I am happy to try and write a transformer that does what you suggested, Pavol. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7070 +/- ##
==========================================
- Coverage 98.65% 98.65% -0.01%
==========================================
Files 1106 1106
Lines 95869 95892 +23
==========================================
+ Hits 94581 94603 +22
- Misses 1288 1289 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@codrut3 thank you for working on this and your willingness to persist. It seems like this would be a worthwhile PR to finish (rather than close) if a transformation can be implemented per comments above. The Qualtran team are among the best people to consult on this topic; @pavoljuhas tagged Tanuj in a comment above, but he may not have been available. I'll ask on the Qualtran list – maybe someone else will be able to help. If we don't get a solution within 24 hrs, I think we should push this PR to after the Cirq 1.5 release. Do people agree? |
Adjust for unequality between X and equal-effect PhasedXPowGate.
|
@codrut3 - I am giving it a quick review pass, please hold on till my next comment. |
This mostly restores the eject_phased_paulis unit tests to their initial form with a few `cirq.Y` replacements sparkled around.
This mostly restores `eject_z_test.py` to its initial form.
pavoljuhas
left a comment
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 have updated the eject_phased_paulis transformation and the phase_by protocol for the X and Y gates so they replace PhasedXPowGate with X or Y gates when equivalent for the phase_exponent. This mostly restores the unit tests back to their original form.
@daxfohl or @tanujkhattar - can you please give it a quick look before merging?
| expected=cirq.Circuit( | ||
| cirq.PhasedXPowGate(phase_exponent=1)(a), | ||
| cirq.Y(b) ** 0.5, | ||
| cirq.PhasedXPowGate(phase_exponent=0.5)(b) ** 0.5, |
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. The updated expected circuit is actually more consistent with the merge_single_qubit_gates_to_phased_x_and_z docstring here -
Cirq/cirq-core/cirq/transformers/merge_single_qubit_gates.py
Lines 28 to 37 in 02941bf
| def merge_single_qubit_gates_to_phased_x_and_z( | |
| circuit: 'cirq.AbstractCircuit', | |
| *, | |
| context: Optional['cirq.TransformerContext'] = None, | |
| atol: float = 1e-8, | |
| ) -> 'cirq.Circuit': | |
| """Replaces runs of single qubit rotations with `cirq.PhasedXPowGate` and `cirq.ZPowGate`. | |
| Specifically, any run of non-parameterized single-qubit unitaries will be replaced by an | |
| optional PhasedX operation followed by an optional Z operation. |
|
@codrut3 - thank you for fixing this! (We are a bit in rush with next |
|
Thank you a lot for doing this @pavoljuhas! I really appreciate it! I also learned from your commits :) |
|
I think we should consider reverting this. This is backwards incompatible:
|
|
cross referencing comment in the related issue - #7284 (comment) TLDR - let us wait with reverting if we can adjust for this downstream |
…mlib#7070) * Assume PhasedXPowGate is different from XPowGate and YPowGate for value_equality protocol. A similar change was done for PhasedISwapPowGate. This addresses issue quantumlib#6528. * Remove _value_equality_values_cls_ and update tests. * Explicitly test that Pauli gates differ from equal-effect PhasedXPowGate * Change engine tests to compare circuit unitaries Adjust for unequality between X and equal-effect PhasedXPowGate. * Fix unintentionally empty Moment in the test * eject_phased_paulis - replace PhasedXPowGate with equivalent X or Y This mostly restores the eject_phased_paulis unit tests to their initial form with a few `cirq.Y` replacements sparkled around. * phase_by for X and Y - replace PhasedXPowGate with equivalent X or Y This mostly restores `eject_z_test.py` to its initial form. --------- Co-authored-by: Michael Hucka <[email protected]> Co-authored-by: Pavol Juhas <[email protected]>
A similar change was done for PhasedISwapPowGate. This addresses issue #6528.