Power-Time Rabi¶
Greetings! In this module, we'll dive into the following topics:
- QUA variables
- Parametric Waveform Generation:
- Amplitude and Duration
- Real-Time Control Flow:
- for-loop
- Out-Bound Data Flow
- Data Processing in the SPU
- Live Data Fetching
Can we jump in?
The QUA program¶
In QUA, the PPU handles variables. These can be fed into instructions and adjusted in real-time based on quantum experiment outcomes or PPU computations. Here we cover the integer t and fixed a variables.
| power_time_rabi.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
- This Python variable is used in the QUA program on line 30, and it used by the PPU to set up the QUA for-loop.
- The declaration of variables follows this syntax. As a good practice, we declare them at the top of the indented context manager block.
The specially designed PPU allows for real-time parametric changes to a pulse during its synthesis. In this context, we're focusing on real-time updates pulse's amplitude and duration for a power-time Rabi experiment.
| power_time_rabi.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
- In the provided code, you can see the syntax for modifying pulse amplitude and duration using
*qua.amp(a)andduration=t, respectively. When*qua.amp(a)is used, the PPU scales the waveform's amplitude based on the QUA variablea. On the other hand, specifyingduration=tprompts the PPU to adjust the pulse's duration through real-time interpolation. Crucially, these adjustments are tied to QUA variables, which means that the scaling of amplitude and stretching of duration can change from one iteration to another. They can even be influenced by quantum measurement outcomes, given that themeasure()function can update QUA variables with new data. It's also important to note that the PPU applies these modifications each time it encounters theplay()command in the thread. Lastly, regardless of the number of for-loops used or the specific values you're adjusting, the utilized waveform and instruction memory remains consistent and minute indeed.
The for-loop in the QM platform allows efficient instruction repetition without consuming extensive waveform and instruction memory. In this code, three nested loops can produce hundreds of thousands of instruction repetitions.
| power_time_rabi.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
- Thanks to the PPU executing pulses very closely to the timing of a pulse sequence, we place the averaging loop as the outermost one which help us to overcome slow frequency drift as you perform your measurement.
*from_array()belongs to ourpy-qua-toolshelper function. The QUA instruction without the helper function looks likewith qua.for_(a, 0.0, a < 1.01, a + 0.01):.
The SPU's operations are designed to minimize the post-processing needed on your computer. As data moves through the SPU pipelines, it's shaped and averaged before being saved to disk and accessed by your computer.
| power_time_rabi.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
-
The
IandQvariables live in the PPU and to pass them to the SPU we usequa.save("I", "I_st"). -
To append SPU operations to the pipeline, you can use the
.followed by the instruction name. Here you find that we are creating a 2D data structure by using two consecutive.buffer(), as well as performing a running-average as the 2D data structures are filled with.average(). Additional instructions, including arithmetic operations, can be found in the SP documentation.
Recall that the SPU and PPU work concurrently, and it is possible to fetch data from the SPU's hard disk concurrently as pipelines continue to be processed.
| power_time_rabi.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
- We're utilizing a helper function from
py-qua-toolscalledfetching_toolto manage the data retrieval. By specifyingmode="live", the function first waits for at least one item to be saved to the SPU's hard drive using.wait_for_value(1)before it proceeds with fetching. This ensures that we don't fetch a value ofNone. - The helper function facilitates live-plotting. Even as the PPU continues to perform quantum experiments in the background, you have the option to halt() the process by closing the pyplot figure.
- By using
results.is_processing(), you can gauge the SPU's processing status, which will either be True or False. When this is combined with a while loop, it makes live-plotting possible. - This line of code retrieves the data stored on the SPU's hard drive and provides it as Python variables for subsequent plotting and analysis.
Other Parametric Waveform Generation Features
The PPU also allows for other waveform modifications such as frequency chirp, truncation, and dynamic port allocation. We emphasize these because they can be executed using the qua.play() command in QUA.
Python for-loop instead of QUA for-loop
When using QUA in Python, it's easy to mistakenly use Python loops like for n in range(n_avg) instead of the QUA loop with qua.for_(n, 0, n < n_avg, n+1):. The Python loop unrolls and sends repeated instructions to the compiler, increasing memory usage. While this might work to some extent, it quickly consumes instruction memory. Using the QUA loop is more memory-efficient as it properly repeats instructions without the extra overhead.
Suggested usage of Python for-loop
Python simplifies the process of writing repetitive QUA instructions that might not be efficiently represented directly in QUA. For instance, to execute qua.play('x180'*qua.amp(a), 'qubit', duration=t) ten times, you can use for i in range(10) instead of copying and pasting. Think of Python as a helper for crafting QUA code. While you're editing on your computer, the actual processing is done in the PPU within your system.
Linking QUA program to Configuration¶
Check the highlighted lines below to see how power_time_rabi.py links to the configuration dictionary. Specifically, line 32 the QUA code qua.play("x180" * qua.amp(a), "qubit", duration=t) directly use the dictionary, and from the analysis of rabi oscillations you will get to calibrate the pulse's amplitude and duration.
The Configuration
-
We associate the
x180operation with a DRAG-gaussian pulse. The parameters for these waveforms are detailed in lines 61 to 63, like the pulse amplitude in volts, the pulse duration in nanoseconds, and the gaussian sigma. -
We first generate a numpy array that outlines the waveform's shape point by point. The sampling rate is set at 1 GSa/sec, matching the DAC's rate.
-
Lines 317 and 318 show how to load custom waveforms. We first set the
typeasarbitrary. Then, we convert the DRAG-gaussian numpy arrays into Python lists to provide thesamples.
Work with any arbitrary waveform
In the Rabi experiment, we used a DRAG-gaussian envelope. However, because you define it in Python and then load it into the quantum machine through configuration, you can actually use any desired arbitrary waveform, such as a flat-top gaussian, as a pulse.
Now it is your turn¶
- Reconfigure the Rabi sequence, place the amplitude sweep as the outer loop, the duration as the middle, and the shots as the innermost loop; then, how should the SPU pipelines be set up to retrieve averaged 2D arrays? Hint: use the information in here.
- Modify the update condition to:
with qua.for_(a, 0, a < a_max, a):(line 31); note that we disabled the update condition. To implement the iterations once again, which QUA code line would you add to the indented instructions? Implement it. - Generate a simplified program to test the following. Instead of using
qua.assign(a, a + da), use the Python commanda += da, and then fetch the results usingqua.save(a, a_st)to your computer. - Instead of using a QUA for-loop for generating
100k shotsin the outer averaging loop (line 30), use a Python loop ->for n in range(100_000). - What occurs if you have
a=7.8and doassign(a, a+1)? Similarly, what happens witha=-7.8when you applyassign(a, a-1)? - What occurs if you have
n=4_294_966_296and doassign(n, n+10_000)? Similarly, what happens withn=-4_294_966_296when you doassign(n, n-10_000)?
Test your knowledge¶
- Consider using flat-top Gaussian pulse instead of a standard Gaussian pulse. In a time-Rabi sequence, if you wish to scan only the flat-top section while maintaining a constant rise and fall, how would you use
durationto achieve it? - If the Gaussian pulse's amplitude is to
0.17 Vin the configuration dictionary, and during a power-Rabi you sweep theaparameter up to1.5, what is the highest voltage measured at the analog outputs? - What would occur if you set the Gaussian pulse amplitude to
0.4 V, and sweep theaparameter up to1.5? - Why do you need to multiply
amplitudes * x180_ampand4 * durationswhen plotting your results in line 109 of the QUA program?
Coming up¶
In the upcoming module, you'll gain a clear understanding of a unique real-time feature of the QM platform: phase updates. This will be demonstrated through the implementation of the Ramsey experiment, where you'll modify the phase of the second x90 pulse while still operating near the qubit resonance frequency.