@@ -42,61 +42,26 @@ def _act_on_fallback_(
42
42
) -> bool :
43
43
return True
44
44
45
-
46
- class AncillaZ (cirq .Gate ):
47
- def __init__ (self , exponent = 1 ):
48
- self ._exponent = exponent
49
-
50
- def num_qubits (self ) -> int :
51
- return 1
52
-
53
- def _decompose_ (self , qubits ):
54
- ancilla = cirq .NamedQubit ('Ancilla' )
55
- yield cirq .CX (qubits [0 ], ancilla )
56
- yield cirq .Z (ancilla ) ** self ._exponent
57
- yield cirq .CX (qubits [0 ], ancilla )
58
-
59
-
60
- class AncillaH (cirq .Gate ):
61
- def __init__ (self , exponent = 1 ):
62
- self ._exponent = exponent
63
-
64
- def num_qubits (self ) -> int :
65
- return 1
66
-
67
- def _decompose_ (self , qubits ):
68
- ancilla = cirq .NamedQubit ('Ancilla' )
69
- yield cirq .H (ancilla ) ** self ._exponent
70
- yield cirq .CX (ancilla , qubits [0 ])
71
- yield cirq .H (ancilla ) ** self ._exponent
72
-
73
-
74
- class AncillaY (cirq .Gate ):
75
- def __init__ (self , exponent = 1 ):
76
- self ._exponent = exponent
77
-
78
- def num_qubits (self ) -> int :
79
- return 1
80
-
81
- def _decompose_ (self , qubits ):
82
- ancilla = cirq .NamedQubit ('Ancilla' )
83
- yield cirq .Y (ancilla ) ** self ._exponent
84
- yield cirq .CX (ancilla , qubits [0 ])
85
- yield cirq .Y (ancilla ) ** self ._exponent
45
+ def add_qubits (self , qubits ):
46
+ ret = super ().add_qubits (qubits )
47
+ return self if NotImplemented else ret
86
48
87
49
88
50
class DelegatingAncillaZ (cirq .Gate ):
89
- def __init__ (self , exponent = 1 ):
51
+ def __init__ (self , exponent = 1 , measure_ancilla : bool = False ):
90
52
self ._exponent = exponent
53
+ self ._measure_ancilla = measure_ancilla
91
54
92
55
def num_qubits (self ) -> int :
93
56
return 1
94
57
95
58
def _decompose_ (self , qubits ):
96
59
a = cirq .NamedQubit ('a' )
97
60
yield cirq .CX (qubits [0 ], a )
98
- yield AncillaZ (self ._exponent ).on (a )
61
+ yield PhaseUsingCleanAncilla (self ._exponent ).on (a )
99
62
yield cirq .CX (qubits [0 ], a )
63
+ if self ._measure_ancilla :
64
+ yield cirq .measure (a )
100
65
101
66
102
67
class Composite (cirq .Gate ):
@@ -115,12 +80,23 @@ def test_measurements():
115
80
116
81
def test_decompose ():
117
82
args = DummySimulationState ()
118
- assert (
119
- simulation_state .strat_act_on_from_apply_decompose (Composite (), args , [cirq .LineQubit (0 )])
120
- is NotImplemented
83
+ assert simulation_state .strat_act_on_from_apply_decompose (
84
+ Composite (), args , [cirq .LineQubit (0 )]
121
85
)
122
86
123
87
88
+ def test_decompose_for_gate_allocating_qubits_raises ():
89
+ class Composite (cirq .testing .SingleQubitGate ):
90
+ def _decompose_ (self , qubits ):
91
+ anc = cirq .NamedQubit ("anc" )
92
+ yield cirq .CNOT (* qubits , anc )
93
+
94
+ args = DummySimulationState ()
95
+
96
+ with pytest .raises (TypeError , match = "add_qubits but not remove_qubits" ):
97
+ simulation_state .strat_act_on_from_apply_decompose (Composite (), args , [cirq .LineQubit (0 )])
98
+
99
+
124
100
def test_mapping ():
125
101
args = DummySimulationState ()
126
102
assert list (iter (args )) == cirq .LineQubit .range (2 )
@@ -162,53 +138,35 @@ def test_field_getters():
162
138
assert args .qubit_map == {q : i for i , q in enumerate (cirq .LineQubit .range (2 ))}
163
139
164
140
165
- @pytest .mark .parametrize ('exp' , [- 3 , - 2 , - 1 , 0 , 1 , 2 , 3 ])
166
- def test_ancilla_z (exp ):
167
- q = cirq .LineQubit (0 )
168
- test_circuit = cirq .Circuit (AncillaZ (exp ).on (q ))
169
-
170
- control_circuit = cirq .Circuit (cirq .ZPowGate (exponent = exp ).on (q ))
171
-
172
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
173
-
174
-
175
- @pytest .mark .parametrize ('exp' , [- 3 , - 2 , - 1 , 0 , 1 , 2 , 3 ])
176
- def test_ancilla_y (exp ):
141
+ @pytest .mark .parametrize ('exp' , np .linspace (0 , 2 * np .pi , 10 ))
142
+ def test_delegating_gate_unitary (exp ):
177
143
q = cirq .LineQubit (0 )
178
- test_circuit = cirq .Circuit (AncillaY (exp ).on (q ))
179
-
180
- control_circuit = cirq .Circuit (cirq .Y (q ))
181
- control_circuit .append (cirq .Y (q ))
182
- control_circuit .append (cirq .XPowGate (exponent = exp ).on (q ))
183
-
184
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
185
144
186
-
187
- @pytest .mark .parametrize ('exp' , [- 3 , - 2 , - 1 , 0 , 1 , 2 , 3 ])
188
- def test_borrowable_qubit (exp ):
189
- q = cirq .LineQubit (0 )
190
145
test_circuit = cirq .Circuit ()
191
146
test_circuit .append (cirq .H (q ))
192
- test_circuit .append (cirq .X (q ))
193
- test_circuit .append (AncillaH (exp ).on (q ))
147
+ test_circuit .append (DelegatingAncillaZ (exp ).on (q ))
194
148
195
149
control_circuit = cirq .Circuit (cirq .H (q ))
150
+ control_circuit .append (cirq .ZPowGate (exponent = exp ).on (q ))
196
151
197
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
152
+ assert_test_circuit_for_dm_simulator (test_circuit , control_circuit )
153
+ assert_test_circuit_for_sv_simulator (test_circuit , control_circuit )
198
154
199
155
200
- @pytest .mark .parametrize ('exp' , [ - 3 , - 2 , - 1 , 0 , 1 , 2 , 3 ] )
201
- def test_delegating_gate_qubit (exp ):
156
+ @pytest .mark .parametrize ('exp' , np . linspace ( 0 , 2 * np . pi , 10 ) )
157
+ def test_delegating_gate_channel (exp ):
202
158
q = cirq .LineQubit (0 )
203
159
204
160
test_circuit = cirq .Circuit ()
205
161
test_circuit .append (cirq .H (q ))
206
- test_circuit .append (DelegatingAncillaZ (exp ).on (q ))
162
+ test_circuit .append (DelegatingAncillaZ (exp , True ).on (q ))
207
163
208
164
control_circuit = cirq .Circuit (cirq .H (q ))
209
165
control_circuit .append (cirq .ZPowGate (exponent = exp ).on (q ))
210
166
211
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
167
+ with pytest .raises (TypeError , match = "DensityMatrixSimulator doesn't support" ):
168
+ # TODO: This test should pass once we extend support to DensityMatrixSimulator.
169
+ assert_test_circuit_for_dm_simulator (test_circuit , control_circuit )
212
170
213
171
214
172
@pytest .mark .parametrize ('num_ancilla' , [1 , 2 , 3 ])
@@ -221,7 +179,8 @@ def test_phase_using_dirty_ancilla(num_ancilla: int):
221
179
u .on (q , * anc ), PhaseUsingDirtyAncilla (ancilla_bitsize = num_ancilla ).on (q )
222
180
)
223
181
control_circuit = cirq .Circuit (u .on (q , * anc ), cirq .Z (q ))
224
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
182
+ assert_test_circuit_for_dm_simulator (test_circuit , control_circuit )
183
+ assert_test_circuit_for_sv_simulator (test_circuit , control_circuit )
225
184
226
185
227
186
@pytest .mark .parametrize ('num_ancilla' , [1 , 2 , 3 ])
@@ -233,25 +192,24 @@ def test_phase_using_clean_ancilla(num_ancilla: int, theta: float):
233
192
u .on (q ), PhaseUsingCleanAncilla (theta = theta , ancilla_bitsize = num_ancilla ).on (q )
234
193
)
235
194
control_circuit = cirq .Circuit (u .on (q ), cirq .ZPowGate (exponent = theta ).on (q ))
236
- assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit )
237
-
238
-
239
- def test_add_qubits_raise_value_error (num_ancilla = 1 ):
240
- q = cirq .LineQubit (0 )
241
- args = cirq .StateVectorSimulationState (qubits = [q ])
242
-
243
- with pytest .raises (ValueError , match = 'should not already be tracked.' ):
244
- args .add_qubits ([q ])
195
+ assert_test_circuit_for_dm_simulator (test_circuit , control_circuit )
196
+ assert_test_circuit_for_sv_simulator (test_circuit , control_circuit )
245
197
246
198
247
- def test_remove_qubits_not_implemented (num_ancilla = 1 ):
248
- args = DummySimulationState ()
249
-
250
- assert args .remove_qubits ([cirq .LineQubit (0 )]) is NotImplemented
199
+ def assert_test_circuit_for_dm_simulator (test_circuit , control_circuit ) -> None :
200
+ # Density Matrix Simulator: For unitary gates, this fallbacks to `cirq.apply_channel`
201
+ # which recursively calls to `cirq.apply_unitary(decompose=True)`.
202
+ for split_untangled_states in [True , False ]:
203
+ sim = cirq .DensityMatrixSimulator (split_untangled_states = split_untangled_states )
204
+ control_sim = sim .simulate (control_circuit ).final_density_matrix
205
+ test_sim = sim .simulate (test_circuit ).final_density_matrix
206
+ assert np .allclose (test_sim , control_sim )
251
207
252
208
253
- def assert_test_circuit_for_sv_dm_simulators (test_circuit , control_circuit ) -> None :
254
- for test_simulator in ['cirq.final_state_vector' , 'cirq.final_density_matrix' ]:
255
- test_sim = eval (test_simulator )(test_circuit )
256
- control_sim = eval (test_simulator )(control_circuit )
209
+ def assert_test_circuit_for_sv_simulator (test_circuit , control_circuit ) -> None :
210
+ # State Vector Simulator.
211
+ for split_untangled_states in [True , False ]:
212
+ sim = cirq .Simulator (split_untangled_states = split_untangled_states )
213
+ control_sim = sim .simulate (control_circuit ).final_state_vector
214
+ test_sim = sim .simulate (test_circuit ).final_state_vector
257
215
assert np .allclose (test_sim , control_sim )
0 commit comments