From ae94cbb832fe8024e0e09a65038bdca0c3ec340f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:27:30 -0400 Subject: [PATCH 1/9] First draft of staggered DD --- .../passes/scheduling/dynamical_decoupling.py | 83 +++++++++++++++++-- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index 8ad77924c..8aaf7e67b 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -16,6 +16,7 @@ from typing import Dict, List, Optional, Union import numpy as np +import rustworkx as rx from qiskit.circuit import Qubit, Gate from qiskit.circuit.delay import Delay from qiskit.circuit.library.standard_gates import IGate, UGate, U3Gate @@ -26,6 +27,7 @@ from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.instruction_durations import InstructionDurations from qiskit.transpiler.passes.optimization import Optimize1qGates +from qiskit.transpiler import CouplingMap from .block_base_padder import BlockBasePadder @@ -117,6 +119,8 @@ def __init__( extra_slack_distribution: str = "middle", sequence_min_length_ratios: Optional[Union[int, List[int]]] = None, insert_multiple_cycles: bool = False, + coupling_map: CouplingMap = None, + alt_spacings: Optional[Union[List[List[float]], List[float]]] = None, ): """Dynamical decoupling initializer. @@ -133,7 +137,8 @@ def __init__( The available slack will be divided according to this. The list length must be one more than the length of dd_sequence, and the elements must sum to 1. If None, a balanced spacing - will be used [d/2, d, d, ..., d, d, d/2]. + will be used [d/2, d, d, ..., d, d, d/2]. This spacing only applies to the first subcircuit, if a + ``coupling_map`` is specified skip_reset_qubits: If True, does not insert DD on idle periods that immediately follow initialized/reset qubits (as qubits in the ground state are less susceptible to decoherence). @@ -161,6 +166,11 @@ def __init__( insert_multiple_cycles: If the available duration exceeds 2*sequence_min_length_ratio*duration(dd_sequence) enable the insertion of multiple rounds of the dynamical decoupling sequence in that delay. + coupling_map: coupling map for the device. Specifying a coupling map partitions the device into two subcircuits, + in order to stagger the inter-pulse delays between the two. + alt_spacings: A list of lists of spacings between the DD gates, for the second subcircuit, as + determined by the coupling map. If None, a balanced spacing that is staggered with respect + to the first subcircuit will be used [d, d, d, ..., d, d, 0]. Raises: TranspilerError: When invalid DD sequence is specified. TranspilerError: When pulse gate with the duration which is @@ -169,6 +179,7 @@ def __init__( super().__init__() self._durations = durations + # Enforce list of DD sequences if dd_sequences: try: @@ -179,19 +190,35 @@ def __init__( self._qubits = qubits self._skip_reset_qubits = skip_reset_qubits self._alignment = pulse_alignment - + self._coupling_map = coupling_map if spacings is not None: try: iter(spacings[0]) # type: ignore except TypeError: spacings = [spacings] # type: ignore + if alt_spacings is not None: + try: + iter(alt_spacings[0]) # type: ignore + except TypeError: + alt_spacings = [alt_spacings] # type: ignore self._spacings = spacings + self._alt_spacings = alt_spacings if self._spacings and len(self._spacings) != len(self._dd_sequences): raise TranspilerError( "Number of sequence spacings must equal number of DD sequences." ) + if self._alt_spacings: + if not self._coupling_map: + warnings.warn( + "Alternate spacings are ignored because a coupling map was not provided" + ) + elif len(self._alt_spacings) != len(self._dd_sequences): + raise TranspilerError( + "Number of alternate sequence spacings must equal number of DD sequences." + ) + self._extra_slack_distribution = extra_slack_distribution self._dd_sequence_lengths: Dict[Qubit, List[List[Gate]]] = {} @@ -217,9 +244,26 @@ def __init__( def _pre_runhook(self, dag: DAGCircuit) -> None: super()._pre_runhook(dag) + if self._coupling_map: + physical_qubits = [dag.qubits.index(q) for q in dag.qubits] + sub_coupling_map = self._coupling_map.reduce(physical_qubits) + self._coupling_coloring = rx.graph_greedy_color( + sub_coupling_map.graph.to_undirected() + ) + if any(c > 1 for c in self._coupling_coloring.values()): + raise TranspilerError( + "This circuit topology not supported for staggered dynamical decoupling. Maximum connectivity is 3 nearest neighbors per qubit." + ) + spacings_required = self._spacings is None if spacings_required: self._spacings = [] # type: ignore + alt_spacings_required = ( + self._alt_spacings is None and self._coupling_map is not None + ) + print("alt required", alt_spacings_required) + if alt_spacings_required: + self._alt_spacings = [] for seq_idx, seq in enumerate(self._dd_sequences): num_pulses = len(self._dd_sequences[seq_idx]) @@ -242,6 +286,19 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: "of the slack period and sum to 1." ) + if self._coupling_map: + if alt_spacings_required: # TODO: merge final pulse if delay is 0 + mid = 1 / num_pulses + self._alt_spacings.append([mid] * num_pulses + [0]) # type: ignore + else: + if sum(self._alt_spacings[seq_idx]) != 1 or any( # type: ignore + a < 0 for a in self._alt_spacings[seq_idx] + ): + raise TranspilerError( + "The spacings must be given in terms of fractions " + "of the slack period and sum to 1." + ) + # Check if DD sequence is identity if num_pulses != 1: if num_pulses % 2 != 0: @@ -362,7 +419,12 @@ def _pad( seq_lengths = self._dd_sequence_lengths[qubit][sequence_idx] seq_length = np.sum(seq_lengths) seq_ratio = self._sequence_min_length_ratios[sequence_idx] - spacings = self._spacings[sequence_idx] + spacings = np.asarray(self._spacings[sequence_idx]) + alt_spacings = ( + np.asarray(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: @@ -383,18 +445,17 @@ def _pad( # multiple dd sequences may be inserted if num_sequences > 1: dd_sequence = list(dd_sequence) * num_sequences - spacings = spacings * num_sequences seq_lengths = seq_lengths * num_sequences seq_length = np.sum(seq_lengths) - spacings = np.asarray(spacings) / num_sequences + spacings = np.asarray(spacings) slack = time_interval - seq_length sequence_gphase = self._sequence_phase if slack <= 0: continue - if len(dd_sequence) == 1: + if len(dd_sequence) == 1: # TODO: include the case where last delay is 0 # Special case of using a single gate for DD u_inv = dd_sequence[0].inverse().to_matrix() theta, phi, lam, phase = OneQubitEulerDecomposer().angles_and_phase( @@ -431,8 +492,16 @@ def _pad( def _constrained_length(values: np.array) -> np.array: return self._alignment * np.floor(values / self._alignment) + if self._coupling_map: + if self._coupling_coloring[qubit.index] == 0: + sub_spacings = spacings + else: + sub_spacings = alt_spacings + else: + sub_spacings = spacings + # (1) Compute DD intervals satisfying the constraint - taus = _constrained_length(slack * spacings) + taus = _constrained_length(slack * sub_spacings) extra_slack = slack - np.sum(taus) # (2) Distribute extra slack if self._extra_slack_distribution == "middle": From 0b7d30bd4d2060f121fdaeacf046b3960fa3ad08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:34:36 -0400 Subject: [PATCH 2/9] Fix docstring --- .../transpiler/passes/scheduling/dynamical_decoupling.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index 8aaf7e67b..c89de0b9e 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -166,8 +166,8 @@ def __init__( insert_multiple_cycles: If the available duration exceeds 2*sequence_min_length_ratio*duration(dd_sequence) enable the insertion of multiple rounds of the dynamical decoupling sequence in that delay. - coupling_map: coupling map for the device. Specifying a coupling map partitions the device into two subcircuits, - in order to stagger the inter-pulse delays between the two. + coupling_map: directed graph representing the coupling map for the device. Specifying a coupling map partitions the device into subcircuits, + in order to apply DD sequences with different pulse spacings within each. Currently support 2 subcircuits. alt_spacings: A list of lists of spacings between the DD gates, for the second subcircuit, as determined by the coupling map. If None, a balanced spacing that is staggered with respect to the first subcircuit will be used [d, d, d, ..., d, d, 0]. @@ -175,6 +175,8 @@ def __init__( TranspilerError: When invalid DD sequence is specified. TranspilerError: When pulse gate with the duration which is non-multiple of the alignment constraint value is found. + TranspilerError: When alternate spacings are specified without a coupling map. + TranspilerError: When the coupling map is not supported (i.e., if degree > 3) """ super().__init__() @@ -261,7 +263,6 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: alt_spacings_required = ( self._alt_spacings is None and self._coupling_map is not None ) - print("alt required", alt_spacings_required) if alt_spacings_required: self._alt_spacings = [] From 8b35c55941c96678a9cd5f11abc25b6754d4497c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Mon, 3 Apr 2023 13:02:50 -0400 Subject: [PATCH 3/9] First unit test for staggered DD --- .../scheduling/test_dynamical_decoupling.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py index f0701fc4d..4698baa4a 100644 --- a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py +++ b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py @@ -22,6 +22,7 @@ from qiskit.quantum_info import Operator from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.exceptions import TranspilerError +from qiskit.transpiler.coupling import CouplingMap from qiskit_ibm_provider.transpiler.passes.scheduling.dynamical_decoupling import ( PadDynamicalDecoupling, @@ -75,6 +76,8 @@ def setUp(self): ] ) + self.coupling_map = CouplingMap([[0, 1], [1, 2], [2, 3]]) + def test_insert_dd_ghz(self): """Test DD gates are inserted in correct spots.""" dd_sequence = [XGate(), XGate()] @@ -853,3 +856,63 @@ def test_multiple_dd_sequence_cycles(self): expected.x(0) expected.delay(225, 0) self.assertEqual(qc_dd, expected) + + def test_staggered_dd(self): + """Test that timing on DD can be staggered if coupled with each other""" + 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], + ), + ] + ) + + qc_barriers = QuantumCircuit(4, 1) + qc_barriers.x(0) + qc_barriers.x(1) + qc_barriers.x(2) + qc_barriers.x(3) + qc_barriers.barrier() + qc_barriers.measure(0, 0) + qc_barriers.delay(14, 0) + qc_barriers.x(1) + qc_barriers.x(2) + qc_barriers.x(3) + qc_barriers.barrier() + + qc_dd = pm.run(qc_barriers) + + expected = QuantumCircuit(4, 1) + expected.x(0) + expected.x(1) + expected.x(2) + expected.x(3) + expected.barrier() + expected.x(1) + expected.delay(208, 1) + expected.x(1) + expected.delay(448, 1) + expected.x(1) + expected.delay(208, 1) + expected.x(2) + expected.delay(80, 2) # q1-q2 are coupled, staggered delays + expected.x(2) + expected.delay(704, 2) + expected.x(2) + expected.delay(80, 2) # q2-q3 are uncoupled, same delays + expected.x(3) + expected.delay(208, 3) + expected.x(3) + expected.delay(448, 3) + expected.x(3) + expected.delay(208, 3) + expected.measure(0, 0) + expected.delay(14, 0) + expected.barrier() + + self.assertEqual(qc_dd, expected) From 91497d726432ad3fcf127dcdaa16c5ec988b195f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:58:51 -0400 Subject: [PATCH 4/9] Testing bad cases --- .../passes/scheduling/dynamical_decoupling.py | 7 ++- .../scheduling/test_dynamical_decoupling.py | 50 +++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index c89de0b9e..a5994b082 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -175,7 +175,6 @@ def __init__( TranspilerError: When invalid DD sequence is specified. TranspilerError: When pulse gate with the duration which is non-multiple of the alignment constraint value is found. - TranspilerError: When alternate spacings are specified without a coupling map. TranspilerError: When the coupling map is not supported (i.e., if degree > 3) """ @@ -288,12 +287,12 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: ) if self._coupling_map: - if alt_spacings_required: # TODO: merge final pulse if delay is 0 + if alt_spacings_required: mid = 1 / num_pulses self._alt_spacings.append([mid] * num_pulses + [0]) # type: ignore else: if sum(self._alt_spacings[seq_idx]) != 1 or any( # type: ignore - a < 0 for a in self._alt_spacings[seq_idx] + a < 0 for a in self._alt_spacings[seq_idx] ): raise TranspilerError( "The spacings must be given in terms of fractions " @@ -456,7 +455,7 @@ def _pad( if slack <= 0: continue - if len(dd_sequence) == 1: # TODO: include the case where last delay is 0 + if len(dd_sequence) == 1: # Special case of using a single gate for DD u_inv = dd_sequence[0].inverse().to_matrix() theta, phi, lam, phase = OneQubitEulerDecomposer().angles_and_phase( diff --git a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py index 4698baa4a..5d298fda3 100644 --- a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py +++ b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py @@ -916,3 +916,53 @@ def test_staggered_dd(self): 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()] + pm = PassManager( + [ + ASAPScheduleAnalysis(self.durations), + PadDynamicalDecoupling( + self.durations, + dd_sequence, + spacings=[0.1, 0.9, 0.1], + coupling_map=self.coupling_map, + ), + ] + ) + + with self.assertRaises(TranspilerError): + pm.run(self.ghz4) + + def test_insert_dd_bad_alt_spacings(self): + """Test DD raises when alt_spacings don't add up to 1.""" + dd_sequence = [XGate(), XGate()] + pm = PassManager( + [ + ASAPScheduleAnalysis(self.durations), + PadDynamicalDecoupling( + self.durations, + dd_sequence, + alt_spacings=[0.1, 0.9, 0.1], + coupling_map=self.coupling_map, + ), + ] + ) + + def test_unsupported_coupling_map(self): + """Test DD raises if coupling map is not supported.""" + dd_sequence = [XGate(), XGate()] + pm = PassManager( + [ + ASAPScheduleAnalysis(self.durations), + PadDynamicalDecoupling( + self.durations, + dd_sequence, + coupling_map=CouplingMap([[0, 1], [0, 2], [1, 2], [2, 3]]), + ), + ] + ) + + with self.assertRaises(TranspilerError): + pm.run(self.ghz4) From a1615b22ffedd80a378f8d3233e4d12f683cb922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:11:24 -0400 Subject: [PATCH 5/9] Release note --- releasenotes/notes/staggered-dd-95ebe09ebc46f60f.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 releasenotes/notes/staggered-dd-95ebe09ebc46f60f.yaml diff --git a/releasenotes/notes/staggered-dd-95ebe09ebc46f60f.yaml b/releasenotes/notes/staggered-dd-95ebe09ebc46f60f.yaml new file mode 100644 index 000000000..8d17144b1 --- /dev/null +++ b/releasenotes/notes/staggered-dd-95ebe09ebc46f60f.yaml @@ -0,0 +1,9 @@ +--- +upgrade: + - | + For each qubit, add the ability to select one of two different sets of spacings between dynamical decoupling pulses, + based on the input coupling map. +fixes: + - | + Staggered inter-pulse spacings allow the user to disable certain interactions between neighboring qubits by + Refer to `#539 <https://github.com/Qiskit/qiskit-ibm-provider/issues/539>` for more details \ No newline at end of file From 047d0a216faeb8760aab010b12f6c6ccc735c760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Tue, 4 Apr 2023 13:12:16 -0400 Subject: [PATCH 6/9] Bypass some type checking --- .../transpiler/passes/scheduling/dynamical_decoupling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index a5994b082..770123ddc 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -263,7 +263,7 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: self._alt_spacings is None and self._coupling_map is not None ) if alt_spacings_required: - self._alt_spacings = [] + self._alt_spacings = [] # type: ignore for seq_idx, seq in enumerate(self._dd_sequences): num_pulses = len(self._dd_sequences[seq_idx]) @@ -292,7 +292,7 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: self._alt_spacings.append([mid] * num_pulses + [0]) # type: ignore else: if sum(self._alt_spacings[seq_idx]) != 1 or any( # type: ignore - a < 0 for a in self._alt_spacings[seq_idx] + a < 0 for a in self._alt_spacings[seq_idx] # type: ignore ): raise TranspilerError( "The spacings must be given in terms of fractions " From 6826fe34b8e8a97a310e2b5e8fe1cde72e3ac646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:06:31 -0400 Subject: [PATCH 7/9] Missing assert --- .../transpiler/passes/scheduling/dynamical_decoupling.py | 2 ++ .../transpiler/passes/scheduling/test_dynamical_decoupling.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index 770123ddc..15e0bc377 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -192,6 +192,8 @@ def __init__( self._skip_reset_qubits = skip_reset_qubits self._alignment = pulse_alignment self._coupling_map = coupling_map + self._coupling_coloring = None + if spacings is not None: try: iter(spacings[0]) # type: ignore diff --git a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py index 5d298fda3..3eae3feba 100644 --- a/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py +++ b/test/unit/transpiler/passes/scheduling/test_dynamical_decoupling.py @@ -950,6 +950,9 @@ def test_insert_dd_bad_alt_spacings(self): ] ) + with self.assertRaises(TranspilerError): + pm.run(self.ghz4) + def test_unsupported_coupling_map(self): """Test DD raises if coupling map is not supported.""" dd_sequence = [XGate(), XGate()] From e84090f5d68022187b6d1343e465e17c88d1da3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:45:30 -0400 Subject: [PATCH 8/9] Revert list/array confusion First list of spacings must be replicated for each sequence, then the spacings are rescaled as fraction of total delay --- .../transpiler/passes/scheduling/dynamical_decoupling.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index 15e0bc377..ecb8d0211 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -421,7 +421,7 @@ def _pad( seq_lengths = self._dd_sequence_lengths[qubit][sequence_idx] seq_length = np.sum(seq_lengths) seq_ratio = self._sequence_min_length_ratios[sequence_idx] - spacings = np.asarray(self._spacings[sequence_idx]) + spacings = self._spacings[sequence_idx] alt_spacings = ( np.asarray(self._alt_spacings[sequence_idx]) if self._coupling_map @@ -449,8 +449,9 @@ def _pad( dd_sequence = list(dd_sequence) * num_sequences seq_lengths = seq_lengths * num_sequences seq_length = np.sum(seq_lengths) + spacings = spacings * num_sequences - spacings = np.asarray(spacings) + spacings = np.asarray(spacings) / num_sequences slack = time_interval - seq_length sequence_gphase = self._sequence_phase From e9d8bfde4e55eaa519fd6ad15d32fbcad994973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rist=C3=A8?= <10402430+dieris@users.noreply.github.com> Date: Tue, 4 Apr 2023 15:37:44 -0400 Subject: [PATCH 9/9] Formatting --- .../passes/scheduling/dynamical_decoupling.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py index ecb8d0211..51ebc76fe 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/dynamical_decoupling.py @@ -137,8 +137,9 @@ def __init__( The available slack will be divided according to this. The list length must be one more than the length of dd_sequence, and the elements must sum to 1. If None, a balanced spacing - will be used [d/2, d, d, ..., d, d, d/2]. This spacing only applies to the first subcircuit, if a - ``coupling_map`` is specified + will be used [d/2, d, d, ..., d, d, d/2]. This spacing only + applies to the first subcircuit, if a ``coupling_map`` is + specified skip_reset_qubits: If True, does not insert DD on idle periods that immediately follow initialized/reset qubits (as qubits in the ground state are less susceptible to decoherence). @@ -166,11 +167,12 @@ def __init__( insert_multiple_cycles: If the available duration exceeds 2*sequence_min_length_ratio*duration(dd_sequence) enable the insertion of multiple rounds of the dynamical decoupling sequence in that delay. - coupling_map: directed graph representing the coupling map for the device. Specifying a coupling map partitions the device into subcircuits, - in order to apply DD sequences with different pulse spacings within each. Currently support 2 subcircuits. - alt_spacings: A list of lists of spacings between the DD gates, for the second subcircuit, as - determined by the coupling map. If None, a balanced spacing that is staggered with respect - to the first subcircuit will be used [d, d, d, ..., d, d, 0]. + coupling_map: directed graph representing the coupling map for the device. Specifying a + coupling map partitions the device into subcircuits, in order to apply DD sequences + with different pulse spacings within each. Currently support 2 subcircuits. + alt_spacings: A list of lists of spacings between the DD gates, for the second subcircuit, + as determined by the coupling map. If None, a balanced spacing that is staggered with + respect to the first subcircuit will be used [d, d, d, ..., d, d, 0]. Raises: TranspilerError: When invalid DD sequence is specified. TranspilerError: When pulse gate with the duration which is @@ -255,7 +257,8 @@ def _pre_runhook(self, dag: DAGCircuit) -> None: ) if any(c > 1 for c in self._coupling_coloring.values()): raise TranspilerError( - "This circuit topology not supported for staggered dynamical decoupling. Maximum connectivity is 3 nearest neighbors per qubit." + "This circuit topology is not supported for staggered dynamical decoupling." + "The maximum connectivity is 3 nearest neighbors per qubit." ) spacings_required = self._spacings is None