qibolab package#

class qibolab.MetaBackend[source]#

Bases: object

Meta-backend class which takes care of loading the qibolab backend.

static load(platform: str)[source]#

Loads the backend.

Parameters:

platform (str) – Name of the platform to load.

Returns:

The loaded backend.

Return type:

qibo.backends.abstract.Backend

list_available() dict[source]#

Lists all the available qibolab platforms.

class qibolab.QibolabBackend(platform)[source]#

Bases: NumpyBackend

apply_gate(gate, state, nqubits)[source]#

Apply a gate to state vector.

apply_gate_density_matrix(gate, state, nqubits)[source]#

Apply a gate to density matrix.

assign_measurements(measurement_map, readout)[source]#

Assigning measurement outcomes to qibo.states.MeasurementResult for each gate.

This allows properly obtaining the measured shots from the qibolab.Readout object obtaned after pulse sequence execution.

Parameters:
  • measurement_map (dict) – Map from each measurement gate to the sequence of readout pulses implementing it.

  • readout (qibolab.Readout) – Readout result object containing the readout measurement shots. This is created in execute_circuit.

execute_circuit(circuit, initial_state=None, nshots=1000)[source]#

Executes a quantum circuit.

Parameters:
  • circuit (qibo.models.circuit.Circuit) – Circuit to execute.

  • initial_state (qibo.models.circuit.Circuit) – Circuit to prepare the initial state. If None the default |00...0> state is used.

  • nshots (int) – Number of shots to sample from the experiment.

Returns:

MeasurementOutcomes object containing the results acquired from the execution.

execute_circuits(circuits, initial_states=None, nshots=1000)[source]#

Executes multiple quantum circuits with a single communication with the control electronics.

Circuits are unrolled to a single pulse sequence.

Parameters:
  • circuits (list) – List of circuits to execute.

  • initial_states (qibo.models.circuit.Circuit) – Circuit to prepare the initial state. If None the default |00...0> state is used.

  • nshots (int) – Number of shots to sample from the experiment.

Returns:

List of MeasurementOutcomes objects containing the results acquired from the execution of each circuit.

class qibolab.Channel(*, device: str = '', path: str = '')[source]#

Bases: Model

Channel to communicate with the qubit.

device: str#

Name of the device.

path: str#

Physical port addresss within the device.

property port: int#
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'device': FieldInfo(annotation=str, required=False, default=''), 'path': FieldInfo(annotation=str, required=False, default='')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.DcChannel(*, device: str = '', path: str = '')[source]#

Bases: Channel

Channel that can be used to send DC pulses.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'device': FieldInfo(annotation=str, required=False, default=''), 'path': FieldInfo(annotation=str, required=False, default='')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.IqChannel(*, device: str = '', path: str = '', mixer: str | None, lo: str | None)[source]#

Bases: Channel

Channel that can be used to send IQ pulses.

mixer: str | None#

Name of the IQ mixer component corresponding to this channel.

None, if the channel does not have a mixer, or it does not need configuration.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'device': FieldInfo(annotation=str, required=False, default=''), 'lo': FieldInfo(annotation=Union[str, NoneType], required=True), 'mixer': FieldInfo(annotation=Union[str, NoneType], required=True), 'path': FieldInfo(annotation=str, required=False, default='')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

lo: str | None#

Name of the local oscillator component corresponding to this channel.

None, if the channel does not have an LO, or it is not configurable.

class qibolab.AcquisitionChannel(*, device: str = '', path: str = '', twpa_pump: str | None, probe: str | None = None)[source]#

Bases: Channel

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'device': FieldInfo(annotation=str, required=False, default=''), 'path': FieldInfo(annotation=str, required=False, default=''), 'probe': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'twpa_pump': FieldInfo(annotation=Union[str, NoneType], required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

twpa_pump: str | None#

Name of the TWPA pump component.

None, if there is no TWPA, or it is not configurable.

probe: str | None#

Name of the corresponding measure/probe channel.

FIXME: This is temporary solution to be able to relate acquisition channel to corresponding probe channel wherever needed in drivers, until we make acquire channels completely independent, and users start putting explicit acquisition commands in pulse sequence.

qibolab.create_dummy() Platform[source]#

Create a dummy platform using the dummy instrument.

class qibolab.AcquisitionType(value)[source]#

Bases: Enum

Data acquisition from hardware.

DISCRIMINATION = 1#

Demodulate, integrate the waveform and discriminate among states based on the voltages.

INTEGRATION = 2#

Demodulate and integrate the waveform.

RAW = 3#

Acquire the waveform as it is.

SPECTROSCOPY = 4#

Zurich Integration mode for RO frequency sweeps.

class qibolab.AveragingMode(value)[source]#

Bases: Enum

Data averaging modes from hardware.

CYCLIC = 1#

Better averaging for short timescale noise.

SINGLESHOT = 2#

No averaging.

Type:

SINGLESHOT

SEQUENTIAL = 3#

Worse averaging for noise[Avoid]

Type:

SEQUENTIAL

property average: bool#

Whether an average is performed or not.

class qibolab.ConfigKinds[source]#

Bases: object

Registered configuration kinds.

This class is handling the known configuration kinds for deserialization.

Attention

Beware that is managing a global state. This should not be a major issue, as the known configurations should be fixed per run. But prefer avoiding changing them during a single session, unless you are clearly controlling the sequence of all loading operations.

classmethod extend(kinds: Iterable[Any | type[qibolab._core.components.configs.Config]])[source]#

Extend the known configuration kinds.

Nested unions are supported (i.e. Union as elements of kinds).

classmethod reset()[source]#

Reset known configuration kinds to built-ins.

classmethod registered() list[Union[Any, type[qibolab._core.components.configs.Config]]][source]#

Retrieve registered configuration kinds.

classmethod adapted() TypeAdapter[source]#

Construct tailored pydantic type adapter.

The adapter will be able to directly load all the registered configuration kinds as the appropriate Python objects.

qibolab.create_platform(name: str) Platform[source]#

A platform for executing quantum algorithms.

It consists of a quantum processor QPU and a set of controlling instruments.

Parameters:
  • name (str) – name of the platform.

  • path (pathlib.Path) – path with platform serialization

Returns:

The plaform class.

qibolab.locate_platform(name: str, paths: list[pathlib.Path] | None = None) Path[source]#

Locate platform’s path.

The name corresponds to the name of the folder in which the platform is defined, i.e. the one containing the platform.py file.

If paths are specified, the environment is ignored, and the folder search happens only in the specified paths.

class qibolab.Platform(name: str, parameters: ~qibolab._core.parameters.Parameters, instruments: dict[str, qibolab._core.instruments.abstract.Instrument], qubits: dict[typing.Union[int, str], qibolab._core.qubits.Qubit], couplers: dict[typing.Union[int, str], qibolab._core.qubits.Qubit] = <factory>, resonator_type: ~typing.Literal['2D', '3D'] = '2D', is_connected: bool = False)[source]#

Bases: object

Platform for controlling quantum devices.

name: str#

Name of the platform.

parameters: Parameters#

instruments: dict[str, qibolab._core.instruments.abstract.Instrument]#

Mapping instrument names to qibolab.instruments.abstract.Instrument objects.

qubits: dict[Union[int, str], qibolab._core.qubits.Qubit]#

Qubit controllers.

The mapped objects hold the qubit.components.channels.Channel instances required to send pulses addressing the desired qubits.

couplers: dict[Union[int, str], qibolab._core.qubits.Qubit]#

Coupler controllers.

Fully analogue to qubits. Only the flux channel is expected to be populated in the mapped objects.

resonator_type: Literal['2D', '3D'] = '2D'#

Type of resonator (2D or 3D) in the used QPU.

is_connected: bool = False#

Flag for whether we are connected to the physical instruments.

property nqubits: int#

Total number of usable qubits in the QPU.

property pairs: list[tuple[Union[int, str], Union[int, str]]]#

Available pairs in thee platform.

property ordered_pairs#

List of qubit pairs that are connected in the QPU.

property settings: Settings#

Container with default execution settings.

property natives: NativeGates#

Native gates containers.

property sampling_rate#

Sampling rate of control electronics in giga samples per second (GSps).

property components: set[str]#

Names of all components available in the platform.

property channels: dict[str, qibolab._core.components.channels.Channel]#

Channels in the platform.

property qubit_channels: dict[str, Union[int, str]]#

Channel to qubit map.

property coupler_channels#

Channel to coupler map.

config(name: str) Config[source]#

Returns configuration of given component.

connect()[source]#

Connect to all instruments.

disconnect()[source]#

Disconnects from instruments.

execute(sequences: list[qibolab._core.sequence.PulseSequence], sweepers: list[list[qibolab._core.sweeper.Sweeper]] | None = None, **options) dict[int, numpy.ndarray[Any, numpy.dtype[numpy.float64]]][source]#

Execute pulse sequences.

If any sweeper is passed, the execution is performed for the different values of sweeped parameters.

Returns readout results acquired by after execution.

Example

import numpy as np
from qibolab import Parameter, PulseSequence, Sweeper, create_dummy


platform = create_dummy()
qubit = platform.qubits[0]
natives = platform.natives.single_qubit[0]
sequence = natives.MZ.create_sequence()
parameter_range = np.random.randint(10, size=10)
sweeper = [
    Sweeper(
        parameter=Parameter.frequency,
        values=parameter_range,
        channels=[qubit.probe],
    )
]
platform.execute([sequence], [sweeper])
classmethod load(path: Path, instruments: dict[str, qibolab._core.instruments.abstract.Instrument], qubits: dict[Union[int, str], qibolab._core.qubits.Qubit], couplers: dict[Union[int, str], qibolab._core.qubits.Qubit] | None = None, name: str | None = None) Platform[source]#

Dump platform.

dump(path: Path)[source]#

Dump platform.

qubit(qubit: int | str) tuple[Union[int, str], qibolab._core.qubits.Qubit][source]#

Retrieve physical qubit name and object.

Temporary fix for the compiler to work for platforms where the qubits are not named as 0, 1, 2, …

coupler(coupler: int | str) tuple[Union[int, str], qibolab._core.qubits.Qubit][source]#

Retrieve physical coupler name and object.

Temporary fix for the compiler to work for platforms where the couplers are not named as 0, 1, 2, …

qibolab.Waveform#

alias of ndarray[Any, dtype[float64]]

qibolab.IqWaveform#

alias of ndarray[Any, dtype[float64]]

class qibolab.BaseEnvelope[source]#

Bases: ABC, Model

Pulse envelopes.

Generates both i (in-phase) and q (quadrature) components.

i(samples: int) ndarray[Any, dtype[float64]][source]#

In-phase envelope.

q(samples: int) ndarray[Any, dtype[float64]][source]#

Quadrature envelope.

envelopes(samples: int) ndarray[Any, dtype[float64]][source]#

Stacked i and q envelope waveforms of the pulse.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Rectangular(*, kind: Literal['rectangular'] = 'rectangular')[source]#

Bases: BaseEnvelope

Rectangular envelope.

kind: Literal['rectangular']#
i(samples: int) ndarray[Any, dtype[float64]][source]#

Generate a rectangular envelope.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'kind': FieldInfo(annotation=Literal['rectangular'], required=False, default='rectangular')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Exponential(*, kind: Literal['exponential'] = 'exponential', tau: float, upsilon: float, g: float = 0.1)[source]#

Bases: BaseEnvelope

Exponential shape, i.e. square pulse with an exponential decay.

\[\frac{\exp\left(-\frac{x}{\text{upsilon}}\right) + g \exp\left(-\frac{x}{\text{tau}}\right)}{1 + g}\]
kind: Literal['exponential']#
tau: float#

The decay rate of the first exponential function.

In units of the interval duration.

upsilon: float#

The decay rate of the second exponential function.

In units of the interval duration.

g: float#

Weight of the second exponential function.

i(samples: int) ndarray[Any, dtype[float64]][source]#

Generate a combination of two exponential decays.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'g': FieldInfo(annotation=float, required=False, default=0.1), 'kind': FieldInfo(annotation=Literal['exponential'], required=False, default='exponential'), 'tau': FieldInfo(annotation=float, required=True), 'upsilon': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Gaussian(*, kind: Literal['gaussian'] = 'gaussian', rel_sigma: float)[source]#

Bases: BaseEnvelope

Gaussian pulse shape.

Parameters:

rel_sigma (float) –

\[A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}\]
kind: Literal['gaussian']#
rel_sigma: float#

Relative Gaussian standard deviation.

In units of the interval duration.

i(samples: int) ndarray[Any, dtype[float64]][source]#

Generate a Gaussian window.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'kind': FieldInfo(annotation=Literal['gaussian'], required=False, default='gaussian'), 'rel_sigma': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.GaussianSquare(*, kind: Literal['gaussian_square'] = 'gaussian_square', rel_sigma: float, width: float)[source]#

Bases: BaseEnvelope

Rectangular envelope with Gaussian rise and fall.

\[A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Rise] + Flat + A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Decay]\]
kind: Literal['gaussian_square']#
rel_sigma: float#

Relative Gaussian standard deviation.

In units of the interval duration.

width: float#

Length of the flat portion.

i(samples: int) ndarray[Any, dtype[float64]][source]#

Generate a Gaussian envelope, with a flat central window.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'kind': FieldInfo(annotation=Literal['gaussian_square'], required=False, default='gaussian_square'), 'rel_sigma': FieldInfo(annotation=float, required=True), 'width': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Drag(*, kind: Literal['drag'] = 'drag', rel_sigma: float, beta: float)[source]#

Bases: BaseEnvelope

Derivative Removal by Adiabatic Gate (DRAG) pulse envelope.

kind: Literal['drag']#
rel_sigma: float#

Relative Gaussian standard deviation.

In units of the interval duration.

beta: float#

Beta.

i(samples: int) ndarray[Any, dtype[float64]][source]#

Generate a Gaussian envelope.

q(samples: int) ndarray[Any, dtype[float64]][source]#

Generate …

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'beta': FieldInfo(annotation=float, required=True), 'kind': FieldInfo(annotation=Literal['drag'], required=False, default='drag'), 'rel_sigma': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Iir(*, kind: Literal['iir'] = 'iir', a: ndarray[Any, dtype[_ScalarType_co]], b: ndarray[Any, dtype[_ScalarType_co]], target: BaseEnvelope)[source]#

Bases: BaseEnvelope

IIR Filter using scipy.signal lfilter.

https://arxiv.org/pdf/1907.04818.pdf (page 11 - filter formula S22):

p = [A, tau_iir]
p = [b0 = 1−k +k ·α, b1 = −(1−k)·(1−α),a0 = 1 and a1 = −(1−α)]
p = [b0, b1, a0, a1]
kind: Literal['iir']#
a: ndarray[Any, dtype[_ScalarType_co]]#
b: ndarray[Any, dtype[_ScalarType_co]]#
target: BaseEnvelope#
i(samples: int) ndarray[Any, dtype[float64]][source]#
q(samples: int) ndarray[Any, dtype[float64]][source]#

Q. .. todo:

Add docstring
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'a': FieldInfo(annotation=ndarray[Any, dtype[+_ScalarType_co]], required=True, metadata=[PlainValidator(func=<function ndarray_deserialize>, json_schema_input_type=typing.Any), PlainSerializer(func=<function ndarray_serialize>, return_type=<class 'str'>, when_used='always')]), 'b': FieldInfo(annotation=ndarray[Any, dtype[+_ScalarType_co]], required=True, metadata=[PlainValidator(func=<function ndarray_deserialize>, json_schema_input_type=typing.Any), PlainSerializer(func=<function ndarray_serialize>, return_type=<class 'str'>, when_used='always')]), 'kind': FieldInfo(annotation=Literal['iir'], required=False, default='iir'), 'target': FieldInfo(annotation=BaseEnvelope, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Snz(*, kind: Literal['snz'] = 'snz', t_idling: float, b_amplitude: float = 0.5)[source]#

Bases: BaseEnvelope

Sudden variant Net Zero.

https://arxiv.org/abs/2008.07411 (Supplementary materials: FIG. S1.)

kind: Literal['snz']#
t_idling: float#

Fraction of interval where idling.

b_amplitude: float#

Relative B amplitude (wrt A).

i(samples: int) ndarray[Any, dtype[float64]][source]#
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'b_amplitude': FieldInfo(annotation=float, required=False, default=0.5), 'kind': FieldInfo(annotation=Literal['snz'], required=False, default='snz'), 't_idling': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.ECap(*, kind: Literal['ecap'] = 'ecap', alpha: float)[source]#

Bases: BaseEnvelope

ECap pulse envelope.

\[\begin{split}e_{\cap(t,\alpha)} &=& A[1 + \tanh(\alpha t/t_\theta)][1 + \tanh(\alpha (1 - t/t_\theta))]\\ &\times& [1 + \tanh(\alpha/2)]^{-2}\end{split}\]
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'alpha': FieldInfo(annotation=float, required=True), 'kind': FieldInfo(annotation=Literal['ecap'], required=False, default='ecap')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

kind: Literal['ecap']#
alpha: float#

In units of the inverse interval duration.

i(samples: int) ndarray[Any, dtype[float64]][source]#
class qibolab.Custom(*, kind: Literal['custom'] = 'custom', i_: ndarray[Any, dtype[_ScalarType_co]], q_: ndarray[Any, dtype[_ScalarType_co]])[source]#

Bases: BaseEnvelope

Arbitrary envelope.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'i_': FieldInfo(annotation=ndarray[Any, dtype[+_ScalarType_co]], required=True), 'kind': FieldInfo(annotation=Literal['custom'], required=False, default='custom'), 'q_': FieldInfo(annotation=ndarray[Any, dtype[+_ScalarType_co]], required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

kind: Literal['custom']#
i_: ndarray[Any, dtype[_ScalarType_co]]#
q_: ndarray[Any, dtype[_ScalarType_co]]#
i(samples: int) ndarray[Any, dtype[float64]][source]#
q(samples: int) ndarray[Any, dtype[float64]][source]#
class qibolab.Acquisition(*, kind: Literal['acquisition'] = 'acquisition', duration: float)[source]#

Bases: _PulseLike

Acquisition instruction.

This event instructs the device to acquire samples for the event span.

Only valid on an acquisition channel.

kind: Literal['acquisition']#
duration: float#

Duration in ns.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'duration': FieldInfo(annotation=float, required=True), 'kind': FieldInfo(annotation=Literal['acquisition'], required=False, default='acquisition')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Align(*, kind: Literal['align'] = 'align')[source]#

Bases: _PulseLike

Brings different channels at the same point in time.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'kind': FieldInfo(annotation=Literal['align'], required=False, default='align')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

kind: Literal['align']#
class qibolab.Delay(*, kind: Literal['delay'] = 'delay', duration: float)[source]#

Bases: _PulseLike

Wait instruction.

During its length no pulse is sent on the same channel.

Valid on any channel.

kind: Literal['delay']#
duration: float#

Duration in ns.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'duration': FieldInfo(annotation=float, required=True), 'kind': FieldInfo(annotation=Literal['delay'], required=False, default='delay')}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Pulse(*, kind: Literal['pulse'] = 'pulse', duration: float, amplitude: float, envelope: Rectangular | Exponential | Gaussian | GaussianSquare | Drag | Iir | Snz | ECap | Custom, relative_phase: float = 0.0)[source]#

Bases: _PulseLike

A pulse to be sent to the QPU.

Valid on any channel, except acquisition ones.

kind: Literal['pulse']#
duration: float#

Pulse duration.

amplitude: float#

Pulse digital amplitude (unitless).

Pulse amplitudes are normalised between -1 and 1.

envelope: Rectangular | Exponential | Gaussian | GaussianSquare | Drag | Iir | Snz | ECap | Custom#

The pulse envelope shape.

See qibolab.Envelope for list of available shapes.

relative_phase: float#

Relative phase of the pulse, in radians.

i(sampling_rate: float) ndarray[Any, dtype[float64]][source]#

Compute the envelope of the waveform i component.

q(sampling_rate: float) ndarray[Any, dtype[float64]][source]#

Compute the envelope of the waveform q component.

envelopes(sampling_rate: float) ndarray[Any, dtype[float64]][source]#

Compute a tuple with the i and q envelopes.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'amplitude': FieldInfo(annotation=float, required=True), 'duration': FieldInfo(annotation=float, required=True), 'envelope': FieldInfo(annotation=Union[Rectangular, Exponential, Gaussian, GaussianSquare, Drag, Iir, Snz, ECap, Custom], required=True, discriminator='kind'), 'kind': FieldInfo(annotation=Literal['pulse'], required=False, default='pulse'), 'relative_phase': FieldInfo(annotation=float, required=False, default=0.0)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

qibolab.PulseId#

alias of int

class qibolab.Readout(*, kind: Literal['readout'] = 'readout', acquisition: Acquisition, probe: Pulse)[source]#

Bases: _PulseLike

Readout instruction.

This event instructs the device to acquire samples for the event span.

Only valid on an acquisition channel.

kind: Literal['readout']#
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'acquisition': FieldInfo(annotation=Acquisition, required=True), 'kind': FieldInfo(annotation=Literal['readout'], required=False, default='readout'), 'probe': FieldInfo(annotation=Pulse, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

acquisition: Acquisition#
probe: Pulse#
classmethod from_probe(probe: Pulse)[source]#

Create a whole readout operation from its probe pulse.

The acquisition is made to match the same probe duration.

property duration: float#

Duration in ns.

property id: int#

Instruction identifier.

class qibolab.VirtualZ(*, kind: Literal['virtualz'] = 'virtualz', phase: float)[source]#

Bases: _PulseLike

Implementation of Z-rotations using virtual phase.

Only valid on a drive channel.

kind: Literal['virtualz']#
phase: float#

Phase that implements the rotation.

property duration#

Duration of the virtual gate should always be zero.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'kind': FieldInfo(annotation=Literal['virtualz'], required=False, default='virtualz'), 'phase': FieldInfo(annotation=float, required=True)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

class qibolab.Qubit(*, drive: str | None = None, drive_qudits: dict[typing.Annotated[tuple[int, int], BeforeValidator(func=<function _split at 0x7f8bd8807490>, json_schema_input_type=PydanticUndefined), PlainSerializer(func=<function _join at 0x7f8bd8807640>, return_type=PydanticUndefined, when_used='always')], str] = None, flux: str | None = None, probe: str | None = None, acquisition: str | None = None)[source]#

Bases: Model

Representation of a physical qubit.

Contains the channel ids used to control the qubit and is instantiated in the function that creates the corresponding qibolab.Platform

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': False}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

drive: str | None#

Ouput channel, to drive the qubit state.

drive_qudits: dict[typing.Annotated[tuple[int, int], BeforeValidator(func=<function _split at 0x7f8bd8807490>, json_schema_input_type=PydanticUndefined), PlainSerializer(func=<function _join at 0x7f8bd8807640>, return_type=PydanticUndefined, when_used='always')], str]#

Output channels collection, to drive non-qubit transitions.

flux: str | None#

Output channel, to control the qubit flux.

probe: str | None#

Output channel, to probe the resonator.

model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_fields: ClassVar[Dict[str, FieldInfo]] = {'acquisition': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, metadata=[True]), 'drive': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, metadata=[True]), 'drive_qudits': FieldInfo(annotation=dict[Annotated[tuple[int, int], BeforeValidator, PlainSerializer], str], required=False, default_factory=dict, metadata=[False]), 'flux': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, metadata=[True]), 'probe': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, metadata=[True])}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

acquisition: str | None#

Input channel, to acquire the readout results.

property channels: list[str]#
classmethod default(name: int | str, channels: list[str] | None = None, **kwargs)[source]#

Create a qubit with default channel names.

Default channel names follow the convention: ‘{qubit_name}/{channel_type}’

Parameters:
  • name – Name for the qubit to be used for channel ids.

  • channels – List of channels to add to the qubit. If None the following channels will be added: probe, acquisition, drive and flux.

class qibolab.PulseSequence(initlist=None)[source]#

Bases: UserList[tuple[str, Union[Align, Pulse, Delay, VirtualZ, Acquisition, Readout][Union[Align, Pulse, Delay, VirtualZ, Acquisition, Readout]]]]

Synchronized sequence of control instructions across multiple channels.

The sequence is a linear stream of instructions, which may be executed in parallel over multiple channels.

Each instruction is composed by the pulse-like object representing the action, and the channel on which it should be performed.

classmethod load(value: list[tuple[str, Union[qibolab._core.pulses.pulse.Align, qibolab._core.pulses.pulse.Pulse, qibolab._core.pulses.pulse.Delay, qibolab._core.pulses.pulse.VirtualZ, qibolab._core.pulses.pulse.Acquisition, qibolab._core.pulses.pulse.Readout]]])[source]#
property duration: float#

Duration of the entire sequence.

property channels: set[str]#

Channels involved in the sequence.

channel(channel: str) Iterable[Align | Pulse | Delay | VirtualZ | Acquisition | Readout][source]#

Isolate pulses on a given channel.

channel_duration(channel: str) float[source]#

Duration of the given channel.

pulse_channels(pulse_id: int) list[str][source]#

Find channels on which a pulse with a given id plays.

concatenate(other: Iterable[tuple[str, Union[qibolab._core.pulses.pulse.Align, qibolab._core.pulses.pulse.Pulse, qibolab._core.pulses.pulse.Delay, qibolab._core.pulses.pulse.VirtualZ, qibolab._core.pulses.pulse.Acquisition, qibolab._core.pulses.pulse.Readout]]]) None[source]#

Concatenate two sequences.

Appends other in-place such that the result is:
  • self

  • necessary delays to synchronize channels

  • other

Guarantees that the all the channels in the concatenated sequence will start simultaneously

juxtapose(other: Iterable[tuple[str, Union[qibolab._core.pulses.pulse.Align, qibolab._core.pulses.pulse.Pulse, qibolab._core.pulses.pulse.Delay, qibolab._core.pulses.pulse.VirtualZ, qibolab._core.pulses.pulse.Acquisition, qibolab._core.pulses.pulse.Readout]]]) None[source]#

Juxtapose two sequences.

Appends other in-place such that the result is:
  • self

  • necessary delays to synchronize channels

  • other

Guarantee simultaneous start and no overlap.

align(channels: list[str]) Align[source]#

Introduce align commands to the sequence.

align_to_delays() PulseSequence[source]#

Compile align commands to delays.

trim() PulseSequence[source]#

Drop final delays.

The operation is not in place, and does not modify the original sequence.

property acquisitions: list[tuple[str, Union[qibolab._core.pulses.pulse.Readout, qibolab._core.pulses.pulse.Acquisition]]]#

Return list of the readout pulses in this sequence.

Note

This selects only the Acquisition events, and not all the instructions directed to an acquistion channel

class qibolab.Parameter(value)[source]#

Bases: Enum

Sweeping parameters.

frequency = (<enum.auto object>, 'channel')#
amplitude = (<enum.auto object>, 'pulse')#
duration = (<enum.auto object>, 'pulse')#
duration_interpolated = (<enum.auto object>, 'pulse')#
relative_phase = (<enum.auto object>, 'pulse')#
offset = (<enum.auto object>, 'channel')#
classmethod channels() set['Parameter'][source]#

Set of parameters to be swept on the channel.

qibolab.ParallelSweepers#

alias of list[Sweeper]

class qibolab.Sweeper(*, parameter: Parameter, values: ndarray[Any, dtype[_ScalarType_co]] | None = None, range: tuple[float, float, float] | None = None, pulses: list[typing.Annotated[typing.Union[qibolab._core.pulses.pulse.Align, qibolab._core.pulses.pulse.Pulse, qibolab._core.pulses.pulse.Delay, qibolab._core.pulses.pulse.VirtualZ, qibolab._core.pulses.pulse.Acquisition, qibolab._core.pulses.pulse.Readout], FieldInfo(annotation=NoneType, required=True, discriminator='kind')]] | None = None, channels: list[str] | None = None)[source]#

Bases: Model

Data structure for Sweeper object.

This object is passed as an argument to the method qibolab.Platform.execute() which enables the user to sweep a specific parameter for one or more pulses. For information on how to perform sweeps see qibolab.Platform.execute().

Example

import numpy as np
from qibolab import Parameter, PulseSequence, Sweeper, create_dummy


platform = create_dummy()
qubit = platform.qubits[0]
natives = platform.natives.single_qubit[0]
sequence = natives.MZ.create_sequence()
parameter_range = np.random.randint(10, size=10)
sweeper = Sweeper(
    parameter=Parameter.frequency, values=parameter_range, channels=[qubit.probe]
)
platform.execute([sequence], [[sweeper]])
Parameters:
  • parameter – parameter to be swept, possible choices are frequency, attenuation, amplitude, current and gain.

  • values – array of parameter values to sweep over.

  • range – tuple of (start, stop, step) to sweep over the array np.arange(start, stop, step). Can be provided instead of values for more efficient sweeps on some instruments.

  • pulses – list of qibolab.Pulse to be swept.

  • channels – list of channel names for which the parameter should be swept.

parameter: Parameter#
values: ndarray[Any, dtype[_ScalarType_co]] | None#
range: tuple[float, float, float] | None#
pulses: list[typing.Annotated[typing.Union[qibolab._core.pulses.pulse.Align, qibolab._core.pulses.pulse.Pulse, qibolab._core.pulses.pulse.Delay, qibolab._core.pulses.pulse.VirtualZ, qibolab._core.pulses.pulse.Acquisition, qibolab._core.pulses.pulse.Readout], FieldInfo(annotation=NoneType, required=True, discriminator='kind')]] | None#
channels: list[str] | None#
check_values()[source]#
model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}#

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[Dict[str, FieldInfo]] = {'channels': FieldInfo(annotation=Union[list[str], NoneType], required=False, default=None), 'parameter': FieldInfo(annotation=Parameter, required=True), 'pulses': FieldInfo(annotation=Union[list[Annotated[Union[Align, Pulse, Delay, VirtualZ, Acquisition, Readout], FieldInfo(annotation=NoneType, required=True, discriminator='kind')]], NoneType], required=False, default=None), 'range': FieldInfo(annotation=Union[tuple[float, float, float], NoneType], required=False, default=None), 'values': FieldInfo(annotation=Union[ndarray[Any, dtype[+_ScalarType_co]], NoneType], required=False, default=None)}#

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.

This replaces Model.__fields__ from Pydantic V1.

Subpackages#