# Qubit Drive: Rabi & Ramsey Experiments (My Lab)

Cahyati Supriyati Sangaji (My Note)

In this lab, you will take what you learned about qubit drive to perform Rabi and Ramsey experiment on a Pulse Simulator. The goal of this lab is to familiarize yourself with the important concepts of manipulating qubit states with microwave pulses.

Installing Necessary Packages

Before we begin, you will need to install some prerequisites into your environment. Run the cell below to complete these installations. At the end, the cell outputs will be cleared.

!pip install -U qiskit==0.19!pip install -U scipy==1.5.1!pip install -U sympy==1.6.1from IPython.display import clear_outputclear_output()

# Simulating the Transmon as a Duffing Oscillator

The transmon can be understood as a Duffing oscillator specified by a frequency 𝜈, anharmonicity 𝛼, and drive strength 𝑟, which results in the Hamiltonian

# Qiskit Pulse Overview

As a brief overview, Qiskit Pulse schedules (experiments) consist of Instructions (i.e., Play) acting on Channels (i.e., the drive channel). Here is a summary table of available Instructions and Channels:

For more detail, this table summarizes the interaction of the channels with the actual quantum hardware:

However, we find it is more instructive to begin with guided programming in Pulse. Below you will learn how to create pulses, schedules, and run experiments on a simulator. These lessons can be immediately applied to actual pulse-enabled quantum hardware, in particular ibmq_armonk.

# Let’s get started!

In most of the cells below, nothing needs to be modified. However, you will need to execute the cells by pressing shift+Enter in each code block. In order to keep things tidy and focus on the important aspects of Qiskit Pulse, the following cells make use of methods from the helper module. For the gory details, please refer back to the Lab 6 notebook. Before coming to Exercise 1a, the following code blocks

• create backend pulse simulator and instantiate the transmon as a Duffing oscillator of frequency ∼5 GHz
• import libraries for numerics and visualization, and define helpful constants
• create the channels for the pulse schedule and define measurment schedule (we will only work with the drive channel)
# our backend is the Pulse Simulatorfrom resources import helperfrom qiskit.providers.aer import PulseSimulatorbackend_sim = PulseSimulator()# sample duration for pulse instructions dt = 1e-9# create the modelduffing_model = helper.get_transmon(dt)# get qubit frequency from Duffing modelqubit_lo_freq = duffing_model.hamiltonian.get_qubit_lo_from_drift()import numpy as np# visualization toolsimport matplotlib.pyplot as pltplt.style.use('dark_background')# unit conversion factors -> all backend properties returned in SI (Hz, sec, etc)GHz = 1.0e9 # GigahertzMHz = 1.0e6 # MegahertzkHz = 1.0e3 # kilohertzus = 1.0e-6 # microsecondsns = 1.0e-9 # nanoseconds

# Instantiate channels and create measurement schedule

We will use the same measurement schedule throughout, whereas the drive schedules will vary. This must be built for the simulator, for a real backend we can ask for its default measurement pulse.

from qiskit import pulsefrom qiskit.pulse import Play, Acquirefrom qiskit.pulse.pulse_lib import GaussianSquare# qubit to be used throughout the notebookqubit = 0### Collect the necessary channelsdrive_chan = pulse.DriveChannel(qubit)meas_chan = pulse.MeasureChannel(qubit)acq_chan = pulse.AcquireChannel(qubit)# Construct a measurement schedule and add it to an InstructionScheduleMapmeas_samples = 1200meas_pulse = GaussianSquare(duration=meas_samples, amp=0.025, sigma=4, width=1150)measure_sched = Play(meas_pulse, meas_chan) | Acquire(meas_samples, acq_chan, pulse.MemorySlot(qubit))inst_map = pulse.InstructionScheduleMap()inst_map.add('measure', [qubit], measure_sched)# save the measurement/acquire pulse for latermeasure = inst_map.get('measure', qubits=[qubit])

# Graded Exercise 1a: Rabi Schedule

Add code to the method below in order to build a Rabi pulse schedule. A Rabi experiment consists of a drive pulse at the qubit frequency, followed by a measurement. A list of Rabis schedules will vary the drive amplitude each time. For a review of creating pulse schedules, see Lab 6 notebook.

from qiskit.pulse import pulse_libdef build_rabi_pulse_schedule(drive_duration, drive_amp, drive_sigma):    ### create a Rabi schedule (already done)    ### create a Gaussian Rabi pulse using pulse_lib    ### play Rabi pulse on the Rabi schedule and return        rabi_schedule = pulse.Schedule(name='rabi_experiment')        ### WRITE YOUR CODE BETWEEN THESE LINES - START    rabi_pulse = pulse_lib.gaussian(duration=drive_duration, amp=drive_amp,                                     sigma=drive_sigma, name=f"rabi_experiment = {drive_amp}")    rabi_schedule += Play(rabi_pulse, drive_chan)        ### WRITE YOUR CODE BETWEEN THESE LINES - END        # add measurement to rabi_schedule    # << indicates time shift the beginning to the start of the     #    schedule    rabi_schedule += measure << rabi_schedule.duration    return rabi_schedule

# From the Rabi schedule of Exercise 1a, create a list of schedules for the experiment

# Gaussian pulse parameters, with varying amplitudedrive_duration = 128num_rabi_points = 41drive_amps = np.linspace(0, 0.9, num_rabi_points)drive_sigma = 16# now vary the amplitude for each drive amprabi_schedules = []for drive_amp in drive_amps:    rabi_schedules.append(build_rabi_pulse_schedule(drive_duration, drive_amp, drive_sigma))rabi_schedules[-1].draw()
# assemble the schedules into a Qobjfrom qiskit import assemblerabi_qobj = assemble(**helper.get_params('rabi', globals()))answer1a = rabi_qobj# run the simulationrabi_result = backend_sim.run(rabi_qobj, duffing_model).result()# retrieve the data from the experimentrabi_values = helper.get_values_from_result(rabi_result, qubit)

# Fit Results and Plot Rabi Experiment

Once the rough frequency of the qubit is know, the Rabi experiment determines the amplitude of a 𝜋-pulse, that is, the strength of a pulse needed to rotate the qubit around the Bloch sphere from the |0⟩ to |1⟩ states (or vice versa). We assume the rotation axis to be the 𝑥-axis.

fit_params, y_fit = helper.fit_sinusoid(drive_amps, rabi_values, [1, 0, 0.5, 0])plt.scatter(drive_amps, rabi_values, color='white')plt.plot(drive_amps, y_fit, color='red')drive_period = fit_params[2] # get period of rabi oscillationplt.axvline(0, color='red', linestyle='--')plt.axvline(drive_period/2, color='red', linestyle='--')plt.xlabel("Drive amp [a.u.]", fontsize=15)plt.ylabel("Measured signal [a.u.]", fontsize=15)plt.show()print("Pi pulse amplitude is %f"%float(drive_period/2))
# x_90 is a concise way to say pi_over_2; i.e., an X rotation of 90 # degreesx90_pulse = pulse_lib.gaussian(duration=drive_duration,                               amp=drive_period/4,                                sigma=drive_sigma,                               name='x90_pulse')

# Ramsey Experiment

The Ramsey experiment reveals the time dynamics of driving the qubit off-resonantly. In particular, we vary the delay between two 𝜋/2-pulses.

# Ramsey experiment parameterstime_max_us = 0.4time_step_us = 0.0035times_us = np.arange(0.1, time_max_us, time_step_us)# Convert to units of dtdelay_times_dt = times_us * us / dt

# Graded Exercise 1b: Ramsey Schedule

Add code to the method below in order to build a Ramsey pulse schedule. For a review of creating pulse schedules, see Lab 6 notebook.

def build_ramsey_pulse_schedule(delay):    ### create a Ramsey pulse schedule (already done)    ### play an x90 pulse on the drive channel    ### play another x90 pulse after delay    ### add measurement pulse to schedule       ramsey_schedule = pulse.Schedule(name='ramsey_experiment')        ### HINT: include delay by adding it to the duration of the schedule    ###       round delay to nearest integer with int(delay)        ### WRITE YOUR CODE BETWEEN THESE LINES - START    ramsey_schedule += Play(x90_pulse, drive_chan)    ramsey_schedule += Play(x90_pulse, drive_chan) << ramsey_schedule.duration + int(delay)    ramsey_schedule += measure << ramsey_schedule.duration        ### WRITE YOUR CODE BETWEEN THESE LINES - END    return ramsey_schedule# create schedules for Ramsey experiment ramsey_schedules = []for delay in delay_times_dt:    ramsey_schedules.append(build_ramsey_pulse_schedule(delay))ramsey_schedules[-1].draw()
# assemble the schedules into a Qobj# the helper will drive the pulses off-resonantly by an unknown # valueramsey_qobj = assemble(**helper.get_params('ramsey', globals()))answer1b = ramsey_qobj# run the simulationramsey_result = backend_sim.run(ramsey_qobj, duffing_model).result()# retrieve the data from the experimentramsey_values = helper.get_values_from_result(ramsey_result, qubit)# off-resonance componentfit_params, y_fit = helper.fit_sinusoid(times_us, ramsey_values, [1, 0.7, 0.1, 0.25])_, _, ramsey_period_us, _, = fit_params del_f_MHz = 1/ramsey_period_us # freq is MHz since times in usplt.scatter(times_us, np.real(ramsey_values), color='white')plt.plot(times_us, y_fit, color='red', label=f"df = {del_f_MHz:.6f} MHz")plt.xlim(np.min(times_us), np.max(times_us))plt.xlabel('Delay between X90 pulses [$\mu$s]', fontsize=15)plt.ylabel('Measured Signal [a.u.]', fontsize=15)plt.title('Ramsey Experiment', fontsize=15)plt.legend(loc=3)plt.show()print("Drive is off-resonant by %f MHz"%float(del_f_MHz))

# Additional Resources

The Qiskit textbook sections that cover this material are

Watch the videos

References:

Qiskit (Global Summer School), Introduction to Quantum Computing and Quantum Hardware — Lab 6.

## Observability With Istio, Kiali, and Grafana in Kubernetes and Spring Boot

Get the Medium app