|
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