From 3d87163d8165c83d9cb3452788cc2b8b9a4f409c Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Sun, 5 May 2024 11:46:06 -0400 Subject: [PATCH] Fix: Hide all private attributes in `Target` - Hide all private attributes of the `Target` to prevent unecessary cloning. - Other small tweaks and fixes. --- crates/accelerate/src/target.rs | 80 +++++++++++++++++++++------------ qiskit/transpiler/target.py | 15 +++---- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/crates/accelerate/src/target.rs b/crates/accelerate/src/target.rs index 54399729c9e9..baea412de548 100644 --- a/crates/accelerate/src/target.rs +++ b/crates/accelerate/src/target.rs @@ -37,30 +37,59 @@ struct Qargs { impl IntoPy for Qargs { fn into_py(self, py: Python<'_>) -> PyObject { - if self.vec.len() == 1 { - let qargs: (PhysicalQubit,) = self.vec.into_iter().collect_tuple().unwrap(); - qargs.to_object(py) - } else if self.vec.len() == 2 { - let qargs: (PhysicalQubit, PhysicalQubit) = - self.vec.into_iter().collect_tuple().unwrap(); - qargs.to_object(py) - } else if self.vec.len() == 3 { - let qargs: (PhysicalQubit, PhysicalQubit, PhysicalQubit) = - self.vec.into_iter().collect_tuple().unwrap(); - qargs.to_object(py) - } else if self.vec.len() == 4 { - let qargs: (PhysicalQubit, PhysicalQubit, PhysicalQubit, PhysicalQubit) = - self.vec.into_iter().collect_tuple().unwrap(); - qargs.to_object(py) - } else { - py.None() + match self.vec.len() { + 1 => { + let qargs: (PhysicalQubit,) = self.vec.into_iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 2 => { + let qargs: (PhysicalQubit, PhysicalQubit) = + self.vec.into_iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 3 => { + let qargs: (PhysicalQubit, PhysicalQubit, PhysicalQubit) = + self.vec.into_iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 4 => { + let qargs: (PhysicalQubit, PhysicalQubit, PhysicalQubit, PhysicalQubit) = + self.vec.into_iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + _ => py.None(), } } } impl ToPyObject for Qargs { fn to_object(&self, py: Python<'_>) -> PyObject { - self.clone().into_py(py) + match self.vec.len() { + 1 => { + let qargs: (&PhysicalQubit,) = self.vec.iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 2 => { + let qargs: (&PhysicalQubit, &PhysicalQubit) = + self.vec.iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 3 => { + let qargs: (&PhysicalQubit, &PhysicalQubit, &PhysicalQubit) = + self.vec.iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + 4 => { + let qargs: ( + &PhysicalQubit, + &PhysicalQubit, + &PhysicalQubit, + &PhysicalQubit, + ) = self.vec.iter().collect_tuple().unwrap(); + qargs.to_object(py) + } + _ => py.None(), + } } } @@ -392,14 +421,10 @@ pub struct Target { #[pyo3(get, set)] pub concurrent_measurements: Vec>, // Maybe convert PyObjects into rust representations of Instruction and Data - #[pyo3(get)] gate_map: GateMapType, - #[pyo3(get)] gate_name_map: IndexMap, global_operations: IndexMap>, - #[pyo3(get)] qarg_gate_map: IndexMap, Option>>, - #[pyo3(get, set)] instruction_durations: Option, instruction_schedule_map: Option, #[pyo3(get, set)] @@ -1048,9 +1073,9 @@ impl Target { operations. */ #[pyo3(text_signature = "(instruction, /)")] - fn operation_from_name(&self, instruction: String) -> PyResult { - if self.gate_name_map.contains_key(&instruction) { - Ok(self.gate_name_map[&instruction].to_owned()) + fn operation_from_name(&self, py: Python<'_>, instruction: String) -> PyResult { + if let Some(gate_obj) = self.gate_name_map.get(&instruction) { + Ok(gate_obj.to_object(py)) } else { Err(PyKeyError::new_err(format!( "Instruction {:?} not in target", @@ -2088,9 +2113,8 @@ impl Target { } fn __getitem__(&self, py: Python<'_>, key: String) -> PyResult { - if self.gate_map.contains_key(&key) { - let value = &self.gate_map[&key]; - Ok(value.to_object(py)) + if let Some(qarg_instprop) = self.gate_map.get(&key) { + Ok(qarg_instprop.to_object(py)) } else { Err(PyKeyError::new_err(format!("{key} not in gate_map"))) } diff --git a/qiskit/transpiler/target.py b/qiskit/transpiler/target.py index a658c8363f50..1dc1bd30cb6a 100644 --- a/qiskit/transpiler/target.py +++ b/qiskit/transpiler/target.py @@ -228,7 +228,7 @@ def _build_coupling_graph(self): multigraph=False ) self.coupling_graph.add_nodes_from([{} for _ in range(self.num_qubits)]) - for gate, qarg_map in self.gate_map.items(): + for gate, qarg_map in self.items(): if qarg_map is None: if self.gate_name_map[gate].num_qubits == 2: self.coupling_graph = None # pylint: disable=attribute-defined-outside-init @@ -236,7 +236,7 @@ def _build_coupling_graph(self): continue for qarg, properties in qarg_map.items(): if qarg is None: - if self.gate_name_map[gate].num_qubits == 2: + if self.operation_from_name(gate).num_qubits == 2: self.coupling_graph = None # pylint: disable=attribute-defined-outside-init return continue @@ -250,7 +250,10 @@ def _build_coupling_graph(self): edge_data[gate] = properties except rx.NoEdgeBetweenNodes: self.coupling_graph.add_edge(*qarg, {gate: properties}) - if self.coupling_graph.num_edges() == 0 and any(x is None for x in self.qarg_gate_map): + qargs = self.qargs + if self.coupling_graph.num_edges() == 0 and ( + qargs == None or any(x is None for x in qargs) + ): self.coupling_graph = None # pylint: disable=attribute-defined-outside-init def build_coupling_map(self, two_q_gate=None, filter_idle_qubits=False): @@ -298,7 +301,7 @@ def build_coupling_map(self, two_q_gate=None, filter_idle_qubits=False): if two_q_gate is not None: coupling_graph = rx.PyDiGraph(multigraph=False) coupling_graph.add_nodes_from([None] * self.num_qubits) - for qargs, properties in self.gate_map[two_q_gate].items(): + for qargs, properties in self[two_q_gate].items(): if len(qargs) != 2: raise ValueError( "Specified two_q_gate: %s is not a 2 qubit instruction" % two_q_gate @@ -339,10 +342,6 @@ def keys(self): """Return all gate names present in the Target""" return {x: None for x in super().keys()}.keys() - def items(self): - """Returns a map of all qargs and properties for each gate.""" - return super().gate_map.items() - def __str__(self): output = io.StringIO() if self.description is not None: