|
28 | 28 | )
|
29 | 29 |
|
30 | 30 | from cirq import ops, value
|
31 |
| -from cirq._compat import deprecated_class |
32 | 31 | from cirq.interop.quirk.cells.cell import Cell, CellMaker, CELL_SIZES
|
33 | 32 |
|
34 | 33 | if TYPE_CHECKING:
|
35 | 34 | import cirq
|
36 | 35 |
|
37 | 36 |
|
38 |
| -@deprecated_class(deadline='v0.16', fix='Use cirq.QuirkArithmeticGate') |
39 |
| -@value.value_equality |
40 |
| -class QuirkArithmeticOperation(ops.ArithmeticOperation): |
41 |
| - """Applies arithmetic to a target and some inputs. |
42 |
| -
|
43 |
| - Implements Quirk-specific implicit effects like assuming that the presence |
44 |
| - of an 'r' input implies modular arithmetic. |
45 |
| -
|
46 |
| - In Quirk, modular operations have no effect on values larger than the |
47 |
| - modulus. This convention is used because unitarity forces *some* convention |
48 |
| - on out-of-range values (they cannot simply disappear or raise exceptions), |
49 |
| - and the simplest is to do nothing. This call handles ensuring that happens, |
50 |
| - and ensuring the new target register value is normalized modulo the modulus. |
51 |
| - """ |
52 |
| - |
53 |
| - def __init__( |
54 |
| - self, |
55 |
| - identifier: str, |
56 |
| - target: Sequence['cirq.Qid'], |
57 |
| - inputs: Sequence[Union[Sequence['cirq.Qid'], int]], |
58 |
| - ): |
59 |
| - """Inits QuirkArithmeticOperation. |
60 |
| -
|
61 |
| - Args: |
62 |
| - identifier: The quirk identifier string for this operation. |
63 |
| - target: The target qubit register. |
64 |
| - inputs: Qubit registers (or classical constants) that |
65 |
| - determine what happens to the target. |
66 |
| -
|
67 |
| - Raises: |
68 |
| - ValueError: If given overlapping registers, or the target is too |
69 |
| - small for a modular operation with too small modulus. |
70 |
| - """ |
71 |
| - self.identifier = identifier |
72 |
| - self.target: Tuple['cirq.Qid', ...] = tuple(target) |
73 |
| - self.inputs: Tuple[Union[Sequence['cirq.Qid'], int], ...] = tuple( |
74 |
| - e if isinstance(e, int) else tuple(e) for e in inputs |
75 |
| - ) |
76 |
| - |
77 |
| - for input_register in self.inputs: |
78 |
| - if isinstance(input_register, int): |
79 |
| - continue |
80 |
| - if set(self.target) & set(input_register): |
81 |
| - raise ValueError(f'Overlapping registers: {self.target} {self.inputs}') |
82 |
| - |
83 |
| - if self.operation.is_modular: |
84 |
| - r = inputs[-1] |
85 |
| - if isinstance(r, int): |
86 |
| - over = r > 1 << len(target) |
87 |
| - else: |
88 |
| - over = len(cast(Sequence, r)) > len(target) |
89 |
| - if over: |
90 |
| - raise ValueError(f'Target too small for modulus.\nTarget: {target}\nModulus: {r}') |
91 |
| - |
92 |
| - @property |
93 |
| - def operation(self) -> '_QuirkArithmeticCallable': |
94 |
| - return ARITHMETIC_OP_TABLE[self.identifier] |
95 |
| - |
96 |
| - def _value_equality_values_(self) -> Any: |
97 |
| - return self.identifier, self.target, self.inputs |
98 |
| - |
99 |
| - def registers(self) -> Sequence[Union[int, Sequence['cirq.Qid']]]: |
100 |
| - return [self.target, *self.inputs] |
101 |
| - |
102 |
| - def with_registers( |
103 |
| - self, *new_registers: Union[int, Sequence['cirq.Qid']] |
104 |
| - ) -> 'QuirkArithmeticOperation': |
105 |
| - if len(new_registers) != len(self.inputs) + 1: |
106 |
| - raise ValueError( |
107 |
| - 'Wrong number of registers.\n' |
108 |
| - f'New registers: {repr(new_registers)}\n' |
109 |
| - f'Operation: {repr(self)}' |
110 |
| - ) |
111 |
| - |
112 |
| - if isinstance(new_registers[0], int): |
113 |
| - raise ValueError( |
114 |
| - 'The first register is the mutable target. ' |
115 |
| - 'It must be a list of qubits, not the constant ' |
116 |
| - f'{new_registers[0]}.' |
117 |
| - ) |
118 |
| - |
119 |
| - return QuirkArithmeticOperation(self.identifier, new_registers[0], new_registers[1:]) |
120 |
| - |
121 |
| - def apply(self, *registers: int) -> Union[int, Iterable[int]]: |
122 |
| - return self.operation(*registers) |
123 |
| - |
124 |
| - def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> List[str]: |
125 |
| - lettered_args = list(zip(self.operation.letters, self.inputs)) |
126 |
| - |
127 |
| - result: List[str] = [] |
128 |
| - |
129 |
| - # Target register labels. |
130 |
| - consts = ''.join( |
131 |
| - f',{letter}={reg}' for letter, reg in lettered_args if isinstance(reg, int) |
132 |
| - ) |
133 |
| - result.append(f'Quirk({self.identifier}{consts})') |
134 |
| - result.extend(f'#{i}' for i in range(2, len(self.target) + 1)) |
135 |
| - |
136 |
| - # Input register labels. |
137 |
| - for letter, reg in lettered_args: |
138 |
| - if not isinstance(reg, int): |
139 |
| - result.extend(f'{letter.upper()}{i}' for i in range(len(cast(Sequence, reg)))) |
140 |
| - |
141 |
| - return result |
142 |
| - |
143 |
| - def __repr__(self) -> str: |
144 |
| - return ( |
145 |
| - 'cirq.interop.quirk.QuirkArithmeticOperation(\n' |
146 |
| - f' {repr(self.identifier)},\n' |
147 |
| - f' target={repr(self.target)},\n' |
148 |
| - f' inputs={_indented_list_lines_repr(self.inputs)},\n' |
149 |
| - ')' |
150 |
| - ) |
151 |
| - |
152 |
| - |
153 | 37 | @value.value_equality
|
154 | 38 | class QuirkArithmeticGate(ops.ArithmeticGate):
|
155 | 39 | """Applies arithmetic to a target and some inputs.
|
|
0 commit comments