Skip to content

Commit 78caf84

Browse files
daxfohltonybruguier
authored andcommitted
Deprecate the ActOnArgs._on_* methods (quantumlib#5224)
Now that we have separated out the `QuantumStateRepresentation` from `ActOnArgs`, there is no need for the `_on_*` methods anymore. This PR deprecates those, adds deprecation tests, and updates any old test ActOnArgs to use the new QuantumStateRepresentation internally. @95-martin-orion
1 parent 529c1ef commit 78caf84

File tree

4 files changed

+126
-21
lines changed

4 files changed

+126
-21
lines changed

cirq-core/cirq/protocols/act_on_protocol_test.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@
2020
from cirq.ops.raw_types import TSelf
2121

2222

23+
class DummyQuantumState(cirq.QuantumStateRepresentation):
24+
def copy(self, deep_copy_buffers=True):
25+
pass
26+
27+
def measure(self, axes, seed=None):
28+
pass
29+
30+
2331
class DummyActOnArgs(cirq.ActOnArgs):
24-
def __init__(self, fallback_result: Any = NotImplemented, measurements=None):
25-
super().__init__(np.random.RandomState())
26-
if measurements is None:
27-
measurements = []
28-
self.measurements = measurements
32+
def __init__(self, fallback_result: Any = NotImplemented):
33+
super().__init__(np.random.RandomState(), state=DummyQuantumState())
2934
self.fallback_result = fallback_result
3035

31-
def _perform_measurement(self, qubits):
32-
return self.measurements # coverage: ignore
33-
3436
def _act_on_fallback_(
3537
self,
3638
action: Any,

cirq-core/cirq/sim/act_on_args.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import numpy as np
3131

3232
from cirq import protocols, value
33-
from cirq._compat import deprecated
33+
from cirq._compat import _warn_or_error, deprecated
3434
from cirq.protocols.decompose_protocol import _try_decompose_into_operations_and_qubits
3535
from cirq.sim.operation_target import OperationTarget
3636

@@ -78,6 +78,8 @@ def __init__(
7878
}
7979
)
8080
self._state = state
81+
if state is None:
82+
_warn_or_error('This function will require a valid `state` input in cirq v0.16.')
8183

8284
@property
8385
def prng(self) -> np.random.RandomState:
@@ -147,9 +149,17 @@ def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf:
147149
if self._state is not None:
148150
args._state = self._state.copy(deep_copy_buffers=deep_copy_buffers)
149151
else:
152+
_warn_or_error(
153+
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
154+
' overrides will be removed in cirq v0.16.'
155+
)
150156
self._on_copy(args, deep_copy_buffers)
151157
return args
152158

159+
@deprecated(
160+
deadline='v0.16',
161+
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
162+
)
153163
def _on_copy(self: TSelf, args: TSelf, deep_copy_buffers: bool = True):
154164
"""Subclasses should implement this with any additional state copy
155165
functionality."""
@@ -164,10 +174,18 @@ def kronecker_product(self: TSelf, other: TSelf, *, inplace=False) -> TSelf:
164174
if self._state is not None and other._state is not None:
165175
args._state = self._state.kron(other._state)
166176
else:
177+
_warn_or_error(
178+
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
179+
' overrides will be removed in cirq v0.16.'
180+
)
167181
self._on_kronecker_product(other, args)
168182
args._set_qubits(self.qubits + other.qubits)
169183
return args
170184

185+
@deprecated(
186+
deadline='v0.16',
187+
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
188+
)
171189
def _on_kronecker_product(self: TSelf, other: TSelf, target: TSelf):
172190
"""Subclasses should implement this with any additional state product
173191
functionality, if supported."""
@@ -204,6 +222,10 @@ def factor(
204222
extracted._state = e
205223
remainder._state = r
206224
else:
225+
_warn_or_error(
226+
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
227+
' overrides will be removed in cirq v0.16.'
228+
)
207229
self._on_factor(qubits, extracted, remainder, validate, atol)
208230
extracted._set_qubits(qubits)
209231
remainder._set_qubits([q for q in self.qubits if q not in qubits])
@@ -214,6 +236,10 @@ def allows_factoring(self):
214236
"""Subclasses that allow factorization should override this."""
215237
return self._state.supports_factor if self._state is not None else False
216238

239+
@deprecated(
240+
deadline='v0.16',
241+
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
242+
)
217243
def _on_factor(
218244
self: TSelf,
219245
qubits: Sequence['cirq.Qid'],
@@ -247,10 +273,18 @@ def transpose_to_qubit_order(
247273
if self._state is not None:
248274
args._state = self._state.reindex(self.get_axes(qubits))
249275
else:
276+
_warn_or_error(
277+
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
278+
' overrides will be removed in cirq v0.16.'
279+
)
250280
self._on_transpose_to_qubit_order(qubits, args)
251281
args._set_qubits(qubits)
252282
return args
253283

284+
@deprecated(
285+
deadline='v0.16',
286+
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
287+
)
254288
def _on_transpose_to_qubit_order(self: TSelf, qubits: Sequence['cirq.Qid'], target: TSelf):
255289
"""Subclasses should implement this with any additional state transpose
256290
functionality, if supported."""

cirq-core/cirq/sim/act_on_args_container_test.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,40 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
from typing import Any, Dict, List, Optional, Sequence
14+
from typing import Any, Dict, Optional, Sequence
1515

1616
import cirq
1717

1818

19+
class EmptyQuantumState(cirq.QuantumStateRepresentation):
20+
def copy(self, deep_copy_buffers=True):
21+
return self
22+
23+
def measure(self, axes, seed=None):
24+
return [0] * len(axes)
25+
26+
@property
27+
def supports_factor(self):
28+
return True
29+
30+
def kron(self, other):
31+
return self
32+
33+
def factor(self, axes, *, validate=True, atol=1e-07):
34+
return self, self
35+
36+
def reindex(self, axes):
37+
return self
38+
39+
1940
class EmptyActOnArgs(cirq.ActOnArgs):
2041
def __init__(self, qubits, classical_data):
2142
super().__init__(
43+
state=EmptyQuantumState(),
2244
qubits=qubits,
2345
classical_data=classical_data,
2446
)
2547

26-
def _perform_measurement(self, qubits: Sequence[cirq.Qid]) -> List[int]:
27-
return [0] * len(qubits)
28-
2948
def _act_on_fallback_(
3049
self,
3150
action: Any,
@@ -34,10 +53,6 @@ def _act_on_fallback_(
3453
) -> bool:
3554
return True
3655

37-
@property
38-
def allows_factoring(self):
39-
return True
40-
4156

4257
q0, q1, q2 = qs3 = cirq.LineQubit.range(3)
4358
qs2 = cirq.LineQubit.range(2)

cirq-core/cirq/sim/act_on_args_test.py

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,21 @@
2020
from cirq.sim import act_on_args
2121

2222

23-
class DummyArgs(cirq.ActOnArgs):
24-
def __init__(self):
25-
super().__init__(qubits=cirq.LineQubit.range(2))
23+
class DummyQuantumState(cirq.QuantumStateRepresentation):
24+
def copy(self, deep_copy_buffers=True):
25+
pass
2626

27-
def _perform_measurement(self, qubits):
27+
def measure(self, axes, seed=None):
2828
return [5, 3]
2929

30+
def reindex(self, axes):
31+
return self
32+
33+
34+
class DummyArgs(cirq.ActOnArgs):
35+
def __init__(self):
36+
super().__init__(state=DummyQuantumState(), qubits=cirq.LineQubit.range(2))
37+
3038
def _act_on_fallback_(
3139
self,
3240
action: Any,
@@ -95,3 +103,49 @@ def test_field_getters():
95103
assert args.qubit_map == {q: i for i, q in enumerate(cirq.LineQubit.range(2))}
96104
with cirq.testing.assert_deprecated('always returns False', deadline='v0.16'):
97105
assert not args.ignore_measurement_results
106+
107+
108+
def test_on_methods_deprecated():
109+
class OldStyleArgs(cirq.ActOnArgs):
110+
def _act_on_fallback_(self, action, qubits, allow_decompose=True):
111+
pass
112+
113+
with cirq.testing.assert_deprecated('state', deadline='v0.16'):
114+
args = OldStyleArgs()
115+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
116+
_ = args.copy()
117+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
118+
_ = args.kronecker_product(args)
119+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
120+
_ = args.factor([])
121+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
122+
_ = args.transpose_to_qubit_order([])
123+
124+
125+
def test_on_methods_deprecated_if_implemented():
126+
class OldStyleArgs(cirq.ActOnArgs):
127+
def _act_on_fallback_(self, action, qubits, allow_decompose=True):
128+
pass
129+
130+
def _on_copy(self, args, deep_copy_buffers=True):
131+
pass
132+
133+
def _on_kronecker_product(self, other, target):
134+
pass
135+
136+
def _on_factor(self, qubits, extracted, remainder, validate=True, atol=1e-07):
137+
pass
138+
139+
def _on_transpose_to_qubit_order(self, qubits, target):
140+
pass
141+
142+
with cirq.testing.assert_deprecated('state', deadline='v0.16'):
143+
args = OldStyleArgs()
144+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
145+
_ = args.copy()
146+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
147+
_ = args.kronecker_product(args)
148+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
149+
_ = args.factor([])
150+
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
151+
_ = args.transpose_to_qubit_order([])

0 commit comments

Comments
 (0)