Skip to content

Commit 5184ca4

Browse files
eliarbelraynelfss
andauthored
Remove calibrations APIs and related functionality (#13861)
* Handle ScheduleBlock and pulse gates loading * Add documentation and remove redundant code * Limit QPY version when generating circuits for compatibility test Fix some doc issues * Handle QPY compatibility testing. Misc other fixes * Update qiskit/qpy/binary_io/circuits.py Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Remove pulse from GenericBackendV2 This commit removes pulse-related functionality from GenericBackendV2, as part of Pulse removal in Qiskit 2.0. This includes the ability to initialize the backend with custom calibrations and query it for channel information. Also, various clean ups where made to accommodate for the updated API of GenericBackendV2. * First pass * Avoid generating pulse circuits in load_qpy & version >= 2.0 * Remove more stuff * Add reno and some misc fixes * Add recent changes from remove-pulse-qpy branch * Raise QpyError when loading ScheduleBlock payloads * Clean up TODOs * Unify transpiler renos w.r.t pulse removal * Remove inst_map from transpile() docstring * Small cleanup and reno update * Fix lint * Applying comments from Elena's review --------- Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
1 parent 3c8bae4 commit 5184ca4

80 files changed

Lines changed: 176 additions & 3308 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/accelerate/src/basis/basis_translator/mod.rs

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ fn run(
218218
Ok(out_dag)
219219
}
220220

221-
/// Method that extracts all non-calibrated gate instances identifiers from a DAGCircuit.
221+
/// Method that extracts all gate instances identifiers from a DAGCircuit.
222222
fn extract_basis(
223223
py: Python,
224224
circuit: &DAGCircuit,
@@ -232,10 +232,8 @@ fn extract_basis(
232232
basis: &mut IndexSet<GateIdentifier, ahash::RandomState>,
233233
min_qubits: usize,
234234
) -> PyResult<()> {
235-
for (node, operation) in circuit.op_nodes(true) {
236-
if !circuit.has_calibration_for_index(py, node)?
237-
&& circuit.get_qargs(operation.qubits).len() >= min_qubits
238-
{
235+
for (_node, operation) in circuit.op_nodes(true) {
236+
if circuit.get_qargs(operation.qubits).len() >= min_qubits {
239237
basis.insert((operation.op.name().to_string(), operation.op.num_qubits()));
240238
}
241239
if operation.op.control_flow() {
@@ -264,11 +262,7 @@ fn extract_basis(
264262
.borrow();
265263
for (index, inst) in circuit_data.iter().enumerate() {
266264
let instruction_object = circuit.get_item(index)?;
267-
let has_calibration = circuit
268-
.call_method1(intern!(py, "_has_calibration_for"), (&instruction_object,))?;
269-
if !has_calibration.is_truthy()?
270-
&& circuit_data.get_qargs(inst.qubits).len() >= min_qubits
271-
{
265+
if circuit_data.get_qargs(inst.qubits).len() >= min_qubits {
272266
basis.insert((inst.op.name().to_string(), inst.op.num_qubits()));
273267
}
274268
if inst.op.control_flow() {
@@ -287,7 +281,7 @@ fn extract_basis(
287281
}
288282

289283
/// Method that extracts a mapping of all the qargs in the local_source basis
290-
/// obtained from the [Target], to all non-calibrated gate instances identifiers from a DAGCircuit.
284+
/// obtained from the [Target], to all gate instances identifiers from a DAGCircuit.
291285
/// When dealing with `ControlFlowOp` instances the function will perform a recursion call
292286
/// to a variant design to handle instances of `QuantumCircuit`.
293287
fn extract_basis_target(
@@ -306,9 +300,9 @@ fn extract_basis_target(
306300
ahash::RandomState,
307301
>,
308302
) -> PyResult<()> {
309-
for (node, node_obj) in dag.op_nodes(true) {
303+
for (_node, node_obj) in dag.op_nodes(true) {
310304
let qargs: &[Qubit] = dag.get_qargs(node_obj.qubits);
311-
if dag.has_calibration_for_index(py, node)? || qargs.len() < min_qubits {
305+
if qargs.len() < min_qubits {
312306
continue;
313307
}
314308
// Treat the instruction as on an incomplete basis if the qargs are in the
@@ -351,8 +345,9 @@ fn extract_basis_target(
351345
unreachable!("Control flow op is not a control flow op. But control_flow is `true`")
352346
};
353347
let bound_inst = op.instruction.bind(py);
354-
// Use python side extraction instead of the Rust method `op.blocks` due to
355-
// required usage of a python-space method `QuantumCircuit.has_calibration_for`.
348+
// TODO: Use Rust method `op.blocks` instead of Python side extraction now that
349+
// the python-space method `QuantumCircuit.has_calibration_for`
350+
// has been removed and we don't need to account for it.
356351
let blocks = bound_inst.getattr("blocks")?.try_iter()?;
357352
for block in blocks {
358353
extract_basis_target_circ(
@@ -390,13 +385,9 @@ fn extract_basis_target_circ(
390385
let py = circuit.py();
391386
let circ_data_bound = circuit.getattr("_data")?.downcast_into::<CircuitData>()?;
392387
let circ_data = circ_data_bound.borrow();
393-
for (index, node_obj) in circ_data.iter().enumerate() {
388+
for node_obj in circ_data.iter() {
394389
let qargs = circ_data.get_qargs(node_obj.qubits);
395-
if circuit
396-
.call_method1("_has_calibration_for", (circuit.get_item(index)?,))?
397-
.is_truthy()?
398-
|| qargs.len() < min_qubits
399-
{
390+
if qargs.len() < min_qubits {
400391
continue;
401392
}
402393
// Treat the instruction as on an incomplete basis if the qargs are in the
@@ -578,29 +569,6 @@ fn apply_translation(
578569
continue;
579570
}
580571

581-
if dag.has_calibration_for_index(py, node)? {
582-
out_dag.apply_operation_back(
583-
py,
584-
node_obj.op.clone(),
585-
node_qarg,
586-
node_carg,
587-
if node_obj.params_view().is_empty() {
588-
None
589-
} else {
590-
Some(
591-
node_obj
592-
.params_view()
593-
.iter()
594-
.map(|param| param.clone_ref(py))
595-
.collect(),
596-
)
597-
},
598-
node_obj.label.as_ref().map(|x| x.as_ref().clone()),
599-
#[cfg(feature = "cache_pygates")]
600-
None,
601-
)?;
602-
continue;
603-
}
604572
let unique_qargs: Option<Qargs> = if qubit_set.is_empty() {
605573
None
606574
} else {

crates/accelerate/src/check_map.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn recurse<'py>(
3636
None => edge_set.contains(&[qubits[0].into(), qubits[1].into()]),
3737
}
3838
};
39-
for (node, inst) in dag.op_nodes(false) {
39+
for (_node, inst) in dag.op_nodes(false) {
4040
let qubits = dag.get_qargs(inst.qubits);
4141
if inst.op.control_flow() {
4242
if let OperationRef::Instruction(py_inst) = inst.op.view() {
@@ -65,10 +65,7 @@ fn recurse<'py>(
6565
}
6666
}
6767
}
68-
} else if qubits.len() == 2
69-
&& (dag.calibrations_empty() || !dag.has_calibration_for_index(py, node)?)
70-
&& !check_qubits(qubits)
71-
{
68+
} else if qubits.len() == 2 && !check_qubits(qubits) {
7269
return Ok(Some((
7370
inst.op.name().to_string(),
7471
[qubits[0].0, qubits[1].0],

crates/accelerate/src/euler_one_qubit_decomposer.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,18 +1094,6 @@ pub(crate) fn optimize_1q_gates_decomposition(
10941094
} else {
10951095
unreachable!("nodes in runs will always be op nodes")
10961096
};
1097-
if !dag.calibrations_empty() {
1098-
let mut has_calibration = false;
1099-
for node in &raw_run {
1100-
if dag.has_calibration_for_index(py, *node)? {
1101-
has_calibration = true;
1102-
break;
1103-
}
1104-
}
1105-
if has_calibration {
1106-
continue;
1107-
}
1108-
}
11091097
if basis_gates_per_qubit[qubit.index()].is_none() {
11101098
let basis_gates = match target {
11111099
Some(target) => Some(

crates/accelerate/src/gate_direction.rs

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ use pyo3::types::PyTuple;
2020
use qiskit_circuit::operations::OperationRef;
2121
use qiskit_circuit::packed_instruction::PackedOperation;
2222
use qiskit_circuit::{
23-
circuit_instruction::CircuitInstruction,
2423
converters::{circuit_to_dag, QuantumCircuitData},
2524
dag_circuit::DAGCircuit,
26-
dag_node::{DAGNode, DAGOpNode},
2725
imports,
2826
imports::get_std_gate_class,
2927
operations::Operation,
@@ -291,7 +289,7 @@ where
291289
}
292290
}
293291

294-
if op_args.len() != 2 || dag.has_calibration_for_index(py, node)? {
292+
if op_args.len() != 2 {
295293
continue;
296294
};
297295

@@ -334,9 +332,7 @@ where
334332
}
335333
}
336334
// No matching replacement found
337-
if gate_complies(packed_inst, &[op_args1, op_args0])
338-
|| has_calibration_for_op_node(py, dag, packed_inst, &[op_args1, op_args0])?
339-
{
335+
if gate_complies(packed_inst, &[op_args1, op_args0]) {
340336
return Err(TranspilerError::new_err(format!("{} would be supported on {:?} if the direction was swapped, but no rules are known to do that. {:?} can be automatically flipped.", packed_inst.op.name(), op_args, vec!["cx", "cz", "ecr", "swap", "rzx", "rxx", "ryy", "rzz"])));
341337
// NOTE: Make sure to update the list of the supported gates if adding more replacements
342338
} else {
@@ -375,36 +371,6 @@ where
375371
Ok(dag)
376372
}
377373

378-
// Check whether the dag as calibration for a DAGOpNode
379-
fn has_calibration_for_op_node(
380-
py: Python,
381-
dag: &DAGCircuit,
382-
packed_inst: &PackedInstruction,
383-
qargs: &[Qubit],
384-
) -> PyResult<bool> {
385-
let py_args = PyTuple::new(py, dag.qubits().map_indices(qargs))?;
386-
387-
let dag_op_node = Py::new(
388-
py,
389-
(
390-
DAGOpNode {
391-
instruction: CircuitInstruction {
392-
operation: packed_inst.op.clone(),
393-
qubits: py_args.unbind(),
394-
clbits: PyTuple::empty(py).unbind(),
395-
params: packed_inst.params_view().iter().cloned().collect(),
396-
label: packed_inst.label.clone(),
397-
#[cfg(feature = "cache_pygates")]
398-
py_op: packed_inst.py_op.clone(),
399-
},
400-
},
401-
DAGNode { node: None },
402-
),
403-
)?;
404-
405-
dag.has_calibration_for(py, dag_op_node.borrow(py))
406-
}
407-
408374
// Return a replacement DAG for the given standard gate in the supported list
409375
// TODO: optimize it by caching the DAGs of the non-parametric gates and caching and
410376
// mutating upon request the DAGs of the parametric gates

crates/accelerate/src/target_transpiler/instruction_properties.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ impl InstructionProperties {
3737
/// specified set of qubits
3838
/// error (Option<f64>): The average error rate for the instruction on the specified
3939
/// set of qubits.
40-
/// calibration (Option<PyObject>): The pulse representation of the instruction.
4140
#[new]
4241
#[pyo3(signature = (duration=None, error=None))]
4342
pub fn new(_py: Python<'_>, duration: Option<f64>, error: Option<f64>) -> Self {

crates/circuit/src/converters.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@
1313
#[cfg(feature = "cache_pygates")]
1414
use std::sync::OnceLock;
1515

16-
use hashbrown::HashMap;
1716
use pyo3::prelude::*;
18-
use pyo3::{
19-
intern,
20-
types::{PyDict, PyList},
21-
};
17+
use pyo3::{intern, types::PyList};
2218

2319
use crate::circuit_data::CircuitData;
2420
use crate::dag_circuit::{DAGCircuit, NodeType};
@@ -30,7 +26,6 @@ use crate::packed_instruction::PackedInstruction;
3026
pub struct QuantumCircuitData<'py> {
3127
pub data: CircuitData,
3228
pub name: Option<Bound<'py, PyAny>>,
33-
pub calibrations: Option<HashMap<String, Py<PyDict>>>,
3429
pub metadata: Option<Bound<'py, PyAny>>,
3530
pub qregs: Option<Bound<'py, PyList>>,
3631
pub cregs: Option<Bound<'py, PyList>>,
@@ -47,10 +42,6 @@ impl<'py> FromPyObject<'py> for QuantumCircuitData<'py> {
4742
Ok(QuantumCircuitData {
4843
data: data_borrowed,
4944
name: ob.getattr(intern!(py, "name")).ok(),
50-
calibrations: ob
51-
.getattr(intern!(py, "_calibrations_prop"))?
52-
.extract()
53-
.ok(),
5445
metadata: ob.getattr(intern!(py, "metadata")).ok(),
5546
qregs: ob
5647
.getattr(intern!(py, "qregs"))

0 commit comments

Comments
 (0)