12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
- from typing import AbstractSet , Any , cast , Collection , Dict , Optional , Sequence , Tuple , Union
15
+ from typing import (
16
+ AbstractSet ,
17
+ Any ,
18
+ cast ,
19
+ Collection ,
20
+ Dict ,
21
+ List ,
22
+ Optional ,
23
+ Sequence ,
24
+ Tuple ,
25
+ Union ,
26
+ TYPE_CHECKING ,
27
+ )
16
28
17
29
import numpy as np
18
30
19
- import cirq
20
- from cirq import protocols , value
31
+ from cirq import protocols , value , _import
21
32
from cirq ._compat import deprecated
22
- from cirq .ops import raw_types , controlled_operation as cop
33
+ from cirq .ops import raw_types , controlled_operation as cop , matrix_gates
23
34
from cirq .type_workarounds import NotImplementedType
24
35
36
+ if TYPE_CHECKING :
37
+ import cirq
38
+
39
+ line_qubit = _import .LazyLoader ('line_qubit' , globals (), 'cirq.devices' )
40
+
25
41
26
42
@value .value_equality
27
43
class ControlledGate (raw_types .Gate ):
@@ -137,17 +153,21 @@ def num_controls(self) -> int:
137
153
return len (self .control_qid_shape )
138
154
139
155
def _qid_shape_ (self ) -> Tuple [int , ...]:
140
- return self .control_qid_shape + cirq .qid_shape (self .sub_gate )
156
+ return self .control_qid_shape + protocols .qid_shape (self .sub_gate )
141
157
142
158
def _decompose_ (self , qubits ):
159
+ if isinstance (self .sub_gate , matrix_gates .MatrixGate ):
160
+ # Default decompositions of 2/3 qubit `cirq.MatrixGate` ignores global phase, which is
161
+ # local phase in the controlled variant and hence cannot be ignored.
162
+ return NotImplemented
163
+
143
164
result = protocols .decompose_once_with_qubits (
144
165
self .sub_gate , qubits [self .num_controls () :], NotImplemented
145
166
)
146
-
147
167
if result is NotImplemented :
148
168
return NotImplemented
149
169
150
- decomposed = []
170
+ decomposed : List [ 'cirq.Operation' ] = []
151
171
for op in result :
152
172
decomposed .append (
153
173
cop .ControlledOperation (qubits [: self .num_controls ()], op , self .control_values )
@@ -172,7 +192,7 @@ def _value_equality_values_(self):
172
192
)
173
193
174
194
def _apply_unitary_ (self , args : 'protocols.ApplyUnitaryArgs' ) -> np .ndarray :
175
- qubits = cirq .LineQid .for_gate (self )
195
+ qubits = line_qubit .LineQid .for_gate (self )
176
196
op = self .sub_gate .on (* qubits [self .num_controls () :])
177
197
c_op = cop .ControlledOperation (qubits [: self .num_controls ()], op , self .control_values )
178
198
return protocols .apply_unitary (c_op , args , default = NotImplemented )
@@ -181,7 +201,7 @@ def _has_unitary_(self) -> bool:
181
201
return protocols .has_unitary (self .sub_gate )
182
202
183
203
def _unitary_ (self ) -> Union [np .ndarray , NotImplementedType ]:
184
- qubits = cirq .LineQid .for_gate (self )
204
+ qubits = line_qubit .LineQid .for_gate (self )
185
205
op = self .sub_gate .on (* qubits [self .num_controls () :])
186
206
c_op = cop .ControlledOperation (qubits [: self .num_controls ()], op , self .control_values )
187
207
@@ -191,7 +211,7 @@ def _has_mixture_(self) -> bool:
191
211
return protocols .has_mixture (self .sub_gate )
192
212
193
213
def _mixture_ (self ) -> Union [np .ndarray , NotImplementedType ]:
194
- qubits = cirq .LineQid .for_gate (self )
214
+ qubits = line_qubit .LineQid .for_gate (self )
195
215
op = self .sub_gate .on (* qubits [self .num_controls () :])
196
216
c_op = cop .ControlledOperation (qubits [: self .num_controls ()], op , self .control_values )
197
217
return protocols .mixture (c_op , default = NotImplemented )
0 commit comments