13
13
use std:: f64:: consts:: PI ;
14
14
15
15
use hashbrown:: { HashMap , HashSet } ;
16
+ use pyo3:: exceptions:: PyRuntimeError ;
16
17
use pyo3:: prelude:: * ;
17
18
use pyo3:: { pyfunction, pymodule, wrap_pyfunction, Bound , PyResult , Python } ;
18
19
use rustworkx_core:: petgraph:: stable_graph:: NodeIndex ;
@@ -110,70 +111,69 @@ pub(crate) fn cancel_commutations(
110
111
} else {
111
112
continue ;
112
113
}
113
- com_set. iter ( ) . for_each ( |node| {
114
+ for node in com_set. iter ( ) {
114
115
let instr = match & dag. dag [ * node] {
115
116
NodeType :: Operation ( instr) => instr,
116
117
_ => panic ! ( "Unexpected type in commutation set." ) ,
117
118
} ;
118
119
let num_qargs = dag. get_qargs ( instr. qubits ) . len ( ) ;
119
120
// no support for cancellation of parameterized gates
120
- if !instr. is_parameterized ( ) {
121
- if let Some ( op_gate) = instr. op . try_standard_gate ( ) {
122
- if num_qargs == 1 && SUPPORTED_GATES . contains ( & op_gate) {
123
- cancellation_sets
124
- . entry ( CancellationSetKey {
125
- gate : GateOrRotation :: Gate ( op_gate) ,
126
- qubits : smallvec ! [ wire] ,
127
- com_set_index : com_set_idx,
128
- second_index : None ,
129
- } )
130
- . or_insert_with ( Vec :: new)
131
- . push ( * node) ;
132
- }
121
+ if instr. is_parameterized ( ) {
122
+ continue ;
123
+ }
124
+ if let Some ( op_gate) = instr. op . try_standard_gate ( ) {
125
+ if num_qargs == 1 && SUPPORTED_GATES . contains ( & op_gate) {
126
+ cancellation_sets
127
+ . entry ( CancellationSetKey {
128
+ gate : GateOrRotation :: Gate ( op_gate) ,
129
+ qubits : smallvec ! [ wire] ,
130
+ com_set_index : com_set_idx,
131
+ second_index : None ,
132
+ } )
133
+ . or_insert_with ( Vec :: new)
134
+ . push ( * node) ;
135
+ }
133
136
134
- if num_qargs == 1 && Z_ROTATIONS . contains ( & op_gate) {
135
- cancellation_sets
136
- . entry ( CancellationSetKey {
137
- gate : GateOrRotation :: ZRotation ,
138
- qubits : smallvec ! [ wire] ,
139
- com_set_index : com_set_idx,
140
- second_index : None ,
141
- } )
142
- . or_insert_with ( Vec :: new)
143
- . push ( * node) ;
144
- }
145
- if num_qargs == 1 && X_ROTATIONS . contains ( & op_gate) {
146
- cancellation_sets
147
- . entry ( CancellationSetKey {
148
- gate : GateOrRotation :: XRotation ,
149
- qubits : smallvec ! [ wire] ,
150
- com_set_index : com_set_idx,
151
- second_index : None ,
152
- } )
153
- . or_insert_with ( Vec :: new)
154
- . push ( * node) ;
155
- }
156
- // Don't deal with Y rotation, because Y rotation doesn't commute with
157
- // CNOT, so it should be dealt with by optimized1qgate pass
158
- if num_qargs == 2
159
- && dag. get_qargs ( instr. qubits ) [ 0 ] == & wire
160
- {
161
- let second_qarg = dag. get_qargs ( instr. qubits ) [ 1 ] ;
162
- cancellation_sets
163
- . entry ( CancellationSetKey {
164
- gate : GateOrRotation :: Gate ( op_gate) ,
165
- qubits : smallvec ! [ wire, second_qarg] ,
166
- com_set_index : com_set_idx,
167
- second_index : node_indices
168
- . get ( & ( * node, Wire :: Qubit ( second_qarg) ) )
169
- . copied ( ) ,
170
- } )
171
- . or_insert_with ( Vec :: new)
172
- . push ( * node) ;
173
- }
137
+ if num_qargs == 1 && Z_ROTATIONS . contains ( & op_gate) {
138
+ cancellation_sets
139
+ . entry ( CancellationSetKey {
140
+ gate : GateOrRotation :: ZRotation ,
141
+ qubits : smallvec ! [ wire] ,
142
+ com_set_index : com_set_idx,
143
+ second_index : None ,
144
+ } )
145
+ . or_insert_with ( Vec :: new)
146
+ . push ( * node) ;
147
+ }
148
+ if num_qargs == 1 && X_ROTATIONS . contains ( & op_gate) {
149
+ cancellation_sets
150
+ . entry ( CancellationSetKey {
151
+ gate : GateOrRotation :: XRotation ,
152
+ qubits : smallvec ! [ wire] ,
153
+ com_set_index : com_set_idx,
154
+ second_index : None ,
155
+ } )
156
+ . or_insert_with ( Vec :: new)
157
+ . push ( * node) ;
158
+ }
159
+ // Don't deal with Y rotation, because Y rotation doesn't commute with
160
+ // CNOT, so it should be dealt with by optimized1qgate pass
161
+ if num_qargs == 2 && dag. get_qargs ( instr. qubits ) [ 0 ] == wire {
162
+ let second_qarg = dag. get_qargs ( instr. qubits ) [ 1 ] ;
163
+ cancellation_sets
164
+ . entry ( CancellationSetKey {
165
+ gate : GateOrRotation :: Gate ( op_gate) ,
166
+ qubits : smallvec ! [ wire, second_qarg] ,
167
+ com_set_index : com_set_idx,
168
+ second_index : node_indices
169
+ . get ( & ( * node, Wire :: Qubit ( second_qarg) ) )
170
+ . copied ( ) ,
171
+ } )
172
+ . or_insert_with ( Vec :: new)
173
+ . push ( * node) ;
174
174
}
175
175
}
176
- } )
176
+ }
177
177
}
178
178
}
179
179
} ) ;
@@ -191,12 +191,10 @@ pub(crate) fn cancel_commutations(
191
191
if matches ! ( cancel_key. gate, GateOrRotation :: ZRotation ) && z_var_gate. is_none ( ) {
192
192
continue ;
193
193
}
194
- if matches ! ( cancel_key. gate, GateOrRotation :: ZRotation | GateOrRotation :: XRotation )
195
- {
196
- let run_qarg = match & dag. dag [ * cancel_set[ 0 ] ] {
197
- NodeType :: Operation ( instr) => dag. get_qargs ( instr. qubits ) [ 0 ] ,
198
- _ => panic ! ( "Unexpected type in commutation set run." ) ,
199
- } ;
194
+ if matches ! (
195
+ cancel_key. gate,
196
+ GateOrRotation :: ZRotation | GateOrRotation :: XRotation
197
+ ) {
200
198
let mut total_angle: f64 = 0.0 ;
201
199
let mut total_phase: f64 = 0.0 ;
202
200
for current_node in cancel_set {
@@ -206,14 +204,6 @@ pub(crate) fn cancel_commutations(
206
204
} ;
207
205
let node_op_name = node_op. op . name ( ) ;
208
206
209
- let node_qargs = dag. get_qargs ( node_op. qubits ) ;
210
- if node_op. condition ( ) . is_some ( )
211
- || node_qargs. len ( ) > 1
212
- || node_qargs[ 0 ] != run_qarg
213
- {
214
- return Err ( QiskitError :: new_err ( "internal error" ) ) ;
215
- }
216
-
217
207
let node_angle = if ROTATION_GATES . contains ( & node_op_name) {
218
208
match node_op. params_view ( ) . first ( ) {
219
209
Some ( Param :: Float ( f) ) => Ok ( * f) ,
@@ -229,7 +219,7 @@ pub(crate) fn cancel_commutations(
229
219
} else if EIGHTH_TURNS . contains ( & node_op_name) {
230
220
Ok ( PI / 4.0 )
231
221
} else {
232
- Err ( QiskitError :: new_err ( format ! (
222
+ Err ( PyRuntimeError :: new_err ( format ! (
233
223
"Angle for operation {} is not defined" ,
234
224
node_op_name
235
225
) ) )
@@ -240,10 +230,10 @@ pub(crate) fn cancel_commutations(
240
230
total_phase += new_phase
241
231
}
242
232
243
- let new_op = match cancel_key. gate
233
+ let new_op = match cancel_key. gate {
244
234
GateOrRotation :: ZRotation => z_var_gate. unwrap ( ) ,
245
- GateOrRotation :: XRotation ) => & RXGate ,
246
- _ => unreachable ! ( )
235
+ GateOrRotation :: XRotation => & RXGate ,
236
+ _ => unreachable ! ( ) ,
247
237
} ;
248
238
249
239
let gate_angle = euler_one_qubit_decomposer:: mod_2pi ( total_angle, 0. ) ;
0 commit comments