Qiskit / qiskit-ibm-runtime

IBM Client for Qiskit Runtime
https://docs.quantum.ibm.com/api/qiskit-ibm-runtime
Apache License 2.0
149 stars 154 forks source link

Measurement error mitigation bug when measurements are asynchronous #481

Closed kevincsmith closed 2 years ago

kevincsmith commented 2 years ago

Describe the bug Qiskit Runtime’s built-in measurement error mitigation returns erroneous results if measurements are asynchronously scheduled. In particular, it seems some bits are "dropped" relative to the unmitigated Counts.

Steps to reproduce Here is a minimal example that will reproduce the error. Below the same circuit is transpiled in two different ways -- once using ALAP and once using ASAP scheduling method. Both circuits are then run using the circuit-runner program on ibm_lagos.

    allqc = []

    qc = QuantumCircuit(4,4)
    qc.h(0)
    qc.cnot(0,1)
    qc.h(2)
    qc.cnot(1,2)
    qc.measure(range(0,4),range(0,4))

    #### Circuit 1 -- ALAP scheduling
    allqc.append(transpile(qc,provider.get_backend('ibm_lagos'),scheduling_method='alap',optimization_level=3))

    #### Circuit 2 -- ASAP scheduling
    allqc.append(transpile(qc,provider.get_backend('ibm_lagos'),scheduling_method='asap',optimization_level=3))

    #### Specify inputs and send circuits to the cloud for execution by the circuit-runner program.
    program_inputs = {
            'circuits': allqc,
            'shots': 1024,
            'measurement_error_mitigation': True,
            'skip_transpilation': True}

    options = {'backend_name': 'ibm_lagos'}

    jobsys_run = provider.runtime.run(program_id='circuit-runner',
                                options=options,
                                inputs=program_inputs,
                                result_decoder=RunnerResult
                               )

Expected behavior After execution, I extract both raw and error mitigated counts:

    job = provider.runtime.job(jobID) 
    counts_raw = RunnerResult.from_dict(job.result()).get_counts() 
    counts_mit = RunnerResult.from_dict(job.result()).get_quasiprobabilities()

As expected, counts_raw[0], counts_raw[1] and counts_mit[0] all contain keys with four bits each. counts_mit[1] (corresponding to the ASAP scheduling), however, entirely contains keys with two bits each (see attached screenshots).

I believe the error has to do with the asynchronous measurements when I use the ASAP scheduling -- see attached screenshots for timelines of each scheduled circuit. As a simple test, I repeated the above experiment but used a barrier before the measurement stage for both scheduling methods in order to force all measurements to take place simultaneously. In this case, the error mitigated quasiprobabilities returned the expected results.

One final note which may or may not help -- I have separately observed this same bug when measuring the same qubit multiple times in a single circuit. In this case, the error mitigated quasiprobabilties somehow reduce to just the final measurement.

Any advice on a workaround is much appreciated.

Suggested solutions

Additional Information

Screen Shot 2022-08-17 at 10 18 06 PM Screen Shot 2022-08-17 at 10 18 22 PM

Circuit 1 timeline:

circuit_1

Circuit 2 timeline:

circuit_2

nonhermitian commented 2 years ago

I am guessing this is because your scheduling has added delay operations at the end and the routine thinks those measurements are no longer terminal operations.

kevincsmith commented 2 years ago

Thanks, @nonhermitian. I can confirm that delay operations appear after the first two measurements. Is the measurement error mitigation not intended to work with mid-circuit measurements? If so, is there a suggested workaround?

nonhermitian commented 2 years ago

It can. The tools were developed really before mid circuit measurement was a thing. There is also the issue of how to tell a mid circuit measurement that is not being used to condition a later gate. But that can probably be done as well.

kt474 commented 2 years ago

@nonhermitian when there is a new release of mthree, this should be fixed

nonhermitian commented 2 years ago

This is now fixed in M3 v1.1.0 that has just been released