Skip to content

Commit

Permalink
Deprecate the ActOnArgs._on_* methods (quantumlib#5224)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
daxfohl authored and tonybruguier committed Apr 19, 2022
1 parent 529c1ef commit 78caf84
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 21 deletions.
18 changes: 10 additions & 8 deletions cirq-core/cirq/protocols/act_on_protocol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@
from cirq.ops.raw_types import TSelf


class DummyQuantumState(cirq.QuantumStateRepresentation):
def copy(self, deep_copy_buffers=True):
pass

def measure(self, axes, seed=None):
pass


class DummyActOnArgs(cirq.ActOnArgs):
def __init__(self, fallback_result: Any = NotImplemented, measurements=None):
super().__init__(np.random.RandomState())
if measurements is None:
measurements = []
self.measurements = measurements
def __init__(self, fallback_result: Any = NotImplemented):
super().__init__(np.random.RandomState(), state=DummyQuantumState())
self.fallback_result = fallback_result

def _perform_measurement(self, qubits):
return self.measurements # coverage: ignore

def _act_on_fallback_(
self,
action: Any,
Expand Down
36 changes: 35 additions & 1 deletion cirq-core/cirq/sim/act_on_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import numpy as np

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

Expand Down Expand Up @@ -78,6 +78,8 @@ def __init__(
}
)
self._state = state
if state is None:
_warn_or_error('This function will require a valid `state` input in cirq v0.16.')

@property
def prng(self) -> np.random.RandomState:
Expand Down Expand Up @@ -147,9 +149,17 @@ def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf:
if self._state is not None:
args._state = self._state.copy(deep_copy_buffers=deep_copy_buffers)
else:
_warn_or_error(
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
' overrides will be removed in cirq v0.16.'
)
self._on_copy(args, deep_copy_buffers)
return args

@deprecated(
deadline='v0.16',
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
)
def _on_copy(self: TSelf, args: TSelf, deep_copy_buffers: bool = True):
"""Subclasses should implement this with any additional state copy
functionality."""
Expand All @@ -164,10 +174,18 @@ def kronecker_product(self: TSelf, other: TSelf, *, inplace=False) -> TSelf:
if self._state is not None and other._state is not None:
args._state = self._state.kron(other._state)
else:
_warn_or_error(
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
' overrides will be removed in cirq v0.16.'
)
self._on_kronecker_product(other, args)
args._set_qubits(self.qubits + other.qubits)
return args

@deprecated(
deadline='v0.16',
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
)
def _on_kronecker_product(self: TSelf, other: TSelf, target: TSelf):
"""Subclasses should implement this with any additional state product
functionality, if supported."""
Expand Down Expand Up @@ -204,6 +222,10 @@ def factor(
extracted._state = e
remainder._state = r
else:
_warn_or_error(
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
' overrides will be removed in cirq v0.16.'
)
self._on_factor(qubits, extracted, remainder, validate, atol)
extracted._set_qubits(qubits)
remainder._set_qubits([q for q in self.qubits if q not in qubits])
Expand All @@ -214,6 +236,10 @@ def allows_factoring(self):
"""Subclasses that allow factorization should override this."""
return self._state.supports_factor if self._state is not None else False

@deprecated(
deadline='v0.16',
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
)
def _on_factor(
self: TSelf,
qubits: Sequence['cirq.Qid'],
Expand Down Expand Up @@ -247,10 +273,18 @@ def transpose_to_qubit_order(
if self._state is not None:
args._state = self._state.reindex(self.get_axes(qubits))
else:
_warn_or_error(
'Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor. The `_on_`'
' overrides will be removed in cirq v0.16.'
)
self._on_transpose_to_qubit_order(qubits, args)
args._set_qubits(qubits)
return args

@deprecated(
deadline='v0.16',
fix='Pass a `QuantumStateRepresentation` into the `ActOnArgs` constructor.',
)
def _on_transpose_to_qubit_order(self: TSelf, qubits: Sequence['cirq.Qid'], target: TSelf):
"""Subclasses should implement this with any additional state transpose
functionality, if supported."""
Expand Down
31 changes: 23 additions & 8 deletions cirq-core/cirq/sim/act_on_args_container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,40 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Dict, List, Optional, Sequence
from typing import Any, Dict, Optional, Sequence

import cirq


class EmptyQuantumState(cirq.QuantumStateRepresentation):
def copy(self, deep_copy_buffers=True):
return self

def measure(self, axes, seed=None):
return [0] * len(axes)

@property
def supports_factor(self):
return True

def kron(self, other):
return self

def factor(self, axes, *, validate=True, atol=1e-07):
return self, self

def reindex(self, axes):
return self


class EmptyActOnArgs(cirq.ActOnArgs):
def __init__(self, qubits, classical_data):
super().__init__(
state=EmptyQuantumState(),
qubits=qubits,
classical_data=classical_data,
)

def _perform_measurement(self, qubits: Sequence[cirq.Qid]) -> List[int]:
return [0] * len(qubits)

def _act_on_fallback_(
self,
action: Any,
Expand All @@ -34,10 +53,6 @@ def _act_on_fallback_(
) -> bool:
return True

@property
def allows_factoring(self):
return True


q0, q1, q2 = qs3 = cirq.LineQubit.range(3)
qs2 = cirq.LineQubit.range(2)
Expand Down
62 changes: 58 additions & 4 deletions cirq-core/cirq/sim/act_on_args_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@
from cirq.sim import act_on_args


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

def _perform_measurement(self, qubits):
def measure(self, axes, seed=None):
return [5, 3]

def reindex(self, axes):
return self


class DummyArgs(cirq.ActOnArgs):
def __init__(self):
super().__init__(state=DummyQuantumState(), qubits=cirq.LineQubit.range(2))

def _act_on_fallback_(
self,
action: Any,
Expand Down Expand Up @@ -95,3 +103,49 @@ def test_field_getters():
assert args.qubit_map == {q: i for i, q in enumerate(cirq.LineQubit.range(2))}
with cirq.testing.assert_deprecated('always returns False', deadline='v0.16'):
assert not args.ignore_measurement_results


def test_on_methods_deprecated():
class OldStyleArgs(cirq.ActOnArgs):
def _act_on_fallback_(self, action, qubits, allow_decompose=True):
pass

with cirq.testing.assert_deprecated('state', deadline='v0.16'):
args = OldStyleArgs()
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
_ = args.copy()
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
_ = args.kronecker_product(args)
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
_ = args.factor([])
with cirq.testing.assert_deprecated('_on_', deadline='v0.16', count=2):
_ = args.transpose_to_qubit_order([])


def test_on_methods_deprecated_if_implemented():
class OldStyleArgs(cirq.ActOnArgs):
def _act_on_fallback_(self, action, qubits, allow_decompose=True):
pass

def _on_copy(self, args, deep_copy_buffers=True):
pass

def _on_kronecker_product(self, other, target):
pass

def _on_factor(self, qubits, extracted, remainder, validate=True, atol=1e-07):
pass

def _on_transpose_to_qubit_order(self, qubits, target):
pass

with cirq.testing.assert_deprecated('state', deadline='v0.16'):
args = OldStyleArgs()
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
_ = args.copy()
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
_ = args.kronecker_product(args)
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
_ = args.factor([])
with cirq.testing.assert_deprecated('_on_', deadline='v0.16'):
_ = args.transpose_to_qubit_order([])

0 comments on commit 78caf84

Please sign in to comment.