Skip to content

Commit

Permalink
Remove some 0.15 items from cirq.sim (#5137)
Browse files Browse the repository at this point in the history
This covers most of the deprecations for `cirq.sim` in 0.15. The two remaining ones have some challenges:

* Removing `target_tensor` etc from the initializers and replacing with `initial_state`: The repr still emits `target_tensor` so it wouldn't round-trip.
* Removing `log_of_measurement_results`: Same thing. Plus we forgot to deprecate it in a couple places.

Also this closes #3898, as the pattern we used to deprecate `copy` without parameters works well.
  • Loading branch information
daxfohl authored Apr 7, 2022
1 parent db5dc6e commit 51a2b6b
Show file tree
Hide file tree
Showing 22 changed files with 70 additions and 592 deletions.
6 changes: 0 additions & 6 deletions cirq-core/cirq/protocols/act_on_protocol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ def __init__(self, fallback_result: Any = NotImplemented, measurements=None):
def _perform_measurement(self, qubits):
return self.measurements # coverage: ignore

def copy(self, deep_copy_buffers: bool = True):
return DummyActOnArgs(self.fallback_result, self.measurements.copy()) # coverage: ignore

def _act_on_fallback_(
self,
action: Any,
Expand All @@ -42,9 +39,6 @@ def _act_on_fallback_(
):
return self.fallback_result

def sample(self, qubits, repetitions=1, seed=None):
pass


op = cirq.X(cirq.LineQubit(0))

Expand Down
58 changes: 7 additions & 51 deletions cirq-core/cirq/sim/act_on_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
# limitations under the License.
"""Objects and methods for acting efficiently on a state tensor."""
import copy
import inspect
import warnings
from typing import (
Any,
cast,
Expand All @@ -31,8 +29,8 @@

import numpy as np

from cirq import ops, protocols, value
from cirq._compat import deprecated, deprecated_parameter
from cirq import protocols, value
from cirq._compat import deprecated
from cirq.protocols.decompose_protocol import _try_decompose_into_operations_and_qubits
from cirq.sim.operation_target import OperationTarget

Expand All @@ -45,18 +43,11 @@
class ActOnArgs(OperationTarget[TSelf]):
"""State and context for an operation acting on a state tensor."""

@deprecated_parameter(
deadline='v0.15',
fix='Use cirq.dephase_measurements to transform the circuit before simulating.',
parameter_desc='ignore_measurement_results',
match=lambda args, kwargs: 'ignore_measurement_results' in kwargs or len(args) > 4,
)
def __init__(
self,
prng: Optional[np.random.RandomState] = None,
qubits: Optional[Sequence['cirq.Qid']] = None,
log_of_measurement_results: Optional[Dict[str, List[int]]] = None,
ignore_measurement_results: bool = False,
classical_data: Optional['cirq.ClassicalDataStore'] = None,
state: Optional['cirq.QuantumStateRepresentation'] = None,
):
Expand All @@ -70,10 +61,6 @@ def __init__(
ordering of the computational basis states.
log_of_measurement_results: A mutable object that measurements are
being recorded into.
ignore_measurement_results: If True, then the simulation
will treat measurement as dephasing instead of collapsing
process, and not log the result. This is only applicable to
simulators that can represent mixed states.
classical_data: The shared classical data container for this
simulation.
state: The underlying quantum state of the simulation.
Expand All @@ -90,7 +77,6 @@ def __init__(
for k, v in (log_of_measurement_results or {}).items()
}
)
self._ignore_measurement_results = ignore_measurement_results
self._state = state

@property
Expand All @@ -101,32 +87,14 @@ def prng(self) -> np.random.RandomState:
def qubit_map(self) -> Mapping['cirq.Qid', int]:
return self._qubit_map

@prng.setter # type: ignore
@deprecated(
deadline="v0.15",
fix="The mutators of this class are deprecated, instantiate a new object instead.",
)
def prng(self, prng):
self._prng = prng

@qubit_map.setter # type: ignore
@deprecated(
deadline="v0.15",
fix="The mutators of this class are deprecated, instantiate a new object instead.",
)
def qubit_map(self, qubit_map):
self._qubit_map = qubit_map

def _set_qubits(self, qubits: Sequence['cirq.Qid']):
self._qubits = tuple(qubits)
self._qubit_map = {q: i for i, q in enumerate(self.qubits)}

def measure(self, qubits: Sequence['cirq.Qid'], key: str, invert_mask: Sequence[bool]):
"""Measures the qubits and records to `log_of_measurement_results`.
Any bitmasks will be applied to the measurement record. If
`self._ignore_measurement_results` is set, it dephases instead of
measuring, and no measurement result will be logged.
Any bitmasks will be applied to the measurement record.
Args:
qubits: The qubits to measure.
Expand All @@ -138,9 +106,6 @@ def measure(self, qubits: Sequence['cirq.Qid'], key: str, invert_mask: Sequence[
Raises:
ValueError: If a measurement key has already been logged to a key.
"""
if self.ignore_measurement_results:
self._act_on_fallback_(ops.phase_damp(1), qubits)
return
bits = self._perform_measurement(qubits)
corrected = [bit ^ (bit < 2 and mask) for bit, mask in zip(bits, invert_mask)]
self._classical_data.record_measurement(
Expand Down Expand Up @@ -181,18 +146,8 @@ def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf:
args._classical_data = self._classical_data.copy()
if self._state is not None:
args._state = self._state.copy(deep_copy_buffers=deep_copy_buffers)
return args
if 'deep_copy_buffers' in inspect.signature(self._on_copy).parameters:
self._on_copy(args, deep_copy_buffers)
else:
warnings.warn(
(
'A new parameter deep_copy_buffers has been added to ActOnArgs._on_copy(). '
'The classes that inherit from ActOnArgs should support it before Cirq 0.15.'
),
DeprecationWarning,
)
self._on_copy(args)
self._on_copy(args, deep_copy_buffers)
return args

def _on_copy(self: TSelf, args: TSelf, deep_copy_buffers: bool = True):
Expand Down Expand Up @@ -304,9 +259,10 @@ def _on_transpose_to_qubit_order(self: TSelf, qubits: Sequence['cirq.Qid'], targ
def classical_data(self) -> 'cirq.ClassicalDataStoreReader':
return self._classical_data

@property
@property # type: ignore
@deprecated(deadline='v0.16', fix='Remove this call, it always returns False.')
def ignore_measurement_results(self) -> bool:
return self._ignore_measurement_results
return False

@property
def qubits(self) -> Tuple['cirq.Qid', ...]:
Expand Down
41 changes: 5 additions & 36 deletions cirq-core/cirq/sim/act_on_args_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import inspect
import warnings
from collections import abc
from typing import (
Any,
Expand All @@ -31,7 +29,7 @@
import numpy as np

from cirq import ops, protocols, value
from cirq._compat import deprecated, deprecated_parameter
from cirq._compat import deprecated_parameter
from cirq.sim.operation_target import OperationTarget
from cirq.sim.simulator import (
TActOnArgs,
Expand All @@ -51,7 +49,7 @@ class ActOnArgsContainer(
@deprecated_parameter(
deadline='v0.15',
fix='Use classical_data.',
parameter_desc='log_of_measurement_results and positional arguments',
parameter_desc='log_of_measurement_results',
match=lambda args, kwargs: 'log_of_measurement_results' in kwargs or len(args) > 4,
)
def __init__(
Expand Down Expand Up @@ -94,22 +92,6 @@ def args(self) -> Mapping[Optional['cirq.Qid'], TActOnArgs]:
def split_untangled_states(self) -> bool:
return self._split_untangled_states

@args.setter # type: ignore
@deprecated(
deadline="v0.15",
fix="The mutators of this class are deprecated, instantiate a new object instead.",
)
def args(self, args):
self._args = args

@split_untangled_states.setter # type: ignore
@deprecated(
deadline="v0.15",
fix="The mutators of this class are deprecated, instantiate a new object instead.",
)
def split_untangled_states(self, split_untangled_states):
self._split_untangled_states = split_untangled_states

def create_merged_state(self) -> TActOnArgs:
if not self.split_untangled_states:
return self.args[None]
Expand Down Expand Up @@ -169,11 +151,8 @@ def _act_on_fallback_(
protocols.act_on(action, op_args, act_on_qubits, allow_decompose=allow_decompose)

# Decouple any measurements or resets
if self.split_untangled_states and (
isinstance(gate_opt, ops.ResetChannel)
or (
isinstance(gate_opt, ops.MeasurementGate) and not op_args.ignore_measurement_results
)
if self.split_untangled_states and isinstance(
gate_opt, (ops.ResetChannel, ops.MeasurementGate)
):
for q in qubits:
if op_args.allows_factoring:
Expand All @@ -189,17 +168,7 @@ def copy(self, deep_copy_buffers: bool = True) -> 'cirq.ActOnArgsContainer[TActO
classical_data = self._classical_data.copy()
copies = {}
for act_on_args in set(self.args.values()):
if 'deep_copy_buffers' in inspect.signature(act_on_args.copy).parameters:
copies[act_on_args] = act_on_args.copy(deep_copy_buffers)
else:
warnings.warn(
(
'A new parameter deep_copy_buffers has been added to ActOnArgs.copy(). The '
'classes that inherit from ActOnArgs should support it before Cirq 0.15.'
),
DeprecationWarning,
)
copies[act_on_args] = act_on_args.copy()
copies[act_on_args] = act_on_args.copy(deep_copy_buffers)
for copy in copies.values():
copy._classical_data = classical_data
args = {q: copies[a] for q, a in self.args.items()}
Expand Down
21 changes: 0 additions & 21 deletions cirq-core/cirq/sim/act_on_args_container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ def __init__(self, qubits, classical_data):
def _perform_measurement(self, qubits: Sequence[cirq.Qid]) -> List[int]:
return [0] * len(qubits)

def copy(self) -> 'EmptyActOnArgs': # type: ignore
"""The deep_copy_buffers parameter is omitted to trigger a deprecation warning test."""
return EmptyActOnArgs(
qubits=self.qubits,
classical_data=self.classical_data.copy(),
)

def _act_on_fallback_(
self,
action: Any,
Expand Down Expand Up @@ -216,12 +209,6 @@ def test_copy_succeeds():
assert copied.qubits == (q0, q1)


def test_copy_deprecation_warning():
args = create_container(qs2, False)
with cirq.testing.assert_deprecated('deep_copy_buffers', deadline='0.15'):
args.copy(False)


def test_merge_succeeds():
args = create_container(qs2, False)
merged = args.create_merged_state()
Expand Down Expand Up @@ -273,11 +260,3 @@ def test_field_getters():
args = create_container(qs2)
assert args.args.keys() == set(qs2) | {None}
assert args.split_untangled_states


def test_field_setters_deprecated():
args = create_container(qs2)
with cirq.testing.assert_deprecated(deadline='v0.15'):
args.args = {}
with cirq.testing.assert_deprecated(deadline='v0.15'):
args.split_untangled_states = False
22 changes: 2 additions & 20 deletions cirq-core/cirq/sim/act_on_args_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ class DummyArgs(cirq.ActOnArgs):
def __init__(self):
super().__init__(qubits=cirq.LineQubit.range(2))

def sample(self, qubits, repetitions=1, seed=None):
pass

def _perform_measurement(self, qubits):
return [5, 3]

Expand All @@ -38,9 +35,6 @@ def _act_on_fallback_(
) -> bool:
return True

def _on_copy(self, args):
return super()._on_copy(args)


def test_measurements():
args = DummyArgs()
Expand Down Expand Up @@ -95,21 +89,9 @@ def test_transpose_qubits():
args.transpose_to_qubit_order((q0, q1, q1))


def test_on_copy_has_no_param():
args = DummyArgs()
with cirq.testing.assert_deprecated('deep_copy_buffers', deadline='0.15'):
args.copy(False)


def test_field_getters():
args = DummyArgs()
assert args.prng is np.random
assert args.qubit_map == {q: i for i, q in enumerate(cirq.LineQubit.range(2))}


def test_field_setters_deprecated():
args = DummyArgs()
with cirq.testing.assert_deprecated(deadline='v0.15'):
args.prng = 0
with cirq.testing.assert_deprecated(deadline='v0.15'):
args.qubit_map = {}
with cirq.testing.assert_deprecated('always returns False', deadline='v0.16'):
assert not args.ignore_measurement_results
44 changes: 12 additions & 32 deletions cirq-core/cirq/sim/act_on_density_matrix_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,30 +242,24 @@ class ActOnDensityMatrixArgs(ActOnArgs):
@_compat.deprecated_parameter(
deadline='v0.15',
fix='Use classical_data.',
parameter_desc='log_of_measurement_results and positional arguments',
parameter_desc='log_of_measurement_results',
match=lambda args, kwargs: 'log_of_measurement_results' in kwargs or len(args) > 5,
)
@_compat.deprecated_parameter(
deadline='v0.15',
fix='Use cirq.dephase_measurements to transform the circuit before simulating.',
parameter_desc='ignore_measurement_results',
match=lambda args, kwargs: 'ignore_measurement_results' in kwargs or len(args) > 7,
)
@_compat.deprecated_parameter(
deadline='v0.15',
fix='Use initial_state instead and specify all the arguments with keywords.',
parameter_desc='target_tensor and positional arguments',
match=lambda args, kwargs: 'target_tensor' in kwargs or len(args) != 1,
fix='Use initial_state instead.',
parameter_desc='target_tensor',
match=lambda args, kwargs: 'target_tensor' in kwargs,
)
def __init__(
self,
*,
target_tensor: Optional[np.ndarray] = None,
available_buffer: Optional[List[np.ndarray]] = None,
qid_shape: Optional[Tuple[int, ...]] = None,
prng: Optional[np.random.RandomState] = None,
log_of_measurement_results: Optional[Dict[str, List[int]]] = None,
qubits: Optional[Sequence['cirq.Qid']] = None,
ignore_measurement_results: bool = False,
initial_state: Union[np.ndarray, 'cirq.STATE_VECTOR_LIKE'] = 0,
dtype: Type[np.number] = np.complex64,
classical_data: Optional['cirq.ClassicalDataStore'] = None,
Expand All @@ -288,10 +282,6 @@ def __init__(
effects.
log_of_measurement_results: A mutable object that measurements are
being recorded into.
ignore_measurement_results: If True, then the simulation
will treat measurement as dephasing instead of collapsing
process. This is only applicable to simulators that can
model dephasing.
initial_state: The initial state for the simulation in the
computational basis.
dtype: The `numpy.dtype` of the inferred state vector. One of
Expand All @@ -310,23 +300,13 @@ def __init__(
dtype=dtype,
buffer=available_buffer,
)
if ignore_measurement_results:
super().__init__(
state=state,
prng=prng,
qubits=qubits,
log_of_measurement_results=log_of_measurement_results,
ignore_measurement_results=ignore_measurement_results,
classical_data=classical_data,
)
else:
super().__init__(
state=state,
prng=prng,
qubits=qubits,
log_of_measurement_results=log_of_measurement_results,
classical_data=classical_data,
)
super().__init__(
state=state,
prng=prng,
qubits=qubits,
log_of_measurement_results=log_of_measurement_results,
classical_data=classical_data,
)
self._state: _BufferedDensityMatrix = state

def _act_on_fallback_(
Expand Down
Loading

0 comments on commit 51a2b6b

Please sign in to comment.