From 4ff8aee85e563d3e4b5b5469e40d2e718b71db65 Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 16 Jun 2022 10:55:00 -0700 Subject: [PATCH] Move QuantumStateRepresentation to its own file Fixes: #5475 --- cirq-core/cirq/qis/__init__.py | 4 +- cirq-core/cirq/qis/clifford_tableau.py | 89 ++------------- .../cirq/qis/quantum_state_representation.py | 102 ++++++++++++++++++ 3 files changed, 111 insertions(+), 84 deletions(-) create mode 100644 cirq-core/cirq/qis/quantum_state_representation.py diff --git a/cirq-core/cirq/qis/__init__.py b/cirq-core/cirq/qis/__init__.py index 9fbed5de10f..b2b8b0e4fcb 100644 --- a/cirq-core/cirq/qis/__init__.py +++ b/cirq-core/cirq/qis/__init__.py @@ -25,10 +25,12 @@ superoperator_to_kraus, ) -from cirq.qis.clifford_tableau import CliffordTableau, QuantumStateRepresentation, StabilizerState +from cirq.qis.clifford_tableau import CliffordTableau, StabilizerState from cirq.qis.measures import entanglement_fidelity, fidelity, von_neumann_entropy +from cirq.qis.quantum_state_representation import QuantumStateRepresentation + from cirq.qis.states import ( bloch_vector_from_state_vector, density_matrix, diff --git a/cirq-core/cirq/qis/clifford_tableau.py b/cirq-core/cirq/qis/clifford_tableau.py index 7372058ceaf..f88d43d521c 100644 --- a/cirq-core/cirq/qis/clifford_tableau.py +++ b/cirq-core/cirq/qis/clifford_tableau.py @@ -13,97 +13,20 @@ # limitations under the License. import abc -from typing import Any, Dict, List, Sequence, Tuple, TYPE_CHECKING, TypeVar +from typing import Any, Dict, List, Sequence, TYPE_CHECKING import numpy as np -from cirq import protocols, value +from cirq import protocols +from cirq.qis import quantum_state_representation from cirq.value import big_endian_int_to_digits, linear_dict if TYPE_CHECKING: import cirq -TSelf = TypeVar('TSelf', bound='QuantumStateRepresentation') - -class QuantumStateRepresentation(metaclass=abc.ABCMeta): - @abc.abstractmethod - def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf: - """Creates a copy of the object. - Args: - deep_copy_buffers: If True, buffers will also be deep-copied. - Otherwise the copy will share a reference to the original object's - buffers. - Returns: - A copied instance. - """ - - @abc.abstractmethod - def measure( - self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None - ) -> List[int]: - """Measures the state. - - Args: - axes: The axes to measure. - seed: The random number seed to use. - Returns: - The measurements in order. - """ - - def sample( - self, - axes: Sequence[int], - repetitions: int = 1, - seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, - ) -> np.ndarray: - """Samples the state. Subclasses can override with more performant method. - - Args: - axes: The axes to sample. - repetitions: The number of samples to make. - seed: The random number seed to use. - Returns: - The samples in order. - """ - prng = value.parse_random_state(seed) - measurements = [] - for _ in range(repetitions): - state = self.copy() - measurements.append(state.measure(axes, prng)) - return np.array(measurements, dtype=np.uint8) - - def kron(self: TSelf, other: TSelf) -> TSelf: - """Joins two state spaces together.""" - raise NotImplementedError() - - def factor( - self: TSelf, axes: Sequence[int], *, validate=True, atol=1e-07 - ) -> Tuple[TSelf, TSelf]: - """Splits two state spaces after a measurement or reset.""" - raise NotImplementedError() - - def reindex(self: TSelf, axes: Sequence[int]) -> TSelf: - """Physically reindexes the state by the new basis. - Args: - axes: The desired axis order. - Returns: - The state with qubit order transposed and underlying representation - updated. - """ - raise NotImplementedError() - - @property - def supports_factor(self) -> bool: - """Subclasses that allow factorization should override this.""" - return False - - @property - def can_represent_mixed_states(self) -> bool: - """Subclasses that can represent mixed states should override this.""" - return False - - -class StabilizerState(QuantumStateRepresentation, metaclass=abc.ABCMeta): +class StabilizerState( + quantum_state_representation.QuantumStateRepresentation, metaclass=abc.ABCMeta +): """Interface for quantum stabilizer state representations. This interface is used for CliffordTableau and StabilizerChForm quantum diff --git a/cirq-core/cirq/qis/quantum_state_representation.py b/cirq-core/cirq/qis/quantum_state_representation.py new file mode 100644 index 00000000000..b2f6587adea --- /dev/null +++ b/cirq-core/cirq/qis/quantum_state_representation.py @@ -0,0 +1,102 @@ +# Copyright 2022 The Cirq Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + +import abc +from typing import List, Sequence, Tuple, TYPE_CHECKING, TypeVar +import numpy as np + +from cirq import value + +if TYPE_CHECKING: + import cirq + +TSelf = TypeVar('TSelf', bound='QuantumStateRepresentation') + + +class QuantumStateRepresentation(metaclass=abc.ABCMeta): + @abc.abstractmethod + def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf: + """Creates a copy of the object. + Args: + deep_copy_buffers: If True, buffers will also be deep-copied. + Otherwise the copy will share a reference to the original object's + buffers. + Returns: + A copied instance. + """ + + @abc.abstractmethod + def measure( + self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None + ) -> List[int]: + """Measures the state. + + Args: + axes: The axes to measure. + seed: The random number seed to use. + Returns: + The measurements in order. + """ + + def sample( + self, + axes: Sequence[int], + repetitions: int = 1, + seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, + ) -> np.ndarray: + """Samples the state. Subclasses can override with more performant method. + + Args: + axes: The axes to sample. + repetitions: The number of samples to make. + seed: The random number seed to use. + Returns: + The samples in order. + """ + prng = value.parse_random_state(seed) + measurements = [] + for _ in range(repetitions): + state = self.copy() + measurements.append(state.measure(axes, prng)) + return np.array(measurements, dtype=np.uint8) + + def kron(self: TSelf, other: TSelf) -> TSelf: + """Joins two state spaces together.""" + raise NotImplementedError() + + def factor( + self: TSelf, axes: Sequence[int], *, validate=True, atol=1e-07 + ) -> Tuple[TSelf, TSelf]: + """Splits two state spaces after a measurement or reset.""" + raise NotImplementedError() + + def reindex(self: TSelf, axes: Sequence[int]) -> TSelf: + """Physically reindexes the state by the new basis. + Args: + axes: The desired axis order. + Returns: + The state with qubit order transposed and underlying representation + updated. + """ + raise NotImplementedError() + + @property + def supports_factor(self) -> bool: + """Subclasses that allow factorization should override this.""" + return False + + @property + def can_represent_mixed_states(self) -> bool: + """Subclasses that can represent mixed states should override this.""" + return False