Skip to content

Commit

Permalink
Fix: Make use of copy_operations
Browse files Browse the repository at this point in the history
- Use `copy_operations` to copy all of the operations obtained from `CircuitData` by calling deepcopy.
- Initialize `._data` manually for instances of `BlueprintCircuit` by calling `._build()`.
- Other small fixes.
  • Loading branch information
raynelfss committed Aug 27, 2024
1 parent 9fdebdd commit 70b4f89
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 29 deletions.
15 changes: 11 additions & 4 deletions crates/circuit/src/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{circuit_data::CircuitData, dag_circuit::DAGCircuit};
/// it contains callbacks to Python and should not be stored anywhere.
#[derive(Debug)]
pub(crate) struct QuantumCircuitData<'py> {
pub data: PyRef<'py, CircuitData>,
pub data: CircuitData,
pub name: Option<Bound<'py, PyAny>>,
pub calibrations: HashMap<String, Py<PyDict>>,
pub metadata: Option<Bound<'py, PyAny>>,
Expand All @@ -38,7 +38,7 @@ pub(crate) struct QuantumCircuitData<'py> {
impl<'py> FromPyObject<'py> for QuantumCircuitData<'py> {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
let circuit_data = ob.getattr("_data")?;
let data_borrowed = circuit_data.downcast::<CircuitData>()?.borrow();
let data_borrowed = circuit_data.extract::<CircuitData>()?;
Ok(QuantumCircuitData {
data: data_borrowed,
name: ob.getattr("name").ok(),
Expand All @@ -53,14 +53,21 @@ impl<'py> FromPyObject<'py> for QuantumCircuitData<'py> {
}
}

#[pyfunction]
#[pyfunction(signature = (quantum_circuit, copy_operations = true, qubit_order = None, clbit_order = None))]
fn circuit_to_dag(
py: Python,
quantum_circuit: QuantumCircuitData,
copy_operations: bool,
qubit_order: Option<Vec<PyObject>>,
clbit_order: Option<Vec<PyObject>>,
) -> PyResult<DAGCircuit> {
DAGCircuit::from_quantum_circuit(py, quantum_circuit, qubit_order, clbit_order)
DAGCircuit::from_quantum_circuit(
py,
quantum_circuit,
copy_operations,
qubit_order,
clbit_order,
)
}

pub fn converters(m: &Bound<PyModule>) -> PyResult<()> {
Expand Down
25 changes: 13 additions & 12 deletions crates/circuit/src/dag_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6363,11 +6363,16 @@ impl DAGCircuit {
pub(crate) fn from_quantum_circuit(
py: Python,
qc: QuantumCircuitData,
copy_op: bool,
qubit_order: Option<Vec<PyObject>>,
clbit_order: Option<Vec<PyObject>>,
) -> PyResult<DAGCircuit> {
// Extract necessary attributes
let qc_data = qc.data;
let qc_data = if copy_op {
qc.data.copy(py, true, true)?
} else {
qc.data
};
let num_qubits = qc_data.num_qubits();
let num_clbits = qc_data.num_clbits();
let num_ops = qc_data.__len__();
Expand Down Expand Up @@ -6420,10 +6425,9 @@ impl DAGCircuit {
qubits
} else {
let qubits: Vec<Qubit> = (0..num_qubits as u32).map(Qubit).collect();
for qubit in &qubits {
let qubit = qc_data.qubits().get(*qubit).unwrap();
let bound = qubit.bind(py);
qubit_data.add(py, bound, false)?;
for qubit in qc_data.qubits().bits() {
let bound = qubit.clone_ref(py).into_bound(py);
qubit_data.add(py, &bound, false)?;
}
qubits
};
Expand All @@ -6445,11 +6449,10 @@ impl DAGCircuit {
}
clbits
} else {
let clbits: Vec<Clbit> = (0..num_clbits as u32).map(Clbit).collect();
for clbit in &clbits {
let clbit = qc_data.clbits().get(*clbit).unwrap();
let bound = clbit.bind(py);
clbit_data.add(py, bound, false)?;
let clbits: Vec<Clbit> = (0..num_qubits as u32).map(Clbit).collect();
for clbit in qc_data.clbits().bits() {
let bound = clbit.clone_ref(py).into_bound(py);
clbit_data.add(py, &bound, false)?;
}
clbits
};
Expand Down Expand Up @@ -6507,8 +6510,6 @@ impl DAGCircuit {
new_dag.calibrations = qc.calibrations;
new_dag.metadata = qc.metadata.map(|meta| meta.unbind());

// TODO: Use Qubit ordering to remap the interners and qubit

// Copy over all interners and registers
new_dag.qargs_cache = qubit_interner;
new_dag.cargs_cache = clbit_interner;
Expand Down
26 changes: 13 additions & 13 deletions qiskit/converters/circuit_to_dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

"""Helper function for converting a circuit to a dag"""

from qiskit.dagcircuit.dagcircuit import DAGCircuit
from qiskit.dagcircuit.dagnode import DAGOpNode
from qiskit.circuit.library.blueprintcircuit import BlueprintCircuit
from qiskit._accelerate.circuit.converters import circuit_to_dag as core_circuit_to_dag


Expand Down Expand Up @@ -57,21 +56,22 @@ def circuit_to_dag(circuit, copy_operations=True, *, qubit_order=None, clbit_ord
circ.rz(0.5, q[1]).c_if(c, 2)
dag = circuit_to_dag(circ)
"""
if qubit_order is None:
qubits = circuit.qubits
elif len(qubit_order) != circuit.num_qubits or set(qubit_order) != set(circuit.qubits):
# If we have an instance of BluePrintCircuit, make sure it is built by calling ._build()
if isinstance(circuit, BlueprintCircuit):
if not circuit._is_built:
circuit._build()

if qubit_order is not None and (
len(qubit_order) != circuit.num_qubits or set(qubit_order) != set(circuit.qubits)
):
raise ValueError("'qubit_order' does not contain exactly the same qubits as the circuit")
else:
qubits = qubit_order

if clbit_order is None:
clbits = circuit.clbits
elif len(clbit_order) != circuit.num_clbits or set(clbit_order) != set(circuit.clbits):
if clbit_order is not None and (
len(clbit_order) != circuit.num_clbits or set(clbit_order) != set(circuit.clbits)
):
raise ValueError("'clbit_order' does not contain exactly the same clbits as the circuit")
else:
clbits = clbit_order

dagcircuit = core_circuit_to_dag(circuit, qubit_order, clbit_order)
dagcircuit = core_circuit_to_dag(circuit, copy_operations, qubit_order, clbit_order)

dagcircuit.duration = circuit.duration
dagcircuit.unit = circuit.unit
Expand Down

0 comments on commit 70b4f89

Please sign in to comment.