diff --git a/cirq/ops/pauli_interaction_gate.py b/cirq/ops/pauli_interaction_gate.py index 562c6b0add6..5a0a27df8fa 100644 --- a/cirq/ops/pauli_interaction_gate.py +++ b/cirq/ops/pauli_interaction_gate.py @@ -17,7 +17,7 @@ import numpy as np from cirq import value, protocols -from cirq._compat import proper_repr +from cirq._compat import deprecated, proper_repr from cirq.ops import gate_features, common_gates, eigen_gate, pauli_gates from cirq.ops.clifford_gate import SingleQubitCliffordGate @@ -66,10 +66,58 @@ def __init__( equal to the tensor product of the two conditions. """ super().__init__(exponent=exponent) - self.pauli0 = pauli0 - self.invert0 = invert0 - self.pauli1 = pauli1 - self.invert1 = invert1 + self._pauli0 = pauli0 + self._invert0 = invert0 + self._pauli1 = pauli1 + self._invert1 = invert1 + + @property + def pauli0(self) -> 'cirq.Pauli': + return self._pauli0 + + @pauli0.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def pauli0(self, pauli0: 'cirq.Pauli'): + self._pauli0 = pauli0 + + @property + def invert0(self) -> bool: + return self._invert0 + + @invert0.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def invert0(self, invert0: bool): + self._invert0 = invert0 + + @property + def pauli1(self) -> 'cirq.Pauli': + return self._pauli1 + + @pauli1.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def pauli1(self, pauli1: 'cirq.Pauli'): + self._pauli1 = pauli1 + + @property + def invert1(self) -> bool: + return self._invert1 + + @invert1.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def invert1(self, invert1: bool): + self._invert1 = invert1 def _num_qubits_(self) -> int: return 2 diff --git a/cirq/ops/pauli_interaction_gate_test.py b/cirq/ops/pauli_interaction_gate_test.py index 04bcfe5a63e..4a7eb6fde98 100644 --- a/cirq/ops/pauli_interaction_gate_test.py +++ b/cirq/ops/pauli_interaction_gate_test.py @@ -126,3 +126,19 @@ def test_text_diagrams(): q1: ───X───X──────(-X)───(-X)───Y───@───Y───(-@)───(-Y)─── """.strip() ) + + +def test_setters_deprecated(): + gate = cirq.PauliInteractionGate(cirq.X, False, cirq.X, False) + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.pauli0 = cirq.Y + assert gate.pauli0 == cirq.Y + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.pauli1 = cirq.Y + assert gate.pauli1 == cirq.Y + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.invert0 = True + assert gate.invert0 + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.invert1 = True + assert gate.invert1 diff --git a/cirq/ops/pauli_measurement_gate.py b/cirq/ops/pauli_measurement_gate.py index b4e29e8b726..b142e3d9f02 100644 --- a/cirq/ops/pauli_measurement_gate.py +++ b/cirq/ops/pauli_measurement_gate.py @@ -15,6 +15,7 @@ from typing import Any, Dict, FrozenSet, Iterable, Tuple, Sequence, TYPE_CHECKING, Union, cast from cirq import protocols, value +from cirq._compat import deprecated from cirq.ops import ( raw_types, measurement_gate, @@ -68,17 +69,35 @@ def __init__( ) self._observable = dps.DensePauliString(observable, coefficient=coefficient) - self.key = key # type: ignore + self._mkey = ( + key if isinstance(key, value.MeasurementKey) else value.MeasurementKey(name=key) + ) @property def key(self) -> str: return str(self.mkey) - @key.setter - def key(self, key: Union[str, 'cirq.MeasurementKey']) -> None: + @key.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def key(self, key: Union[str, 'cirq.MeasurementKey']): if isinstance(key, str): key = value.MeasurementKey(name=key) - self.mkey = key + self._mkey = key + + @property + def mkey(self) -> 'cirq.MeasurementKey': + return self._mkey + + @mkey.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def mkey(self, mkey: 'cirq.MeasurementKey'): + self._mkey = mkey def _qid_shape_(self) -> Tuple[int, ...]: return (2,) * len(self._observable) diff --git a/cirq/ops/pauli_measurement_gate_test.py b/cirq/ops/pauli_measurement_gate_test.py index 348f414f9cc..533e87f9b21 100644 --- a/cirq/ops/pauli_measurement_gate_test.py +++ b/cirq/ops/pauli_measurement_gate_test.py @@ -195,3 +195,19 @@ def test_pauli_measurement_gate_samples(rot, obs, out): q = cirq.NamedQubit("q") c = cirq.Circuit(rot(q), cirq.PauliMeasurementGate(obs, key='out').on(q)) assert cirq.Simulator().sample(c)['out'][0] == out + + +def test_setters_deprecated(): + gate = cirq.PauliMeasurementGate(cirq.DensePauliString("Z", coefficient=+1), key='m') + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.key = 'n' + assert gate.key == 'n' + assert gate.mkey == cirq.MeasurementKey('n') + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.key = cirq.MeasurementKey('o') + assert gate.key == 'o' + assert gate.mkey == cirq.MeasurementKey('o') + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.mkey = cirq.MeasurementKey('p') + assert gate.key == 'p' + assert gate.mkey == cirq.MeasurementKey('p') diff --git a/cirq/ops/pauli_string_raw_types.py b/cirq/ops/pauli_string_raw_types.py index 54430532373..cf75784d506 100644 --- a/cirq/ops/pauli_string_raw_types.py +++ b/cirq/ops/pauli_string_raw_types.py @@ -17,6 +17,7 @@ import abc from cirq import protocols +from cirq._compat import deprecated from cirq.ops import pauli_string as ps, raw_types if TYPE_CHECKING: @@ -29,7 +30,19 @@ class PauliStringGateOperation(raw_types.Operation, metaclass=abc.ABCMeta): def __init__(self, pauli_string: ps.PauliString) -> None: - self.pauli_string = pauli_string + self._pauli_string = pauli_string + + @property + def pauli_string(self) -> 'cirq.PauliString': + return self._pauli_string + + @pauli_string.setter # type: ignore + @deprecated( + deadline="v0.15", + fix="The mutators of this class are deprecated, instantiate a new object instead.", + ) + def pauli_string(self, pauli_string: 'cirq.PauliString'): + self._pauli_string = pauli_string def validate_args(self, qubits: Sequence[raw_types.Qid]) -> None: if len(qubits) != len(self.pauli_string): diff --git a/cirq/ops/pauli_string_raw_types_test.py b/cirq/ops/pauli_string_raw_types_test.py index ed34fadc789..776fdc7aa28 100644 --- a/cirq/ops/pauli_string_raw_types_test.py +++ b/cirq/ops/pauli_string_raw_types_test.py @@ -91,3 +91,16 @@ def _circuit_diagram_info_( q2: ───[Z]───[Z]─── """, ) + + +def test_setters_deprecated(): + q0 = cirq.LineQubit(0) + + class DummyGate(cirq.PauliStringGateOperation): + def map_qubits(self, qubit_map): + pass + + gate = DummyGate(cirq.PauliString({q0: cirq.X})) + with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): + gate.pauli_string = cirq.PauliString({q0: cirq.Z}) + assert gate.pauli_string == cirq.PauliString({q0: cirq.Z})