Skip to content

Conversation

@codrut3
Copy link
Contributor

@codrut3 codrut3 commented Feb 15, 2025

A similar change was done for PhasedISwapPowGate. This addresses issue #6528.

…ue_equality protocol.

A similar change was done for PhasedISwapPowGate. This addresses issue quantumlib#6528.
@codrut3 codrut3 requested review from a team and vtomole as code owners February 15, 2025 20:23
@codrut3 codrut3 requested a review from viathor February 15, 2025 20:23
@CirqBot CirqBot added the size: S 10< lines changed <50 label Feb 15, 2025

return self._exponent % period

def _value_equality_values_cls_(self):
Copy link
Collaborator

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.

Copy link
Collaborator

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]:

@codrut3 codrut3 requested review from verult and wcourtney as code owners March 3, 2025 22:24
@codrut3
Copy link
Contributor Author

codrut3 commented Mar 3, 2025

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.
The problem is that:

  • circuit optimization,
  • merge gate operations,
  • and conversion to proto,

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.

@daxfohl
Copy link
Collaborator

daxfohl commented Mar 4, 2025

Should an optimizer have a final stage where it puts all the gates in canonical form perhaps?

@pavoljuhas
Copy link
Collaborator

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,
e.g., cirq.PhasedXPowGate(phase_exponent=0) to cirq.X?

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:

cirq.Circuit([
    cirq.Moment(
        cirq.PhasedXPowGate(phase_exponent=0.0, exponent=0.25).on(cirq.LineQubit(0)),
    ),
    cirq.Moment(
        cirq.S(cirq.LineQubit(0)),
    ),
])

@codrut3
Copy link
Contributor Author

codrut3 commented Mar 25, 2025

I am happy to try and write a transformer that does what you suggested, Pavol.

@pavoljuhas pavoljuhas added the priority/before-1.5 Finish before the Cirq 1.5 release label Apr 4, 2025
@mhucka mhucka self-assigned this Apr 6, 2025
@codecov
Copy link

codecov bot commented Apr 6, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.65%. Comparing base (02941bf) to head (3034d1a).
Report is 34 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mhucka
Copy link
Contributor

mhucka commented Apr 6, 2025

@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?

@pavoljuhas
Copy link
Collaborator

@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.
Copy link
Collaborator

@pavoljuhas pavoljuhas left a 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,
Copy link
Collaborator

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 -

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.

@mhucka mhucka assigned pavoljuhas and unassigned mhucka Apr 7, 2025
@pavoljuhas pavoljuhas added this pull request to the merge queue Apr 7, 2025
Merged via the queue into quantumlib:main with commit 0a326d0 Apr 7, 2025
38 checks passed
@pavoljuhas
Copy link
Collaborator

@codrut3 - thank you for fixing this! (We are a bit in rush with next
release so I took a liberty to wrap up few final steps.)

@codrut3
Copy link
Contributor Author

codrut3 commented Apr 8, 2025

Thank you a lot for doing this @pavoljuhas! I really appreciate it! I also learned from your commits :)

@dstrain115
Copy link
Collaborator

I think we should consider reverting this. This is backwards incompatible:

cirq.X**0.5 == cirq.PhasedXPowGate(exponent=0.5,phase_exponent=0) returns True before the change and False afterwards. This is a change in behavior that could have unexpected and adverse behavior for users.

@pavoljuhas
Copy link
Collaborator

pavoljuhas commented Apr 22, 2025

cross referencing comment in the related issue - #7284 (comment)

TLDR - let us wait with reverting if we can adjust for this downstream

@dstrain115 dstrain115 added the BREAKING CHANGE For pull requests that are important to mention in release notes. label Apr 23, 2025
BichengYing pushed a commit to BichengYing/Cirq that referenced this pull request Jun 20, 2025
…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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BREAKING CHANGE For pull requests that are important to mention in release notes. priority/before-1.5 Finish before the Cirq 1.5 release size: S 10< lines changed <50

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants