Repository: quantumlib/Cirq

Issue:
Remove exponent parameter from _Pauli{X,Y,Z}
Raising a Pauli to an arbitrary exponent generally does not return another Pauli. Therefore, it doesn't make sense for the constructor of these (private) classes to take the parameter.

Note that functions like `__pow__` do the right thing by instantiating an appropriate gate from `common_gates`.

Also note that this requires custom implementation of algorithms that use `with_exponent`. I think there is just one implemented in `EigenGate. _equal_up_to_global_phase_`.


Discussion:

Resolving patch:
diff --git a/cirq/ops/eigen_gate.py b/cirq/ops/eigen_gate.py
--- a/cirq/ops/eigen_gate.py
+++ b/cirq/ops/eigen_gate.py
@@ -115,7 +115,7 @@ def global_shift(self) -> float:
         return self._global_shift
 
     # virtual method
-    def _with_exponent(self: TSelf, exponent: value.TParamVal) -> TSelf:
+    def _with_exponent(self: TSelf, exponent: value.TParamVal) -> 'EigenGate':
         """Return the same kind of gate, but with a different exponent.
 
         Child classes should override this method if they have an __init__
@@ -337,7 +337,7 @@ def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
     def _is_parameterized_(self) -> bool:
         return protocols.is_parameterized(self._exponent)
 
-    def _resolve_parameters_(self: TSelf, param_resolver) -> TSelf:
+    def _resolve_parameters_(self: TSelf, param_resolver) -> 'EigenGate':
         return self._with_exponent(
                 exponent=param_resolver.value_of(self._exponent))
 
diff --git a/cirq/ops/pauli_gates.py b/cirq/ops/pauli_gates.py
--- a/cirq/ops/pauli_gates.py
+++ b/cirq/ops/pauli_gates.py
@@ -101,50 +101,65 @@ def _canonical_exponent(self):
 
 class _PauliX(Pauli, common_gates.XPowGate):
 
-    def __init__(self, *, exponent: value.TParamVal = 1.0):
+    def __init__(self):
         Pauli.__init__(self, index=0, name='X')
-        common_gates.XPowGate.__init__(self, exponent=exponent)
+        common_gates.XPowGate.__init__(self, exponent=1.0)
 
     def __pow__(self: '_PauliX',
                 exponent: value.TParamVal) -> common_gates.XPowGate:
         return common_gates.XPowGate(exponent=exponent)
 
+    def _with_exponent(self: '_PauliX',
+                       exponent: value.TParamVal) -> common_gates.XPowGate:
+        return self.__pow__(exponent)
+
     @classmethod
     def _from_json_dict_(cls, exponent, global_shift, **kwargs):
         assert global_shift == 0
-        return cls(exponent=exponent)
+        assert exponent == 1
+        return cls()
 
 
 class _PauliY(Pauli, common_gates.YPowGate):
 
-    def __init__(self, *, exponent: value.TParamVal = 1.0):
+    def __init__(self):
         Pauli.__init__(self, index=1, name='Y')
-        common_gates.YPowGate.__init__(self, exponent=exponent)
+        common_gates.YPowGate.__init__(self, exponent=1.0)
 
     def __pow__(self: '_PauliY',
                 exponent: value.TParamVal) -> common_gates.YPowGate:
         return common_gates.YPowGate(exponent=exponent)
 
+    def _with_exponent(self: '_PauliY',
+                       exponent: value.TParamVal) -> common_gates.YPowGate:
+        return self.__pow__(exponent)
+
     @classmethod
     def _from_json_dict_(cls, exponent, global_shift, **kwargs):
         assert global_shift == 0
-        return cls(exponent=exponent)
+        assert exponent == 1
+        return cls()
 
 
 class _PauliZ(Pauli, common_gates.ZPowGate):
 
-    def __init__(self, *, exponent: value.TParamVal = 1.0):
+    def __init__(self):
         Pauli.__init__(self, index=2, name='Z')
-        common_gates.ZPowGate.__init__(self, exponent=exponent)
+        common_gates.ZPowGate.__init__(self, exponent=1.0)
 
     def __pow__(self: '_PauliZ',
                 exponent: value.TParamVal) -> common_gates.ZPowGate:
         return common_gates.ZPowGate(exponent=exponent)
 
+    def _with_exponent(self: '_PauliZ',
+                       exponent: value.TParamVal) -> common_gates.ZPowGate:
+        return self.__pow__(exponent)
+
     @classmethod
     def _from_json_dict_(cls, exponent, global_shift, **kwargs):
         assert global_shift == 0
-        return cls(exponent=exponent)
+        assert exponent == 1
+        return cls()
 
 
 X = _PauliX()


Test patch:
diff --git a/cirq/ops/eigen_gate_test.py b/cirq/ops/eigen_gate_test.py
--- a/cirq/ops/eigen_gate_test.py
+++ b/cirq/ops/eigen_gate_test.py
@@ -407,6 +407,8 @@ def _with_exponent(self, exponent):
     (WeightedZPowGate(0), WeightedZPowGate(0.1), False),
     (WeightedZPowGate(0.3), WeightedZPowGate(0.3, global_shift=0.1), True),
     (cirq.X, cirq.Z, False),
+    (cirq.X, cirq.Y, False),
+    (cirq.rz(np.pi), cirq.Z, True),
     (cirq.X**0.3, cirq.Z**0.3, False),
 ])
 def test_equal_up_to_global_phase(gate1, gate2, eq_up_to_global_phase):