From 5030bda59968d3d912c2e15859d036acd30cfaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Mon, 6 May 2024 15:10:32 -0400 Subject: [PATCH] Fix multiple cycles of staggered DD (#1630) * Fix staggered DD with insert_multiple_cycles * release note --------- Co-authored-by: Kevin Tian --- .../passes/scheduling/dynamical_decoupling.py | 8 ++- release-notes/unreleased/1630.bug.rst | 4 ++ .../scheduling/test_dynamical_decoupling.py | 63 +++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 release-notes/unreleased/1630.bug.rst diff --git a/qiskit_ibm_runtime/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_runtime/transpiler/passes/scheduling/dynamical_decoupling.py index f313ebc54..0ef841829 100644 --- a/qiskit_ibm_runtime/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_runtime/transpiler/passes/scheduling/dynamical_decoupling.py @@ -448,9 +448,7 @@ def _pad( seq_length = np.sum(seq_lengths) seq_ratio = self._sequence_min_length_ratios[sequence_idx] spacings = self._spacings[sequence_idx] - alt_spacings = ( - np.asarray(self._alt_spacings[sequence_idx]) if self._coupling_map else None - ) + alt_spacings = self._alt_spacings[sequence_idx] if self._coupling_map else None # Verify the delay duration exceeds the minimum time to insert if time_interval / seq_length <= seq_ratio: @@ -474,8 +472,12 @@ def _pad( seq_lengths = seq_lengths * num_sequences seq_length = np.sum(seq_lengths) spacings = spacings * num_sequences + if alt_spacings is not None: + alt_spacings = alt_spacings * num_sequences spacings = np.asarray(spacings) / num_sequences + if alt_spacings is not None: + alt_spacings = np.asarray(alt_spacings) / num_sequences slack = time_interval - seq_length sequence_gphase = self._sequence_phase diff --git a/release-notes/unreleased/1630.bug.rst b/release-notes/unreleased/1630.bug.rst new file mode 100644 index 000000000..2583c2722 --- /dev/null +++ b/release-notes/unreleased/1630.bug.rst @@ -0,0 +1,4 @@ +Fixed the combination of `insert_multiple_cycles` and `coupling_map` options in + :class:`.PadDynamicalDecoupling`. This combination allows to select staggered + dynamical decoupling with multiple sequence cycles in each delay that crosses + the threshold set by `sequence_min_length_ratios`. \ No newline at end of file diff --git a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py index 932bb0676..efb38e96e 100644 --- a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py +++ b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py @@ -989,6 +989,69 @@ def test_staggered_dd(self): self.assertEqual(qc_dd, expected) + def test_staggered_dd_multiple_cycles(self): + """Test staggered DD with multiple cycles in a single delay""" + dd_sequence = [XGate(), XGate()] + pm = PassManager( + [ + ASAPScheduleAnalysis(self.durations), + PadDynamicalDecoupling( + self.durations, + dd_sequence, + coupling_map=self.coupling_map, + alt_spacings=[0.1, 0.8, 0.1], + sequence_min_length_ratios=[4.0], + insert_multiple_cycles=True, + schedule_idle_qubits=True, + ), + ] + ) + + qc_barriers = QuantumCircuit(3, 1) + qc_barriers.x(0) + qc_barriers.x(1) + qc_barriers.x(2) + qc_barriers.barrier() + qc_barriers.measure(0, 0) + qc_barriers.delay(14, 0) + qc_barriers.x(1) + qc_barriers.x(2) + qc_barriers.barrier() + + qc_dd = pm.run(qc_barriers) + + expected = QuantumCircuit(3, 1) + expected.x(0) + expected.x(1) + expected.x(2) + expected.barrier() + expected.x(1) + expected.delay(80, 1) + expected.x(1) + expected.delay(176, 1) + expected.x(1) + expected.delay(160, 1) + expected.delay(80, 1) + expected.x(1) + expected.delay(176, 1) + expected.x(1) + expected.delay(92, 1) + expected.x(2) + expected.delay(32, 2) + expected.x(2) + expected.delay(304, 2) + expected.x(2) + expected.delay(48, 2) + expected.delay(32, 2) + expected.x(2) + expected.delay(304, 2) + expected.x(2) + expected.delay(44, 2) + expected.measure(0, 0) + expected.delay(14, 0) + expected.barrier() + self.assertEqual(qc_dd, expected) + def test_insert_dd_bad_spacings(self): """Test DD raises when spacings don't add up to 1.""" dd_sequence = [XGate(), XGate()]