Skip to content

Commit

Permalink
feat!: Unify batched execution and sweeper interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
alecandido committed Apr 22, 2024
1 parent 729b8a8 commit ef4863f
Showing 1 changed file with 34 additions and 59 deletions.
93 changes: 34 additions & 59 deletions src/qibolab/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,24 +230,50 @@ def _controller(self):
assert len(controllers) == 1
return controllers[0]

def _execute(self, sequence, options, **kwargs):
def _execute(self, sequence, options, *sweepers, **kwargs):
"""Executes sequence on the controllers."""
result = {}

for instrument in self.instruments.values():
if isinstance(instrument, Controller):
new_result = instrument.play(
self.qubits, self.couplers, sequence, options
self.qubits, self.couplers, sequence, options, *sweepers
)
if isinstance(new_result, dict):
result.update(new_result)

return result

def execute(
self, sequences: List[PulseSequence], options: ExecutionParameters, **kwargs
self,
sequences: List[PulseSequence],
options: ExecutionParameters,
*sweepers: Sweeper,
**kwargs,
):
"""
"""Executes a pulse sequences.
If any sweeper is passed, the execution is performed for the different values of sweeped parameters.
Example:
.. testcode::
import numpy as np
from qibolab.dummy import create_dummy
from qibolab.sweeper import Sweeper, Parameter
from qibolab.pulses import PulseSequence
from qibolab.execution_parameters import ExecutionParameters
platform = create_dummy()
sequence = PulseSequence()
parameter = Parameter.frequency
pulse = platform.create_qubit_readout_pulse(qubit=0)
sequence.append(pulse)
parameter_range = np.random.randint(10, size=10)
sweeper = Sweeper(parameter, parameter_range, [pulse])
platform.execute([sequence], ExecutionParameters(), sweeper)
Args:
sequence (List[:class:`qibolab.pulses.PulseSequence`]): Pulse sequences to execute.
options (:class:`qibolab.platforms.platform.ExecutionParameters`): Object holding the execution options.
Expand All @@ -263,7 +289,9 @@ def execute(
* options.nshots
* NS_TO_SEC
)
log.info(f"Minimal execution time (unrolling): {time}")
for sweep in sweepers:
time *= len(sweep.values)
log.info(f"Minimal execution time: {time}")

# find readout pulses
ro_pulses = {
Expand All @@ -276,7 +304,7 @@ def execute(
bounds = kwargs.get("bounds", self._controller.bounds)
for b in batch(sequences, bounds):
sequence, readouts = unroll_sequences(b, options.relaxation_time)
result = self._execute(sequence, options, **kwargs)
result = self._execute(sequence, options, *sweepers, **kwargs)
for serial, new_serials in readouts.items():
results[serial].extend(result[ser] for ser in new_serials)

Expand All @@ -285,59 +313,6 @@ def execute(

return results

def sweep(
self, sequence: PulseSequence, options: ExecutionParameters, *sweepers: Sweeper
):
"""Executes a pulse sequence for different values of sweeped
parameters.
Useful for performing chip characterization.
Example:
.. testcode::
import numpy as np
from qibolab.dummy import create_dummy
from qibolab.sweeper import Sweeper, Parameter
from qibolab.pulses import PulseSequence
from qibolab.execution_parameters import ExecutionParameters
platform = create_dummy()
sequence = PulseSequence()
parameter = Parameter.frequency
pulse = platform.create_qubit_readout_pulse(qubit=0)
sequence.append(pulse)
parameter_range = np.random.randint(10, size=10)
sweeper = Sweeper(parameter, parameter_range, [pulse])
platform.sweep(sequence, ExecutionParameters(), sweeper)
Returns:
Readout results acquired by after execution.
"""
if options.nshots is None:
options = replace(options, nshots=self.settings.nshots)

if options.relaxation_time is None:
options = replace(options, relaxation_time=self.settings.relaxation_time)

time = (
(sequence.duration + options.relaxation_time) * options.nshots * NS_TO_SEC
)
for sweep in sweepers:
time *= len(sweep.values)
log.info(f"Minimal execution time (sweep): {time}")

result = {}
for instrument in self.instruments.values():
if isinstance(instrument, Controller):
new_result = instrument.sweep(
self.qubits, self.couplers, sequence, options, *sweepers
)
if isinstance(new_result, dict):
result.update(new_result)
return result

def get_qubit(self, qubit):
"""Return the name of the physical qubit corresponding to a logical
qubit.
Expand Down

0 comments on commit ef4863f

Please sign in to comment.