Skip to content

Commit 2df128f

Browse files
mergify[bot]ElePT
andauthored
Do not raise deprecation warnings for internal uses of dag.duration and dag.unit (backport Qiskit#14133) (Qiskit#14147)
* Do not raise deprecation warnings for internal uses of dag.duration and dag.unit (Qiskit#14133) * Filter Rust deprecation warning when calling dag.duration/dag.unit internally Filter Rust deprecation warning when calling dag.duration/dag.unit internally * Apply Matt's suggestions: * Refactor access patterns: add dag._duration and dag._unit * Refactor internal uses of dag.duration and dag.unit to rely on internal methods * Remove blanket warning filters from unit test config On top of these: * Extend deprecation warnings to dag.duration and dag.unit setters (previously only in getters) * Clean up unit test config from old filters * Change stacklevel * Fix circuit_to_dag * Handle failing tests * _DAGDependencyV2 is private and not a DAGCircuit, so don't use internal attributes * Reduce duplication in getters and setters (cherry picked from commit d0aa100) # Conflicts: # crates/circuit/src/dag_circuit.rs # qiskit/transpiler/passes/scheduling/padding/base_padding.py # test/python/circuit/test_scheduled_circuit.py # test/python/compiler/test_transpiler.py # test/utils/base.py * Fix merge conflicts * Address failing tests * More fixes * More fixes * Last try --------- Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> Co-authored-by: Elena Peña Tapia <epenatap@gmail.com>
1 parent 01e0c9b commit 2df128f

File tree

24 files changed

+235
-171
lines changed

24 files changed

+235
-171
lines changed

crates/circuit/src/dag_circuit.rs

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,8 @@ pub struct DAGCircuit {
208208
/// Global phase.
209209
global_phase: Param,
210210
/// Duration.
211-
#[pyo3(set)]
212211
duration: Option<PyObject>,
213212
/// Unit of duration.
214-
#[pyo3(set)]
215213
unit: String,
216214

217215
// Note: these are tracked separately from `qubits` and `clbits`
@@ -415,11 +413,11 @@ impl DAGCircuit {
415413
})
416414
}
417415

418-
/// The total duration of the circuit, set by a scheduling transpiler pass. Its unit is
416+
/// Returns the total duration of the circuit, set by a scheduling transpiler pass. Its unit is
419417
/// specified by :attr:`.unit`
420418
///
421-
/// DEPRECATED since Qiskit 1.3.0 and will be removed in Qiskit 2.0.0
422-
#[getter]
419+
/// DEPRECATED since Qiskit 1.3.0 and will be removed in Qiskit 3.0.0
420+
#[getter("duration")]
423421
fn get_duration(&self, py: Python) -> PyResult<Option<Py<PyAny>>> {
424422
imports::WARNINGS_WARN.get_bound(py).call1((
425423
intern!(
@@ -430,12 +428,49 @@ impl DAGCircuit {
430428
)
431429
),
432430
py.get_type_bound::<PyDeprecationWarning>(),
433-
2,
431+
1,
434432
))?;
433+
self.get_internal_duration(py)
434+
}
435+
436+
/// Returns the total duration of the circuit for internal use (no deprecation warning).
437+
///
438+
/// To be removed with get_duration.
439+
#[getter("_duration")]
440+
fn get_internal_duration(&self, py: Python) -> PyResult<Option<Py<PyAny>>> {
435441
Ok(self.duration.as_ref().map(|x| x.clone_ref(py)))
436442
}
437443

438-
/// The unit that duration is specified in.
444+
/// Sets the total duration of the circuit, set by a scheduling transpiler pass. Its unit is
445+
/// specified by :attr:`.unit`
446+
///
447+
/// DEPRECATED since Qiskit 1.3.0 and will be removed in Qiskit 3.0.0
448+
#[setter("duration")]
449+
fn set_duration(&mut self, py: Python, duration: Option<PyObject>) -> PyResult<()> {
450+
imports::WARNINGS_WARN.get_bound(py).call1((
451+
intern!(
452+
py,
453+
concat!(
454+
"The property ``qiskit.dagcircuit.dagcircuit.DAGCircuit.duration`` is ",
455+
"deprecated as of Qiskit 1.3.0. It will be removed in Qiskit 3.0.0.",
456+
)
457+
),
458+
py.get_type_bound::<PyDeprecationWarning>(),
459+
1,
460+
))?;
461+
self.set_internal_duration(duration);
462+
Ok(())
463+
}
464+
465+
/// Sets the total duration of the circuit for internal use (no deprecation warning).
466+
///
467+
/// To be removed with set_duration.
468+
#[setter("_duration")]
469+
fn set_internal_duration(&mut self, duration: Option<PyObject>) {
470+
self.duration = duration
471+
}
472+
473+
/// Returns the unit that duration is specified in.
439474
///
440475
/// DEPRECATED since Qiskit 1.3.0 and will be removed in Qiskit 2.0.0
441476
#[getter]
@@ -449,11 +484,47 @@ impl DAGCircuit {
449484
)
450485
),
451486
py.get_type_bound::<PyDeprecationWarning>(),
452-
2,
487+
1,
453488
))?;
489+
self.get_internal_unit()
490+
}
491+
492+
/// Returns the unit that duration is specified in for internal use (no deprecation warning).
493+
///
494+
/// To be removed with get_unit.
495+
#[getter("_unit")]
496+
fn get_internal_unit(&self) -> PyResult<String> {
454497
Ok(self.unit.clone())
455498
}
456499

500+
/// Sets the unit that duration is specified in.
501+
///
502+
/// DEPRECATED since Qiskit 1.3.0 and will be removed in Qiskit 3.0.0
503+
#[setter("unit")]
504+
fn set_unit(&mut self, py: Python, unit: String) -> PyResult<()> {
505+
imports::WARNINGS_WARN.get_bound(py).call1((
506+
intern!(
507+
py,
508+
concat!(
509+
"The property ``qiskit.dagcircuit.dagcircuit.DAGCircuit.unit`` is ",
510+
"deprecated as of Qiskit 1.3.0. It will be removed in Qiskit 3.0.0.",
511+
)
512+
),
513+
py.get_type_bound::<PyDeprecationWarning>(),
514+
1,
515+
))?;
516+
self.set_internal_unit(unit);
517+
Ok(())
518+
}
519+
520+
/// Sets the unit that duration is specified in for internal use (no deprecation warning).
521+
///
522+
/// To be removed with set_unit.
523+
#[setter("_unit")]
524+
fn set_internal_unit(&mut self, unit: String) {
525+
self.unit = unit
526+
}
527+
457528
#[getter]
458529
fn input_map(&self, py: Python) -> PyResult<Py<PyDict>> {
459530
let out_dict = PyDict::new_bound(py);

qiskit/circuit/duration.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,29 @@ def convert_durations_to_dt(qc: QuantumCircuit, dt_in_sec: float, inplace=True):
6565

6666
for instruction in circ.data:
6767
operation = instruction.operation
68-
if operation.unit == "dt" or operation.duration is None:
68+
if operation._unit == "dt" or operation._duration is None:
6969
continue
7070

71-
if not operation.unit.endswith("s"):
72-
raise CircuitError(f"Invalid time unit: '{operation.unit}'")
71+
if not operation._unit.endswith("s"):
72+
raise CircuitError(f"Invalid time unit: '{operation._unit}'")
7373

74-
duration = operation.duration
75-
if operation.unit != "s":
76-
duration = apply_prefix(duration, operation.unit)
74+
duration = operation._duration
75+
if operation._unit != "s":
76+
duration = apply_prefix(duration, operation._unit)
7777

78-
operation.duration = duration_in_dt(duration, dt_in_sec)
79-
operation.unit = "dt"
78+
operation._duration = duration_in_dt(duration, dt_in_sec)
79+
operation._unit = "dt"
8080

81-
if circ.duration is not None and circ.unit != "dt":
82-
if not circ.unit.endswith("s"):
83-
raise CircuitError(f"Invalid time unit: '{circ.unit}'")
81+
if circ._duration is not None and circ._unit != "dt":
82+
if not circ._unit.endswith("s"):
83+
raise CircuitError(f"Invalid time unit: '{circ._unit}'")
8484

85-
duration = circ.duration
86-
if circ.unit != "s":
87-
duration = apply_prefix(duration, circ.unit)
85+
duration = circ._duration
86+
if circ._unit != "s":
87+
duration = apply_prefix(duration, circ._unit)
8888

89-
circ.duration = duration_in_dt(duration, dt_in_sec)
90-
circ.unit = "dt"
89+
circ._duration = duration_in_dt(duration, dt_in_sec)
90+
circ._unit = "dt"
9191

9292
if not inplace:
9393
return circ

qiskit/circuit/quantumcircuit.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,8 +1546,8 @@ def reverse_ops(self) -> "QuantumCircuit":
15461546
for instruction in reversed(self.data):
15471547
reverse_circ._append(instruction.replace(operation=instruction.operation.reverse_ops()))
15481548

1549-
reverse_circ.duration = self.duration
1550-
reverse_circ.unit = self.unit
1549+
reverse_circ._duration = self._duration
1550+
reverse_circ._unit = self._unit
15511551
return reverse_circ
15521552

15531553
def reverse_bits(self) -> "QuantumCircuit":
@@ -2620,8 +2620,8 @@ def _append(self, instruction, qargs=(), cargs=(), *, _standard_gate: bool = Fal
26202620
"""
26212621
if _standard_gate:
26222622
self._data.append(instruction)
2623-
self.duration = None
2624-
self.unit = "dt"
2623+
self._duration = None
2624+
self._unit = "dt"
26252625
return instruction
26262626

26272627
old_style = not isinstance(instruction, CircuitInstruction)
@@ -2643,8 +2643,8 @@ def _append(self, instruction, qargs=(), cargs=(), *, _standard_gate: bool = Fal
26432643
self._data.append_manual_params(instruction, params)
26442644

26452645
# Invalidate whole circuit duration if an instruction is added
2646-
self.duration = None
2647-
self.unit = "dt"
2646+
self._duration = None
2647+
self._unit = "dt"
26482648
return instruction.operation if old_style else instruction
26492649

26502650
@typing.overload
@@ -6584,7 +6584,7 @@ def qubit_start_time(self, *qubits: Union[Qubit, int]) -> float:
65846584
Raises:
65856585
CircuitError: if ``self`` is a not-yet scheduled circuit.
65866586
"""
6587-
if self.duration is None:
6587+
if self._duration is None:
65886588
# circuit has only delays, this is kind of scheduled
65896589
for instruction in self._data:
65906590
if not isinstance(instruction.operation, Delay):
@@ -6626,7 +6626,7 @@ def qubit_stop_time(self, *qubits: Union[Qubit, int]) -> float:
66266626
Raises:
66276627
CircuitError: if ``self`` is a not-yet scheduled circuit.
66286628
"""
6629-
if self.duration is None:
6629+
if self._duration is None:
66306630
# circuit has only delays, this is kind of scheduled
66316631
for instruction in self._data:
66326632
if not isinstance(instruction.operation, Delay):
@@ -6637,7 +6637,7 @@ def qubit_stop_time(self, *qubits: Union[Qubit, int]) -> float:
66376637

66386638
qubits = [self.qubits[q] if isinstance(q, int) else q for q in qubits]
66396639

6640-
stops = {q: self.duration for q in qubits}
6640+
stops = {q: self._duration for q in qubits}
66416641
dones = {q: False for q in qubits}
66426642
for instruction in reversed(self._data):
66436643
for q in qubits:

qiskit/converters/circuit_to_dag.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,6 @@ def circuit_to_dag(circuit, copy_operations=True, *, qubit_order=None, clbit_ord
7373

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

76-
dagcircuit.duration = circuit._duration
77-
dagcircuit.unit = circuit._unit
76+
dagcircuit._duration = circuit._duration
77+
dagcircuit._unit = circuit._unit
7878
return dagcircuit

qiskit/converters/dag_to_circuit.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ def dag_to_circuit(dag, copy_operations=True):
7474
circuit._calibrations_prop = dag._calibrations_prop
7575

7676
circuit._data = circuit_data
77-
78-
circuit._duration = dag.duration
79-
circuit._unit = dag.unit
77+
circuit._duration = dag._duration
78+
circuit._unit = dag._unit
8079
return circuit

qiskit/dagcircuit/dagdependency_v2.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,15 +525,16 @@ def copy_empty_like(self):
525525
target_dag = _DAGDependencyV2()
526526
target_dag.name = self.name
527527
target_dag._global_phase = self._global_phase
528-
target_dag.duration = self.duration
529-
target_dag.unit = self.unit
530528
target_dag.metadata = self.metadata
531529
target_dag._key_cache = self._key_cache
532530
target_dag.comm_checker = self.comm_checker
533531

534532
target_dag.add_qubits(self.qubits)
535533
target_dag.add_clbits(self.clbits)
536534

535+
target_dag.duration = self.duration
536+
target_dag.unit = self.unit
537+
537538
for qreg in self.qregs.values():
538539
target_dag.add_qreg(qreg)
539540
for creg in self.cregs.values():

qiskit/transpiler/passes/scheduling/alap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def run(self, dag):
147147
new_dag._calibrations_prop = dag._calibrations_prop
148148

149149
# set circuit duration and unit to indicate it is scheduled
150-
new_dag.duration = circuit_duration
151-
new_dag.unit = time_unit
150+
new_dag._duration = circuit_duration
151+
new_dag._unit = time_unit
152152

153153
return new_dag

qiskit/transpiler/passes/scheduling/alignments/align_measures.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def run(self, dag: DAGCircuit):
129129
return dag
130130

131131
# if circuit is not yet scheduled, schedule with ALAP method
132-
if dag.duration is None:
132+
if dag._duration is None:
133133
raise TranspilerError(
134134
f"This circuit {dag.name} may involve a delay instruction violating the "
135135
"pulse controller alignment. To adjust instructions to "
@@ -201,8 +201,8 @@ def pad_with_delays(qubits: Iterable[QubitSpecifier], until, unit) -> None:
201201
new_dag.metadata = dag.metadata
202202

203203
# set circuit duration and unit to indicate it is scheduled
204-
new_dag.duration = circuit_duration
205-
new_dag.unit = time_unit
204+
new_dag._duration = circuit_duration
205+
new_dag._unit = time_unit
206206

207207
return new_dag
208208

qiskit/transpiler/passes/scheduling/asap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,6 @@ def run(self, dag):
170170
new_dag._calibrations_prop = dag._calibrations_prop
171171

172172
# set circuit duration and unit to indicate it is scheduled
173-
new_dag.duration = circuit_duration
174-
new_dag.unit = time_unit
173+
new_dag._duration = circuit_duration
174+
new_dag._unit = time_unit
175175
return new_dag

qiskit/transpiler/passes/scheduling/dynamical_decoupling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def run(self, dag):
168168
if len(dag.qregs) != 1 or dag.qregs.get("q", None) is None:
169169
raise TranspilerError("DD runs on physical circuits only.")
170170

171-
if dag.duration is None:
171+
if dag._duration is None:
172172
raise TranspilerError("DD runs after circuit is scheduled.")
173173

174174
durations = self._update_inst_durations(dag)

0 commit comments

Comments
 (0)