Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5.28k stars 2.37k forks source link

Transpiler error during execution of circuits with dynamical decoupling on real backends #7317

Closed riddhisw closed 2 years ago

riddhisw commented 2 years ago

Environment

'qiskit-terra': '0.18.3', 'qiskit-aer': '0.9.1', 'qiskit-ignis': '0.6.0', 'qiskit-ibmq-provider': '0.18.1', 'qiskit-aqua': '0.9.5', 'qiskit': '0.32.1', 'qiskit-nature': None, 'qiskit-finance': None, 'qiskit-optimization': None, 'qiskit-machine-learning': None}

What is happening?

A Transpiler Error occurs when executing circuits with dynamical coupling on real backends:

TranspilerError: "This circuit None may involve a delay instruction violating the pulse controller alignment. To adjust instructions to right timing, you should call one of scheduling passes first. This is usually done by calling transpiler with scheduling_method='alap'."

Whether or not these errors occur to be dependent on the type of circuit. For instance, the following circuit executes without errors:

image

But the same test circuit FAILS after adding one extra hadamard on qubit 0: image.

Commenting out the hadmard on qubit 0 will allow the circuit to execute without errors. Changing to backend = FakeMumbai() also executes without errors. Changing optimization level =1to other levels makes no difference. Code fails on multiple real devices (not just IBM mumbai).

How can we reproduce the issue?

The code below

from qiskit.transpiler import PassManager, InstructionDurations
from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling
from qiskit.circuit.library import XGate
from qiskit import QuantumCircuit, transpile, execute, IBMQ 

IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q-internal' , group='performance', project='demos')
realbackend = provider.get_backend('ibmq_mumbai')

circ = QuantumCircuit(4)
circ.cx(0, 1)
circ.cx(2, 3)
circ.h(0) # comment out to run without errors
circ.cx(1, 2)
circ.measure_all()

circ_t = transpile(circ, backend=realbackend,scheduling_method="alap")
dd_sequence = [XGate()] * 2
spacing = []
durations = InstructionDurations.from_backend(realbackend)
pm = PassManager([ALAPSchedule(durations),
                DynamicalDecoupling(durations, dd_sequence, qubits=None, spacing=None)])
circuits = pm.run(circ_t)

job = execute(circuits, realbackend, shots=10)

fails with error:

TranspilerError: "This circuit None may involve a delay instruction violating the pulse controller alignment. To adjust instructions to right timing, you should call one of scheduling passes first. This is usually done by calling transpiler with scheduling_method='alap'."

What should happen?

Code should execute without Transpile errors irrespective of the type of circuit.

Any suggestions?

No response

mtreinish commented 2 years ago

The issue here is in your code, specifically the use of execute() (which combines transpile(qc, backend) and backend.run(qc) into a single function call). What is happening is that you're scheduling your circuit with your custom pass manager first but not adjusting it to the timing constraints on the backend. Then when you call execute() again that's the equivalent of running transpile(circuits, backend) again without specifying a scheduling method. That transpile() call is raising an error telling you you've got a circuit with delays that doesn't comply with the scheduling constraints on the specified backend target and it won't run correctly without scheduling. The suggestion there is that the easiest way to fix this is to use the scheduling method kwarg on transpile() to run the full set of scheduling passes which will adjust the scheduled circuit based on the timing constraints. You have 2 ways you can fix this, either update your code to do:

circuits = pm.run(circuit_t)
job = realbackend.run(transpile(circuits, realbackend, scheduling_method="alap"), shots=10)

or add the timing constraint passes to your custom pass manager. You can see the relevant passes here:

https://github.com/Qiskit/qiskit-terra/blob/main/qiskit/transpiler/preset_passmanagers/level0.py#L213-L244

riddhisw commented 2 years ago

Thanks so much that worked!

mtreinish commented 2 years ago

Ok, then I'll close this issue. But please feel free to reopen it if there is more to discuss on this.

riddhisw commented 2 years ago

I am not sure if this is the same issue but the following code

import qiskit.version
from qiskit.transpiler import PassManager, InstructionDurations
from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling
from qiskit.circuit.library import XGate
from qiskit import QuantumCircuit, transpile, IBMQ 
import qiskit

IBMQ.load_account()
print(qiskit.version.QiskitVersion())

for name in ['ibmq_mumbai', 'ibm_auckland', 'ibm_cairo']: 
    realbackend = provider.get_backend(name)
    config = realbackend.configuration()
    timing_constraints = config.to_dict()['timing_constraints']
    print("Timing constraints for "+name)
    print(timing_constraints)
    print()

    circ = QuantumCircuit(4)
    circ.cx(0, 1)
    circ.cx(2, 3)
    circ.h(0)
    circ.cx(1, 2)
    circ.measure_all()

    circ_t = transpile(circ, backend=realbackend,scheduling_method="alap")
    dd_sequence = [XGate(),XGate()]
    durations = InstructionDurations.from_backend(realbackend)
    pm = PassManager([ALAPSchedule(durations),
                    DynamicalDecoupling(durations, dd_sequence, qubits=None, spacing=None)])
    circuits = pm.run(circ_t)

    try:
        job = realbackend.run(transpile(circuits, realbackend, scheduling_method="alap"), shots=10)
        print(job.result())
    except Exception as ecp:
        print(ecp)

produces the errors on IBM mumbai and auckland but works on cairo


ibmqfactory.load_account:WARNING:2021-12-07 20:13:54,619: Credentials are already in use. The existing account in the session will be replaced.
{'qiskit-terra': '0.18.3', 'qiskit-aer': '0.9.1', 'qiskit-ignis': '0.6.0', 'qiskit-ibmq-provider': '0.18.1', 'qiskit-aqua': '0.9.5', 'qiskit': '0.32.1', 'qiskit-nature': None, 'qiskit-finance': None, 'qiskit-optimization': None, 'qiskit-machine-learning': None}

Timing constraints for ibmq_mumbai
{'acquire_alignment': 16, 'granularity': 16, 'min_length': 64, 'pulse_alignment': 16}
'Unable to retrieve result for job 61b031091e11d5067a6bdcc4. Job has failed: Internal Error. Error code: 9999.'

Timing constraints for ibm_auckland
{'acquire_alignment': 16, 'granularity': 16, 'min_length': 64, 'pulse_alignment': 16}
'Unable to retrieve result for job 61b031873d53f86e8a9e186f. Job has failed: Internal Error. Error code: 9999.'

Timing constraints for ibm_cairo
{'acquire_alignment': 16, 'granularity': 16, 'min_length': 64, 'pulse_alignment': 1}
Result(backend_name='ibm_cairo', backend_version='1.0.17', qobj_id='a365313f-a911-4ae9-b3c4-25b0e06e5978', job_id='61b035d36a8ec054db19b285', success=True, results=[ExperimentResult(shots=10, success=True, meas_level=2, data=ExperimentResultData(counts={'0x0': 4, '0x1': 6}), header=QobjExperimentHeader(clbit_labels=[['meas', 0], ['meas', 1], ['meas', 2], ['meas', 3]], creg_sizes=[['meas', 4]], global_phase=0.0, memory_slots=4, metadata={}, n_qubits=27, name='circuit-9', qreg_sizes=[['q', 27]], qubit_labels=[['q', 0], ['q', 1], ['q', 2], ['q', 3], ['q', 4], ['q', 5], ['q', 6], ['q', 7], ['q', 8], ['q', 9], ['q', 10], ['q', 11], ['q', 12], ['q', 13], ['q', 14], ['q', 15], ['q', 16], ['q', 17], ['q', 18], ['q', 19], ['q', 20], ['q', 21], ['q', 22], ['q', 23], ['q', 24], ['q', 25], ['q', 26]]))], date=2021-12-07 22:09:54-08:00, status=Successful completion, status=QobjHeader(backend_name='ibm_cairo', backend_version='1.0.17'), execution_id='50beb26a-57ed-11ec-9d46-bc97e15b19e6', time_taken=8.261377811431885, error=None, client_version={'qiskit': '0.32.1'})

Manually changing 'pulse_alignment': 1 and passing this as a dictionary setting intiming_constraintsin transpile doesn't help for auckland and mumbai

nonhermitian commented 2 years ago

The error coming back is

Exception: Delays must be a multiple of 16 samples

due to the delay of 712dt on q0

image

nkanazawa1989 commented 2 years ago

Note that you cannot change timing constraints on your side. This is constraints from the control electronics. If your backend says pulse_alignment: 16 currently you cannot use DD pass. So far in all IBM systems this constraint has been 1 meaning you can place your instruction at arbitrary starting time. On the other hand, if this is not 1, the electronics will ask you to start every instruction at multiple of that value. Currently we only have such stretching pass for acquire_alignment https://github.com/Qiskit/qiskit-terra/blob/d9ab98f2b3663b42ba354ed1cd2bc18b3f2cd19d/qiskit/transpiler/passes/scheduling/instruction_alignment.py#L29

Even if you add scheduling pass, no stretching to satisfy the constraint will happen without such alignment pass. However, current implementation of the stretching pass is really inefficient, since quantum circuit is too lazy for the timing context (they don't have t0 and we always need to scan all instructions in DAG to find t0). This may cause non-negligible performance regression in transpilation.

nkanazawa1989 commented 2 years ago

The best (or temporarily) solution for now would be asking the DD pass to check the constraints and insert delays that conform to the pulse alignment constraints. @ajavadia

ajavadia commented 2 years ago

Yeah I think the DD pass should be enhanced to take into account pulse constraints, if a backend reports them. Right now it is agnostic to that, so it can produce delays which violate the control electronics' constraints.

pat-phattharaporn commented 2 years ago

The issue here is in your code, specifically the use of execute() (which combines transpile(qc, backend) and backend.run(qc) into a single function call). What is happening is that you're scheduling your circuit with your custom pass manager first but not adjusting it to the timing constraints on the backend. Then when you call execute() again that's the equivalent of running transpile(circuits, backend) again without specifying a scheduling method. That transpile() call is raising an error telling you you've got a circuit with delays that doesn't comply with the scheduling constraints on the specified backend target and it won't run correctly without scheduling. The suggestion there is that the easiest way to fix this is to use the scheduling method kwarg on transpile() to run the full set of scheduling passes which will adjust the scheduled circuit based on the timing constraints. You have 2 ways you can fix this, either update your code to do:

circuits = pm.run(circuit_t)
job = realbackend.run(transpile(circuits, realbackend, scheduling_method="alap"), shots=10)

or add the timing constraint passes to your custom pass manager. You can see the relevant passes here:

https://github.com/Qiskit/qiskit-terra/blob/main/qiskit/transpiler/preset_passmanagers/level0.py#L213-L244

I tried this on my VQE circuit but it still raised that error. Any suggestion please? (here ansatz_ = pm_dd.run(my_compiled_ansatz))

Screen Shot 2022-01-02 at 3 45 48 PM

This is the error:

Screen Shot 2022-01-02 at 3 46 02 PM
nonhermitian commented 2 years ago

@nkanazawa1989 any progress to report here? The above issue is a pain and hopefully we can squash it soon.

nkanazawa1989 commented 2 years ago

Yes, this actually involves the refactoring of the whole framework in addition to the DD pass. I have updated the behavior of scheduling pass in #7655, and current stage is #7709 which upgrades scheduler pass and introduces BasePadding class which will be new base class of dynamical decoupling pass. Then, DD pass will be upgraded to consider the pulse alignment. Hopefully I can get reviews soon.

ajavadia commented 2 years ago

this should be fixed with #7760

sirgeorgesawcon commented 1 year ago

Hi, Is this issue closed, I am still facing the same error SmartSelect_20230824_010922_Chrome

steps to replicate the error.

SmartSelect_20230824_011227_Chrome

This circuit is a part of Iterative Amplitude Estimation procedure.

SmartSelect_20230824_011331_Chrome

qc is circ_ dd here, basically at the end I made qc = circ_dd

From the above discussion, I get the key point that add the timing constraint passes to your custom pass manager, but how to do that? Since I can't fix it with simply by changing execute to backend.run,

Do I have to use anything else than ALAPScheduler?

Web capture_24-8-2023_132246_qiskit org

Since Qiskit offers all these passes?