Qiskit / qiskit-ibm-provider

Qiskit Provider for accessing the IBM Quantum Services: Online Systems and Simulators
https://qiskit.org/ecosystem/ibm-provider/
Apache License 2.0
77 stars 68 forks source link

DD pass adds extra barrier/idling time #458

Closed nsundare closed 1 year ago

nsundare commented 1 year ago

Information

What is the current behavior?

DD pass is moving delay on qubit and adding barrier - resulting in extra idling sequence.

image

Steps to reproduce the problem

# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile
from qiskit.circuit.library import XGate
from qiskit.quantum_info import Operator
from qiskit.transpiler.instruction_durations import InstructionDurations
from qiskit.transpiler.passmanager import PassManager

import qiskit
from qiskit_ibm_provider import IBMProvider
from qiskit_ibm_provider.transpiler.passes.scheduling import DynamicCircuitInstructionDurations, PadDelay, PadDynamicalDecoupling, ALAPScheduleAnalysis

provider_ibm = IBMProvider()
backend = provider_ibm.get_backend("ibm_peekskill", instance= f"{'ibm-q-internal'}/{'performance'}/{'reservations'}")

durations = DynamicCircuitInstructionDurations.from_backend(backend)

dq = QuantumRegister(3, 'dq')
cr = ClassicalRegister(3)

circ = QuantumCircuit(dq)
circ.add_register(cr)

circ.cx(0,1)
circ.cx(2,1)
circ.barrier()
circ.measure(1,cr[0])
circ.x(2).c_if(cr[0],1)
circ.barrier()

circ.measure(0,cr[1])
circ.measure(2,cr[2])

circTranspiled = transpile(circ, backend, initial_layout=[0,1,4], 
                    scheduling_method='alap',optimization_level=3,
                    basis_gates = backend.configuration().basis_gates,
                    instruction_durations=durations)

pm = PassManager([ALAPScheduleAnalysis(durations),
                  PadDynamicalDecoupling(durations, [XGate(), XGate()], 
                  qubits=[0], spacings=None,
                  pulse_alignment=16, 
                  sequence_min_length_ratios=None, 
                  insert_multiple_cycles=False)])

circDD = pm.run(circTranspiled)

What is the expected behavior?

Suggested solutions

kt474 commented 1 year ago

@taalexander can you take a look

taalexander commented 1 year ago

Looking at your code I think the first thing that pops out is that you're passing instruction durations to transpile. I think this is causing Qiskit to use its default scheduling pass which is invalid for dynamic circuit backends and insert a delay during the conditional gate. I think this then interacts with a second problem which is the movement of the delays when scheduling an already scheduled circuit. You can fix this quickly by not scheduling with transpile.

Ie.,

circTranspiled = transpile(circ, backend, initial_layout=[0,1,4], 
                    optimization_level=3,
                    basis_gates = backend.configuration().basis_gates)

I will look at the second problem

taalexander commented 1 year ago

In https://github.com/taalexander/qiskit-ibm-provider/commit/3fa5b982e1b0206894c5bfb9928a6fa68928019c, I've confirmed that the problem is the delays being inserted on idle qubits by the Qiskit default scheduler. These are extending the final schedulable region and are not visible in your plots because you have set idle_wires=False.

IMO, this is not a bug but rather an incompatibility of two scheduling approaches interacting negatively.

nsundare commented 1 year ago

Thank you! This has resolved my issue.

nsundare commented 1 year ago

Slight modification of the circuit by adding Hadamards

image

Is this an issue of not using the right parameters to the DD pass? I don't see why an extra sequence on Q2 is inserted in this case prior to Q1 measurement (this is still ALAP correct?)

taalexander commented 1 year ago

Could you please provide another reproducer?

nsundare commented 1 year ago
# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile
from qiskit.circuit.library import XGate
from qiskit.quantum_info import Operator
from qiskit.transpiler.instruction_durations import InstructionDurations
from qiskit.transpiler.passmanager import PassManager

import qiskit
from qiskit_ibm_provider import IBMProvider
from qiskit_ibm_provider.transpiler.passes.scheduling import DynamicCircuitInstructionDurations, PadDelay, PadDynamicalDecoupling, ALAPScheduleAnalysis

provider_ibm = IBMProvider()
backend = provider_ibm.get_backend("ibm_peekskill", instance= f"{'ibm-q-internal'}/{'performance'}/{'reservations'}")

durations = DynamicCircuitInstructionDurations.from_backend(backend)

dq = QuantumRegister(3, 'dq')
cr = ClassicalRegister(3)

circ = QuantumCircuit(dq)
circ.add_register(cr)

circ.cx(0,1)
circ.cx(2,1)
circ.h(0)
circ.h(2)
circ.barrier()
circ.measure(1,cr[0])
circ.x(2).c_if(cr[0],1)
circ.barrier()

circ.measure(0,cr[1])
circ.measure(2,cr[2])

circTranspiled = transpile(circ, backend, initial_layout=[0,1,4], 
                    optimization_level=3,
                    basis_gates = backend.configuration().basis_gates)

pm = PassManager([ALAPScheduleAnalysis(durations),
                  PadDynamicalDecoupling(durations, [XGate(), XGate()], 
                  qubits=[0,4])])
circDD = pm.run(circTranspiled)
taalexander commented 1 year ago

The second example is a bug 😄 - fixed in https://github.com/Qiskit/qiskit-ibm-provider/pull/460/commits/32b4049eb3d9618ac1dd51740674ac7f45a68b0d