Skip to content

Commit 4245581

Browse files
authored
Return old phase from DAGCircuit::set_global_phase_* (#16057)
`ParameterExpression` can get rather heavy, and this permits temporarily swapping out the global phase without having to clone what was there before in order to store it.
1 parent 51680f9 commit 4245581

3 files changed

Lines changed: 31 additions & 22 deletions

File tree

crates/circuit/src/dag_circuit.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -914,15 +914,8 @@ impl DAGCircuit {
914914
/// Args:
915915
/// angle (float, :class:`.ParameterExpression`): The phase angle.
916916
#[setter(global_phase)]
917-
pub fn set_global_phase_param(&mut self, angle: Param) -> PyResult<()> {
918-
match angle {
919-
Param::Float(angle) => self.set_global_phase_f64(angle),
920-
Param::ParameterExpression(angle) => {
921-
self.global_phase = Param::ParameterExpression(angle);
922-
}
923-
Param::Obj(_) => return Err(PyTypeError::new_err("Invalid type for global phase")),
924-
}
925-
Ok(())
917+
pub fn set_global_phase(&mut self, angle: Param) -> PyResult<()> {
918+
self.set_global_phase_param(angle).map(|_| ())
926919
}
927920

928921
/// Remove all operation nodes with the given name.
@@ -6230,12 +6223,30 @@ impl DAGCircuit {
62306223
Ok((in_node, out_node))
62316224
}
62326225

6233-
/// Set the global phase to a float value.
6226+
/// Set the global phase to a float value. Returns the old phase.
62346227
///
62356228
/// Unlike the general [set_global_phase_param], this is infallible.
62366229
#[inline]
6237-
pub fn set_global_phase_f64(&mut self, angle: f64) {
6238-
self.global_phase = Param::Float(angle.rem_euclid(::std::f64::consts::TAU));
6230+
pub fn set_global_phase_f64(&mut self, angle: f64) -> Param {
6231+
std::mem::replace(
6232+
&mut self.global_phase,
6233+
Param::Float(angle.rem_euclid(::std::f64::consts::TAU)),
6234+
)
6235+
}
6236+
6237+
/// Set the global phase to a general [Param]. Returns the old phase.
6238+
///
6239+
/// Unlike the general [set_global_phase_param], this is infallible.
6240+
#[inline]
6241+
pub fn set_global_phase_param(&mut self, angle: Param) -> PyResult<Param> {
6242+
match angle {
6243+
Param::Float(angle) => Ok(self.set_global_phase_f64(angle)),
6244+
Param::ParameterExpression(angle) => Ok(std::mem::replace(
6245+
&mut self.global_phase,
6246+
Param::ParameterExpression(angle),
6247+
)),
6248+
Param::Obj(_) => Err(PyTypeError::new_err("Invalid type for global phase")),
6249+
}
62396250
}
62406251

62416252
/// Get the nodes on the given wire.
@@ -7298,14 +7309,13 @@ impl DAGCircuit {
72987309

72997310
pub fn add_global_phase(&mut self, value: &Param) -> PyResult<()> {
73007311
match value {
7301-
Param::Obj(_) => {
7302-
return Err(PyTypeError::new_err(
7303-
"Invalid parameter type, only float and parameter expression are supported",
7304-
));
7305-
}
7306-
_ => self.set_global_phase_param(add_global_phase(&self.global_phase, value))?,
7312+
Param::Obj(_) => Err(PyTypeError::new_err(
7313+
"Invalid parameter type, only float and parameter expression are supported",
7314+
)),
7315+
_ => self
7316+
.set_global_phase_param(add_global_phase(&self.global_phase, value))
7317+
.map(|_| ()),
73077318
}
7308-
Ok(())
73097319
}
73107320

73117321
/// Return the op name counts in the circuit

crates/transpiler/src/passes/commutative_optimization.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ pub fn run_commutative_optimization(
482482
let num_nodes = node_indices.len();
483483

484484
let mut node_actions: Vec<NodeAction> = vec![NodeAction::Keep; num_nodes];
485-
let mut new_global_phase = dag.global_phase().clone();
485+
let mut new_global_phase = new_dag.set_global_phase_f64(0.0);
486486

487487
let mut modified: bool = false;
488488

crates/transpiler/src/passes/remove_identity_equiv.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,7 @@ pub fn py_remove_identity_equiv(
250250
//
251251
// This doesn't account for control-flow blocks which _also_ might have set global phases, byt
252252
// `run_remove_identity_equiv` as of Qiskit 2.4 doesn't recurse, so the hack should hold.
253-
let old_phase = dag.global_phase().clone();
254-
dag.set_global_phase_f64(0.0);
253+
let old_phase = dag.set_global_phase_f64(0.0);
255254

256255
// Explicitly release GIL because threads may call Python to get
257256
// the matrix for a PyGate

0 commit comments

Comments
 (0)