From 9252713e59fe2c621874ca92a32bf1e25bbf6cfe Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Wed, 14 Aug 2024 12:14:10 +0200 Subject: [PATCH] Fix error message upon misalignment in `PadDynamicalDecoupling` (#12952) * Fix misalignment msg * slightly better formatting * typo --- .../scheduling/padding/dynamical_decoupling.py | 12 +++++++++--- ...ix-dd-misalignment-msg-76fe16e5eb4ae670.yaml | 7 +++++++ .../transpiler/test_dynamical_decoupling.py | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/fix-dd-misalignment-msg-76fe16e5eb4ae670.yaml diff --git a/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py b/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py index 8c3ea87c85..0e351161f7 100644 --- a/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +++ b/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py @@ -20,7 +20,7 @@ from qiskit.circuit import Gate, ParameterExpression, Qubit from qiskit.circuit.delay import Delay from qiskit.circuit.library.standard_gates import IGate, UGate, U3Gate from qiskit.circuit.reset import Reset -from qiskit.dagcircuit import DAGCircuit, DAGNode, DAGInNode, DAGOpNode +from qiskit.dagcircuit import DAGCircuit, DAGNode, DAGInNode, DAGOpNode, DAGOutNode from qiskit.quantum_info.operators.predicates import matrix_equal from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer from qiskit.transpiler.exceptions import TranspilerError @@ -331,8 +331,7 @@ class PadDynamicalDecoupling(BasePadding): if time_interval % self._alignment != 0: raise TranspilerError( f"Time interval {time_interval} is not divisible by alignment {self._alignment} " - f"between DAGNode {prev_node.name} on qargs {prev_node.qargs} and {next_node.name} " - f"on qargs {next_node.qargs}." + f"between {_format_node(prev_node)} and {_format_node(next_node)}." ) if not self.__is_dd_qubit(dag.qubits.index(qubit)): @@ -430,3 +429,10 @@ class PadDynamicalDecoupling(BasePadding): else: params.append(p) return tuple(params) + + +def _format_node(node: DAGNode) -> str: + """Util to format the DAGNode, DAGInNode, and DAGOutNode.""" + if isinstance(node, (DAGInNode, DAGOutNode)): + return f"{node.__class__.__name__} on qarg {node.wire}" + return f"DAGNode {node.name} on qargs {node.qargs}" diff --git a/releasenotes/notes/fix-dd-misalignment-msg-76fe16e5eb4ae670.yaml b/releasenotes/notes/fix-dd-misalignment-msg-76fe16e5eb4ae670.yaml new file mode 100644 index 0000000000..4634fe48ae --- /dev/null +++ b/releasenotes/notes/fix-dd-misalignment-msg-76fe16e5eb4ae670.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixed a bug in :class:`.PadDynamicalDecoupling`, which previously + did not correctly display the error message that a delay is not + pulse-aligned, if the previous or following node was an input/output + node. Now, the error message is correctly displayed. diff --git a/test/python/transpiler/test_dynamical_decoupling.py b/test/python/transpiler/test_dynamical_decoupling.py index 5f11ede3a3..38c5c3c2d4 100644 --- a/test/python/transpiler/test_dynamical_decoupling.py +++ b/test/python/transpiler/test_dynamical_decoupling.py @@ -1051,6 +1051,23 @@ class TestPadDynamicalDecoupling(QiskitTestCase): self.assertEqual(qc.global_phase + np.pi, pm.run(qc).global_phase) + def test_misalignment_at_boundaries(self): + """Test the correct error message is raised for misalignments at In/Out nodes.""" + # a circuit where the previous node is DAGInNode, and the next DAGOutNode + circuit = QuantumCircuit(1) + circuit.delay(101) + + dd_sequence = [XGate(), XGate()] + pm = PassManager( + [ + ALAPScheduleAnalysis(self.durations), + PadDynamicalDecoupling(self.durations, dd_sequence, pulse_alignment=2), + ] + ) + + with self.assertRaises(TranspilerError): + _ = pm.run(circuit) + if __name__ == "__main__": unittest.main()