DynamicalDecoupling creates sequences of delays not multiple of 16
See original GitHub issueEnvironment
- Qiskit Terra version: 0.20.0
- Python version:
- Operating system:
What is happening?
When running PassManager
with DynamicalDecoupling
the sequence of delays returned are not always multiple of 16 and the resulting circuit cannot be run on real hardware.
How can we reproduce the issue?
from qiskit.quantum_info import Pauli
from qiskit.opflow import PauliOp
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import SuzukiTrotter
from qiskit import QuantumCircuit, transpile, IBMQ
# Dynamical decoupling
from qiskit.circuit.library import XGate
from qiskit.transpiler import PassManager, InstructionDurations
from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling
# load the backend
provider = IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q-internal', group='deployed')
backend = provider.get_backend('ibmq_mumbai')
layout = [0,1,4]
shots = 100000
# data for the pass manager
instruction_durations = InstructionDurations.from_backend(backend)
# functions to create the circuit
def heisenberg_EO(n_qubits):
"""Construct Hamiltonian of 1-D Heisenberg chain with n_qubits sites.
Return a list of matrices corresponding to the even-odd-splitting (154) in
Childs2021.
"""
# Three qubits because for 2 we get H_O = 0
assert n_qubits >= 3
def OPauli(s):
return PauliOp(Pauli(s))
def two_qubit_interaction(i, coeff):
assert i < n_qubits - 1
return (OPauli("I" * i + "XX" + "I" * (n_qubits - 2 - i)) +
OPauli("I" * i + "YY" + "I" * (n_qubits - 2 - i)) +
OPauli("I" * i + "ZZ" + "I" * (n_qubits - 2 - i)) +
OPauli("I" * i + "Z" + "I" * (n_qubits - 1 - i)) *
coeff)
H_E = sum((two_qubit_interaction(i, 1)
for i in range(0, n_qubits - 1, 2)))
H_O = sum((two_qubit_interaction(i, 1)
for i in range(1, n_qubits - 1, 2)))
return [H_E, H_O]
def get_circuit(qubits, evo_time, trotter_steps):
num_qubits = qubits
# Obtain the matrices for Trotter - careful the algorithm returns sometimes the all zero matrix
# minimize ||ms||_1 such that ||a||_1 \leq 2
paulis = heisenberg_EO(num_qubits)
evo_op = PauliEvolutionGate(paulis, evo_time, synthesis=SuzukiTrotter(order=2, reps=trotter_steps))
return evo_op.definition
num_qubits = len(layout) # size of the system
evo_time = 1 # evolution time
m = 1 # number of trotter steps (reduced example)
qc = QuantumCircuit(num_qubits, num_qubits)
qc.h(list(range(num_qubits))) # dummy initial state
qc.append(get_circuit(num_qubits, evo_time, m), list(range(num_qubits)))
qc.measure(range(num_qubits), range(num_qubits))
# transpiled circuit
qct = transpile(qc, backend, initial_layout=layout, optimization_level=2)
# add dynamical decoupling
dd_sequence = [XGate(), XGate()]
pm = PassManager([ALAPSchedule(instruction_durations),
DynamicalDecoupling(instruction_durations, dd_sequence)])
qctd = pm.run(qct)
Printing the values of the DynamicalDecoupling class gives:
slack 9952
spacing [0.25, 0.5, 0.25]
taus [2488, 4976, 2488]
slack 11488
spacing [0.25, 0.5, 0.25]
taus [2872, 5744, 2872]
What should happen?
The taus should all be multiples of 16.
Any suggestions?
From DynamicalDecoupling:
# insert the actual DD sequence
taus = [int(slack * a) for a in self._spacing]
unused_slack = slack - sum(taus) # unused, due to rounding to int multiples of dt
middle_index = int((len(taus) - 1) / 2) # arbitrary: redistribute to middle
taus[middle_index] += unused_slack # now we add up to original delay duration
Even if slack
is a multiple of 16, whenever a
is not an integer there is no assurance that int(slack*a)
will also be a multiple of 16 (e.g. the a
’s in the example above are not integers).
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (5 by maintainers)
Top Results From Across the Web
Robustness of dynamical decoupling sequences - arXiv
Dynamical decoupling (DD) is a promising approach that applies sequences of control pulses to the system in order to reduce the adverse effect...
Read more >Robust dynamical decoupling - Journals
In the present review, we give an overview of this technique and compare different pulse sequences proposed earlier.
Read more >qiskit.transpiler.passes.scheduling.padding.dynamical_decoupling ...
[docs]class PadDynamicalDecoupling(BasePadding): """Dynamical decoupling insertion ... is multiple of 16 dt but the gate length of 36 is not multiple of it.
Read more >Noise-resilient quantum evolution steered by dynamical ...
At the same time, the qubit coherence time is elongated at least 30 fold. The design scheme does not require the dynamical decoupling...
Read more >Effect of pulse error accumulation on dynamical decoupling of ...
delay.15,16 To suppress the effect of system-environment ... not imply good performance of the decoupling sequence,.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
16 is indeed specific to IBM hardware. Other hardware may use different multiples. We should avoid hard-coding multiples of 16, instead this should come from a configuration.
There is a separate pass to align with backend specified timing constraints: https://github.com/Qiskit/qiskit-terra/blob/main/qiskit/transpiler/passes/scheduling/instruction_alignment.py Can you try integrating that into your custom passmanager with dd as I expect it to solve the issue if it’s run after dd.