1# Copyright 2021 The Cirq Developers
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""An interface for quantum states as targets for operations."""
15import abc
16from typing import (
17    TypeVar,
18    TYPE_CHECKING,
19    Generic,
20    Dict,
21    Any,
22    Tuple,
23    Optional,
24    Iterator,
25    List,
26    Sequence,
27    Union,
28)
29
30import numpy as np
31
32from cirq import protocols
33from cirq.type_workarounds import NotImplementedType
34
35if TYPE_CHECKING:
36    import cirq
37
38
39TSelfTarget = TypeVar('TSelfTarget', bound='OperationTarget')
40TActOnArgs = TypeVar('TActOnArgs', bound='cirq.ActOnArgs')
41
42
43class OperationTarget(Generic[TActOnArgs], metaclass=abc.ABCMeta):
44    """An interface for quantum states as targets for operations."""
45
46    @abc.abstractmethod
47    def create_merged_state(self) -> TActOnArgs:
48        """Creates a final merged state."""
49
50    @abc.abstractmethod
51    def _act_on_fallback_(
52        self,
53        action: Union['cirq.Operation', 'cirq.Gate'],
54        qubits: Sequence['cirq.Qid'],
55        allow_decompose: bool = True,
56    ) -> Union[bool, NotImplementedType]:
57        """Handles the act_on protocol fallback implementation.
58
59        Args:
60            action: Either a gate or an operation to act on.
61            qubits: The applicable qubits if a gate is passed as the action.
62            allow_decompose: Flag to allow decomposition.
63
64        Returns:
65            True if the fallback applies, else NotImplemented."""
66
67    def apply_operation(self, op: 'cirq.Operation'):
68        protocols.act_on(op, self)
69
70    @abc.abstractmethod
71    def copy(self: TSelfTarget) -> TSelfTarget:
72        """Copies the object."""
73
74    @property
75    @abc.abstractmethod
76    def qubits(self) -> Tuple['cirq.Qid', ...]:
77        """Gets the qubit order maintained by this target."""
78
79    @property
80    @abc.abstractmethod
81    def log_of_measurement_results(self) -> Dict[str, Any]:
82        """Gets the log of measurement results."""
83
84    @abc.abstractmethod
85    def sample(
86        self,
87        qubits: List['cirq.Qid'],
88        repetitions: int = 1,
89        seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
90    ) -> np.ndarray:
91        """Samples the state value."""
92
93    def __getitem__(self, item: Optional['cirq.Qid']) -> TActOnArgs:
94        """Gets the item associated with the qubit."""
95
96    def __len__(self) -> int:
97        """Gets the number of items in the mapping."""
98
99    def __iter__(self) -> Iterator[Optional['cirq.Qid']]:
100        """Iterates the keys of the mapping."""
101