Qiskit / qiskit-aer

Aer is a high performance simulator for quantum circuits that includes noise models
https://qiskit.github.io/qiskit-aer/
Apache License 2.0
503 stars 361 forks source link

PulseSimulator for ibmq_armonk throwing error when running jobs #1264

Closed epelaaez closed 3 years ago

epelaaez commented 3 years ago

Informations

What is the current behavior?

I'm getting the following status everytime I try to run a job using PulseSimulator from the real backend ibmq_armonk.

Job Status: job incurred error

Steps to reproduce the problem

This is the code I'm trying to run:

from qiskit import pulse, IBMQ
from qiskit.tools.monitor import job_monitor
from qiskit.providers.aer import PulseSimulator

provider = IBMQ.load_account()
backend_name = 'ibmq_armonk'
backend_real = provider.get_backend(backend_name)
backend = PulseSimulator.from_backend(backend_real)

# Some code setting up the schedules

job_params = {
    'meas_level': 1,
    'meas_return': 'avg',
    'shots': 512
}

qobj = assemble(spec01_scheds, backend=backend, **job_params)
spec01_job = backend.run(qobj)
job_monitor(spec01_job)

For some context on the schedules I'm trying to send, this is the code I used to complete exercise 4 from IBM Quantum Challenge. It worked perfectly fine when running on the real device ibmq_jakarta, but now that we don't have access to it, I want to run it locally with a simulator. The code that I'm running to set up the schedules is the exact same as in the notebook here: Transmon qubit.

As I said, this code worked perfectly during the channel, so I guess the problem now is while setting up the backend to run it.

What is the expected behavior?

The job should run correctly and return its results; as it did during the challenge using ibmq_jakarta.

Suggested solutions

I'm not sure if this issue is with how I'm trying to set up the backend or if there is some issue with the PulseSimulator itself. I made sure to follow Qiskit's documentation and tutorials to set up my backend, but there's still the possibility that I messed up while doing it. Let me know if I just made some mistake and there is no issue at all.

DanPuzzuoli commented 3 years ago

@epelaaez thanks for the report.

Could you distill a minimal example from the notebook you linked to? There's a lot going on in that notebook and also the error message in your post doesn't provide any insight. It would be very helpful for getting started identifying the issue.

epelaaez commented 3 years ago

Sure, let me know if this notebook helps.

DanPuzzuoli commented 3 years ago

Sorry to be a pain, but I'm more looking for a single small block of code you can copy into a comment in this thread.

epelaaez commented 3 years ago

No problem at all. This should work.

from qiskit import pulse, IBMQ, assemble
from qiskit.pulse import Play, Schedule, DriveChannel, Gaussian, AcquireChannel
from qiskit.providers.aer import PulseSimulator
from qiskit.tools.monitor import job_monitor
import numpy as np

# Constants and units

job_params = {
    'meas_level': 1,
    'meas_return': 'avg',
    'shots': 512
}

spec_range = 0.300 # GHz
num_spec01_freqs = 71
GHz = 1.0e9 # Gigahertz

# Helper functions

def get_exc_chans(gv):
    return [AcquireChannel(i) for i in range(gv['backend_config'].n_qubits)]

def get_spec01_freqs(center_freqs, qubit):
    center_freq = round(center_freqs[qubit], -8) # 2 significant digits
    return np.linspace(center_freq/GHz - spec_range/2,
        center_freq/GHz + spec_range/2, num_spec01_freqs)

# Set up backend and config

provider = IBMQ.load_account()
backend_name = 'ibmq_armonk'
backend_real = provider.get_backend(backend_name)
backend = PulseSimulator.from_backend(backend_real)

qubit = 0

backend_config = backend.configuration()
exc_chans = get_exc_chans(globals())
dt = backend_config.dt

backend_defaults = backend.defaults()
center_frequency = backend_defaults.qubit_freq_est
inst_sched_map = backend_defaults.instruction_schedule_map 

# |0⟩ -> |1⟩  pulse

# Retrieve calibrated measurement pulse from backend
meas = inst_sched_map.get('measure', qubits=[qubit])

# The same spec pulse for both 01 and 12 spec
drive_amp = 0.25
drive_duration = inst_sched_map.get('x', qubits=[qubit]).duration

# Calibrated backend pulse use advanced DRAG pulse to reduce leakage to the |2> state.
# Here we will use simple Gaussian pulse
drive_sigma = drive_duration // 4 # DRAG pulses typically 4*sigma long. 
spec_pulse = Gaussian(duration=drive_duration, amp=drive_amp, 
                        sigma=drive_sigma, name=f"Spec drive amplitude = {drive_amp}")

# Construct an np array of the frequencies for our experiment
spec_freqs_GHz = get_spec01_freqs(center_frequency, qubit)

# Create the base schedule
# Start with drive pulse acting on the drive channel
spec01_scheds = []
for freq in spec_freqs_GHz:
    with pulse.build(name="Spec Pulse at %.3f GHz" % freq) as spec01_sched:
        with pulse.align_sequential():
            # Pay close attention to this part to solve the problem at the end
            pulse.set_frequency(freq*GHz, DriveChannel(qubit))
            pulse.play(spec_pulse, DriveChannel(qubit))
            pulse.call(meas)

    spec01_scheds.append(spec01_sched)

qobj = assemble(spec01_scheds, backend=backend, **job_params)
spec01_job = backend.run(qobj)
job_monitor(spec01_job)
DanPuzzuoli commented 3 years ago

Okay so the issue is that this schedule has a set frequency instruction, which isn't supported. I think the explicit error associated with this wasn't being raised because I don't think it gets run unless backend.run(qobj).result() is called.

The set/shift frequency instructions are not supported by the pulse simulator - a related issue is #736 . I'm going to put an explicit error into the code explaining this.

epelaaez commented 3 years ago

Oh okay, thanks for the information. Is this feature going to be implemented in the future? Or is there another way I can run set frequency instructions in a simulator rather than a real device?

DanPuzzuoli commented 3 years ago

While it's something that should be implemented at some point, there aren't any plans for doing so currently, as it will likely be somewhat involved and for now the only work being done on the pulse simulator is maintenance.

A way to bypass this issue as a user is to manually add an oscillation to the pulse envelopes. E.g. if the channel's LO frequency is w, but you want to set it to v for a given pulse (or pulses), convert the pulse to an explicit WaveForm specified in terms of a sample list, then multiply the sample array exp(i(v-w)t), where t is the array of associated times. I may be missing some book keeping here but some version of this should work.

epelaaez commented 3 years ago

Thanks!