Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify execution interface #861

Merged
merged 17 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ platform.connect()

# Execute a pulse sequence
options = ExecutionParameters(nshots=1000)
results = platform.execute_pulse_sequence(sequence, options)
results = platform.execute([sequence], options)

# Print the acquired shots
print(results.samples)
Expand Down
4 changes: 2 additions & 2 deletions doc/source/getting-started/experiment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,10 @@ We leave to the dedicated tutorial a full explanation of the experiment, but her
acquisition_type=AcquisitionType.INTEGRATION,
)

results = platform.sweep(sequence, options, sweeper)
results = platform.execute([sequence], options, sweeper)

# plot the results
amplitudes = results[ro_pulse.id].magnitude
amplitudes = results[ro_pulse.id][0].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + ro_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down
23 changes: 10 additions & 13 deletions doc/source/main-documentation/qibolab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In the platform, the main methods can be divided in different sections:

- functions save and change qubit parameters (``dump``, ``update``)
- functions to coordinate the instruments (``connect``, ``setup``, ``disconnect``)
- functions to execute experiments (``execute_pulse_sequence``, ``execute_pulse_sequences``, ``sweep``)
- a unique interface to execute experiments (``execute``)
- functions to initialize gates (``create_RX90_pulse``, ``create_RX_pulse``, ``create_CZ_pulse``, ``create_MZ_pulse``, ``create_qubit_drive_pulse``, ``create_qubit_readout_pulse``, ``create_RX90_drag_pulse``, ``create_RX_drag_pulse``)
- setters and getters of channel/qubit parameters (local oscillator parameters, attenuations, gain and biases)

Expand Down Expand Up @@ -86,7 +86,7 @@ Now we can execute the sequence on hardware:
acquisition_type=AcquisitionType.INTEGRATION,
averaging_mode=AveragingMode.CYCLIC,
)
results = platform.execute_pulse_sequence(ps, options=options)
results = platform.execute([ps], options=options)

Finally, we can stop instruments and close connections.

Expand Down Expand Up @@ -390,7 +390,7 @@ When conducting experiments on quantum hardware, pulse sequences are vital. Assu

.. testcode:: python

result = platform.execute_pulse_sequence(sequence, options=options)
result = platform.execute([sequence], options=options)

Lastly, when conducting an experiment, it is not always required to define a pulse from scratch.
Usual pulses, such as pi-pulses or measurements, are already defined in the platform runcard and can be easily initialized with platform methods.
Expand All @@ -415,7 +415,7 @@ Typical experiments may include both pre-defined pulses and new ones:
)
sequence.append(platform.create_MZ_pulse(0))

results = platform.execute_pulse_sequence(sequence, options=options)
results = platform.execute([sequence], options=options)

.. note::

Expand Down Expand Up @@ -496,7 +496,7 @@ A tipical resonator spectroscopy experiment could be defined with:
type=SweeperType.OFFSET,
)

results = platform.sweep(sequence, options, sweeper)
results = platform.execute([sequence], options, sweeper)

.. note::

Expand Down Expand Up @@ -543,7 +543,7 @@ For example:
type=SweeperType.FACTOR,
)

results = platform.sweep(sequence, options, sweeper_freq, sweeper_amp)
results = platform.execute([sequence], options, sweeper_freq, sweeper_amp)

Let's say that the RX pulse has, from the runcard, a frequency of 4.5 GHz and an amplitude of 0.3, the parameter space probed will be:

Expand All @@ -562,8 +562,7 @@ In the course of several examples, you've encountered the ``options`` argument i

.. testcode:: python

res = platform.execute_pulse_sequence(sequence, options=options)
res = platform.sweep(sequence, options=options)
res = platform.execute([sequence], options=options)

Let's now delve into the details of the ``options`` parameter and understand its components.

Expand Down Expand Up @@ -636,7 +635,7 @@ Let's now delve into a typical use case for result objects within the qibolab fr
averaging_mode=AveragingMode.CYCLIC,
)

res = platform.execute_pulse_sequence(sequence, options=options)
res = platform.execute([sequence], options=options)

The ``res`` object will manifest as a dictionary, mapping the measurement pulse serial to its corresponding results.

Expand Down Expand Up @@ -734,10 +733,8 @@ Instruments all implement a set of methods:
- setup
- disconnect

While the controllers, the main instruments in a typical setup, add other two methods:

- execute_pulse_sequence
- sweep
While the controllers, the main instruments in a typical setup, add another, i.e.
execute.

Some more detail on the interal functionalities of instruments is given in :doc:`/tutorials/instrument`

Expand Down
20 changes: 10 additions & 10 deletions doc/source/tutorials/calibration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ We then define the execution parameters and launch the experiment.
acquisition_type=AcquisitionType.INTEGRATION,
)

results = platform.sweep(sequence, options, sweeper)
results = platform.execute([sequence], options, sweeper)

In few seconds, the experiment will be finished and we can proceed to plot it.

.. testcode:: python

import matplotlib.pyplot as plt

amplitudes = results[readout_pulse.id].magnitude
amplitudes = results[readout_pulse.id][0].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + readout_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down Expand Up @@ -153,9 +153,9 @@ We can now proceed to launch on hardware:
acquisition_type=AcquisitionType.INTEGRATION,
)

results = platform.sweep(sequence, options, sweeper)
results = platform.execute([sequence], options, sweeper)

amplitudes = results[readout_pulse.id].magnitude
amplitudes = results[readout_pulse.id][0].magnitude
frequencies = np.arange(-2e8, +2e8, 1e6) + drive_pulse.frequency

plt.title("Resonator Spectroscopy")
Expand Down Expand Up @@ -239,20 +239,20 @@ and its impact on qubit states in the IQ plane.
acquisition_type=AcquisitionType.INTEGRATION,
)

results_one = platform.execute_pulse_sequence(one_sequence, options)
results_zero = platform.execute_pulse_sequence(zero_sequence, options)
results_one = platform.execute([one_sequence], options)
results_zero = platform.execute([zero_sequence], options)

plt.title("Single shot classification")
plt.xlabel("I [a.u.]")
plt.ylabel("Q [a.u.]")
plt.scatter(
results_one[readout_pulse1.id].voltage_i,
results_one[readout_pulse1.id].voltage_q,
results_one[readout_pulse1.id][0].voltage_i,
results_one[readout_pulse1.id][0].voltage_q,
label="One state",
)
plt.scatter(
results_zero[readout_pulse2.id].voltage_i,
results_zero[readout_pulse2.id].voltage_q,
results_zero[readout_pulse2.id][0].voltage_i,
results_zero[readout_pulse2.id][0].voltage_q,
label="Zero state",
)
plt.show()
Expand Down
2 changes: 1 addition & 1 deletion doc/source/tutorials/pulses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pulse sequence according to the number of shots ``nshots`` specified.

# Executes a pulse sequence.
options = ExecutionParameters(nshots=1000, relaxation_time=100)
results = platform.execute_pulse_sequence(sequence, options=options)
results = platform.execute([sequence], options=options)

# Disconnect from the instruments
platform.disconnect()
Expand Down
2 changes: 1 addition & 1 deletion examples/minimum_working_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# Connects to lab instruments using the details specified in the calibration settings.
platform.connect()
# Executes a pulse sequence.
results = platform.execute_pulse_sequence(sequence, nshots=3000)
results = platform.execute([sequence], nshots=3000)
print(f"results (amplitude, phase, i, q): {results}")
# Disconnect from the instruments
platform.disconnect()
4 changes: 2 additions & 2 deletions examples/qibolab_v017_1Q_emulator_test_QuTiP.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
"\n",
"# Execute the pulse sequence and save the output\n",
"options = ExecutionParameters(nshots=1000)\n",
"results = emulator_platform.execute_pulse_sequence(sequence, options=options)"
"results = emulator_platform.execute([sequence], options=options)"
]
},
{
Expand Down Expand Up @@ -454,7 +454,7 @@
"id": "08e1c8ee-8076-47ee-a05a-bcc068d681d0",
"metadata": {},
"source": [
"The simulation results generated by the simulation engine are returned together with the usual outputs of `execute_pulse_sequence` for device platforms and are grouped under 'simulation'. \n",
"The simulation results generated by the simulation engine are returned together with the usual outputs of `execute` for device platforms and are grouped under 'simulation'. \n",
"\n",
"Let us retrieve the simulation results obtained previously:"
]
Expand Down
10 changes: 4 additions & 6 deletions src/qibolab/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ def execute_circuit(self, circuit, initial_state=None, nshots=1000):
if not self.platform.is_connected:
self.platform.connect()

readout = self.platform.execute_pulse_sequence(
sequence,
readout_ = self.platform.execute(
[sequence],
ExecutionParameters(nshots=nshots),
)
readout = {k: v[0] for k, v in readout_.items()}

self.platform.disconnect()

Expand Down Expand Up @@ -147,10 +148,7 @@ def execute_circuits(self, circuits, initial_states=None, nshots=1000):
if not self.platform.is_connected:
self.platform.connect()

readout = self.platform.execute_pulse_sequences(
sequences,
ExecutionParameters(nshots=nshots),
)
readout = self.platform.execute(sequences, ExecutionParameters(nshots=nshots))

self.platform.disconnect()

Expand Down
12 changes: 3 additions & 9 deletions src/qibolab/instruments/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,11 @@ def ports(self, port_name, *args, **kwargs):
def play(self, *args, **kwargs):
"""Play a pulse sequence and retrieve feedback.

Returns:
(Dict[ResultType]) mapping the serial of the readout pulses used to
the acquired :class:`qibolab.result.ExecutionResults` object.
"""

@abstractmethod
def sweep(self, *args, **kwargs):
"""Play a pulse sequence while sweeping one or more parameters.
If :cls:`qibolab.sweeper.Sweeper` objects are passed as arguments, they are
executed in real-time. If not possible, an error is raised.

Returns:
(dict) mapping the serial of the readout pulses used to
(Dict[ResultType]) mapping the serial of the readout pulses used to
the acquired :class:`qibolab.result.ExecutionResults` object.
"""

Expand Down
21 changes: 0 additions & 21 deletions src/qibolab/instruments/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,27 +120,6 @@ def play(
couplers: Dict[QubitId, Coupler],
sequence: PulseSequence,
options: ExecutionParameters,
):
exp_points = (
1 if options.averaging_mode is AveragingMode.CYCLIC else options.nshots
)
shape = (exp_points,)
results = {}

for ro_pulse in sequence.ro_pulses:
values = np.squeeze(self.get_values(options, ro_pulse, shape))
results[ro_pulse.qubit] = results[ro_pulse.id] = options.results_type(
values
)

return results

def sweep(
self,
qubits: Dict[QubitId, Qubit],
couplers: Dict[QubitId, Coupler],
sequence: PulseSequence,
options: ExecutionParameters,
*sweepers: List[Sweeper],
):
results = {}
Expand Down
Loading
Loading