Skip to content

Commit d919028

Browse files
committed
comments from code review
1 parent e5d70a6 commit d919028

File tree

1 file changed

+88
-99
lines changed

1 file changed

+88
-99
lines changed

crates/accelerate/src/commutation_cancellation.rs

+88-99
Original file line numberDiff line numberDiff line change
@@ -99,82 +99,79 @@ pub(crate) fn cancel_commutations(
9999
(0..dag.num_qubits() as u32).for_each(|qubit| {
100100
let wire = Qubit(qubit);
101101
if let Some(wire_commutation_set) = commutation_set.get(&Wire::Qubit(wire)) {
102-
wire_commutation_set
103-
.iter()
104-
.enumerate()
105-
.for_each(|(com_set_idx, com_set)| {
106-
// This ensures that we only have DAGOPNodes in the current com_set, yuck...
107-
if let NodeType::Operation(_node0) = &dag.dag[*com_set.first().unwrap()] {
108-
com_set.iter().for_each(|node| {
109-
let op = match &dag.dag[*node] {
110-
NodeType::Operation(instr) => instr,
111-
_ => panic!("Unexpected type in commutation set."),
112-
};
113-
let num_qargs = dag.get_qargs(op.qubits).len();
114-
// no support for cancellation of parameterized gates
115-
if op
116-
.params_view()
117-
.iter()
118-
.all(|p| !matches!(p, Param::ParameterExpression(_)))
119-
{
120-
if let Some(op_gate) = op.op.try_standard_gate() {
121-
if num_qargs == 1usize && SUPPORTED_GATES.contains(&op_gate) {
122-
cancellation_sets
123-
.entry(CancellationSetKey {
124-
gate: GateOrRotation::Gate(op_gate),
125-
qubits: smallvec![wire],
126-
com_set_index: com_set_idx,
127-
second_index: None,
128-
})
129-
.or_insert_with(Vec::new)
130-
.push(*node);
131-
}
102+
for (com_set_idx, com_set) in wire_commutation_set.iter().enumerate() {
103+
if let Some(&nd) = com_set.first() {
104+
if !matches!(dag.dag[nd], NodeType::Operation(_)) {
105+
continue;
106+
}
107+
} else {
108+
continue;
109+
}
110+
com_set.iter().for_each(|node| {
111+
let instr = match &dag.dag[*node] {
112+
NodeType::Operation(instr) => instr,
113+
_ => panic!("Unexpected type in commutation set."),
114+
};
115+
let num_qargs = dag.get_qargs(instr.qubits).len();
116+
// no support for cancellation of parameterized gates
117+
if !instr.is_parameterized() {
118+
if let Some(op_gate) = instr.op.try_standard_gate() {
119+
if num_qargs == 1 && SUPPORTED_GATES.contains(&op_gate) {
120+
cancellation_sets
121+
.entry(CancellationSetKey {
122+
gate: GateOrRotation::Gate(op_gate),
123+
qubits: smallvec![wire],
124+
com_set_index: com_set_idx,
125+
second_index: None,
126+
})
127+
.or_insert_with(Vec::new)
128+
.push(*node);
129+
}
132130

133-
if num_qargs == 1usize && Z_ROTATIONS.contains(&op_gate) {
134-
cancellation_sets
135-
.entry(CancellationSetKey {
136-
gate: GateOrRotation::ZRotation,
137-
qubits: smallvec![wire],
138-
com_set_index: com_set_idx,
139-
second_index: None,
140-
})
141-
.or_insert_with(Vec::new)
142-
.push(*node);
143-
}
144-
if num_qargs == 1usize && X_ROTATIONS.contains(&op_gate) {
145-
cancellation_sets
146-
.entry(CancellationSetKey {
147-
gate: GateOrRotation::XRotation,
148-
qubits: smallvec![wire],
149-
com_set_index: com_set_idx,
150-
second_index: None,
151-
})
152-
.or_insert_with(Vec::new)
153-
.push(*node);
154-
}
155-
// Don't deal with Y rotation, because Y rotation doesn't commute with
156-
// CNOT, so it should be dealt with by optimized1qgate pass
157-
if num_qargs == 2usize
158-
&& dag.get_qargs(op.qubits).first().unwrap() == &wire
159-
{
160-
let second_qarg = dag.get_qargs(op.qubits)[1];
161-
cancellation_sets
162-
.entry(CancellationSetKey {
163-
gate: GateOrRotation::Gate(op_gate),
164-
qubits: smallvec![wire, second_qarg],
165-
com_set_index: com_set_idx,
166-
second_index: node_indices
167-
.get(&(*node, Wire::Qubit(second_qarg)))
168-
.copied(),
169-
})
170-
.or_insert_with(Vec::new)
171-
.push(*node);
172-
}
173-
}
131+
if num_qargs == 1 && Z_ROTATIONS.contains(&op_gate) {
132+
cancellation_sets
133+
.entry(CancellationSetKey {
134+
gate: GateOrRotation::ZRotation,
135+
qubits: smallvec![wire],
136+
com_set_index: com_set_idx,
137+
second_index: None,
138+
})
139+
.or_insert_with(Vec::new)
140+
.push(*node);
141+
}
142+
if num_qargs == 1 && X_ROTATIONS.contains(&op_gate) {
143+
cancellation_sets
144+
.entry(CancellationSetKey {
145+
gate: GateOrRotation::XRotation,
146+
qubits: smallvec![wire],
147+
com_set_index: com_set_idx,
148+
second_index: None,
149+
})
150+
.or_insert_with(Vec::new)
151+
.push(*node);
152+
}
153+
// Don't deal with Y rotation, because Y rotation doesn't commute with
154+
// CNOT, so it should be dealt with by optimized1qgate pass
155+
if num_qargs == 2
156+
&& dag.get_qargs(instr.qubits).first().unwrap() == &wire
157+
{
158+
let second_qarg = dag.get_qargs(instr.qubits)[1];
159+
cancellation_sets
160+
.entry(CancellationSetKey {
161+
gate: GateOrRotation::Gate(op_gate),
162+
qubits: smallvec![wire, second_qarg],
163+
com_set_index: com_set_idx,
164+
second_index: node_indices
165+
.get(&(*node, Wire::Qubit(second_qarg)))
166+
.copied(),
167+
})
168+
.or_insert_with(Vec::new)
169+
.push(*node);
174170
}
175-
})
171+
}
176172
}
177173
})
174+
}
178175
}
179176
});
180177

@@ -193,12 +190,10 @@ pub(crate) fn cancel_commutations(
193190
if matches!(cancel_key.gate, GateOrRotation::ZRotation)
194191
|| matches!(cancel_key.gate, GateOrRotation::XRotation)
195192
{
196-
let run_op = match &dag.dag[*cancel_set.first().unwrap()] {
197-
NodeType::Operation(instr) => instr,
193+
let run_qarg = match &dag.dag[*cancel_set.first().unwrap()] {
194+
NodeType::Operation(instr) => dag.get_qargs(instr.qubits)[0],
198195
_ => panic!("Unexpected type in commutation set run."),
199196
};
200-
201-
let run_qarg = dag.get_qargs(run_op.qubits).first().unwrap();
202197
let mut total_angle: f64 = 0.0;
203198
let mut total_phase: f64 = 0.0;
204199
for current_node in cancel_set {
@@ -214,33 +209,35 @@ pub(crate) fn cancel_commutations(
214209
.as_deref()
215210
.is_some_and(|attr| attr.condition.is_some())
216211
|| node_qargs.len() > 1
217-
|| &node_qargs[0] != run_qarg
212+
|| node_qargs[0] != run_qarg
218213
{
219-
panic!("internal error");
214+
return Err(QiskitError::new_err("internal error"));
220215
}
221216

222217
let node_angle = if ROTATION_GATES.contains(&node_op_name) {
223218
match node_op.params_view().first() {
224-
Some(Param::Float(f)) => *f,
219+
Some(Param::Float(f)) => Ok(*f),
225220
_ => return Err(QiskitError::new_err(format!(
226-
"Rotational gate with parameter expression encoutned in cancellation {:?}",
221+
"Rotational gate with parameter expression encountered in cancellation {:?}",
227222
node_op.op
228223
)))
229224
}
230225
} else if HALF_TURNS.contains(&node_op_name) {
231-
PI
226+
Ok(PI)
232227
} else if QUARTER_TURNS.contains(&node_op_name) {
233-
PI / 2.0
228+
Ok(PI / 2.0)
234229
} else if EIGHTH_TURNS.contains(&node_op_name) {
235-
PI / 4.0
230+
Ok(PI / 4.0)
236231
} else {
237-
panic!("Angle for operation {node_op_name} is not defined")
232+
Err(QiskitError::new_err(format!(
233+
"Angle for operation {} is not defined",
234+
node_op_name
235+
)))
238236
};
239-
total_angle += node_angle;
237+
total_angle += node_angle?;
240238

241-
if let Some(definition) = node_op.op.definition(node_op.params_view()) {
242-
total_phase += match definition.global_phase() {Param::Float(f) => f, _ => panic!("PackedInstruction with definition has no global phase set as floating point number")};
243-
}
239+
let Param::Float(new_phase) = node_op.op.definition(node_op.params_view()).unwrap().global_phase().clone() else { unreachable!() };
240+
total_phase += new_phase
244241
}
245242

246243
let new_op = if matches!(cancel_key.gate, GateOrRotation::ZRotation) {
@@ -254,20 +251,12 @@ pub(crate) fn cancel_commutations(
254251
let gate_angle = euler_one_qubit_decomposer::mod_2pi(total_angle, 0.);
255252

256253
let new_op_phase: f64 = if gate_angle.abs() > _CUTOFF_PRECISION {
257-
let new_index = dag.insert_1q_on_incoming_qubit(
254+
dag.insert_1q_on_incoming_qubit(
258255
(*new_op, &[total_angle]),
259256
*cancel_set.first().unwrap(),
260257
);
261-
let new_node = match &dag.dag[new_index] {
262-
NodeType::Operation(instr) => instr,
263-
_ => panic!("Unexpected type in commutation set run."),
264-
};
265-
266-
if let Some(definition) = new_node.op.definition(new_node.params_view()) {
267-
match definition.global_phase() {Param::Float(f) => *f, _ => panic!("PackedInstruction with definition has no global phase set as floating point number")}
268-
} else {
269-
0.0
270-
}
258+
let Param::Float(new_phase) = new_op.definition(&[Param::Float(total_angle)]).unwrap().global_phase().clone() else { unreachable!();};
259+
new_phase
271260
} else {
272261
0.0
273262
};

0 commit comments

Comments
 (0)