qoolqit
qoolqit
Section titled “
qoolqit
”A Python library for algorithm development in the Rydberg Analog Model.
Modules:
-
devices– -
drive– -
embedding–Collection of graph and matrix embedding algorithms.
-
exceptions– -
execution–Execute quantum programs on QPUs or local/remote emulators.
-
graphs–Graph creation and manipulation in QoolQit.
-
program– -
register– -
waveforms–Composable, time-bounded scalar waveforms for pulse-level quantum control.
Classes:
-
AnalogDevice–A realistic device for analog sequence execution.
-
AnalogDeviceWithDMM–A realistic device with DMM for analog sequence execution.
-
BlackmanWaveform–A Blackman window of a specified duration and area under the curve.
-
ConstantWaveform–A constant waveform over a given duration.
-
DelayWaveform–An empty waveform.
-
Device–QoolQit Device wrapper around a Pulser BaseDevice.
-
DigitalAnalogDevice–A device with digital and analog capabilities.
-
Drive–The drive Hamiltonian acting over a duration.
-
InterpolatedWaveform–A waveform created from shape-preserving interpolation of data points.
-
MockDevice–A virtual device for unconstrained prototyping.
-
PiecewiseLinearWaveform–A piecewise linear waveform.
-
QuantumProgram–A program representing a Sequence acting on a Register of qubits.
-
RampWaveform–A ramp that linearly interpolates between an initial and final value.
-
Register–A QoolQit register mapping qubit IDs to 2D coordinates.
-
SequenceCompiler–Compiles a QoolQit Register and Drive to a Device.
Functions:
-
available_default_devices–Show the default available devices in QooQit.
AnalogDevice
Section titled “
AnalogDevice
”AnalogDevice()A realistic device for analog sequence execution.
Methods:
-
from_connection–Return the specified device from the selected device from a connection.
-
info–Show the device short description and constraints.
-
reset_converter–Resets the unit converter to the default one.
-
set_distance_unit–Changes the unit converter according to a reference distance unit.
-
set_energy_unit–Changes the unit converter according to a reference energy unit.
Attributes:
-
specs(dict[str, float | None]) –Return the device specification constraints.
Source code in qoolqit/devices/device.py
def __init__(self) -> None: super().__init__(pulser_device=pulser.AnalogDevice)
specs
property
Section titled “
specs
property
”specs: dict[str, float | None]Return the device specification constraints.
from_connection
classmethod
Section titled “
from_connection
classmethod
”from_connection( connection: RemoteConnection, name: str) -> Device (qoolqit.devices.device.Device)" href="#qoolqit.Device">DeviceReturn the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with
the connection.fetch_available_devices() method.
Parameters:
-
connection(RemoteConnection) –connection object to fetch the available devices.
-
name(str) –The name of the desired device.
Returns:
-
Device(Device) –The requested device.
Raises:
-
ValueError–If the requested device is not available through the provided connection.
Example:
from pasqal_cloud import PasqalCloudConnectionfresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL")Source code in qoolqit/devices/device.py
@classmethoddef from_connection(cls, connection: RemoteConnection, name: str) -> Device: """Return the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with the `connection.fetch_available_devices()` method.
Args: connection (RemoteConnection): connection object to fetch the available devices. name (str): The name of the desired device.
Returns: Device: The requested device.
Raises: ValueError: If the requested device is not available through the provided connection.
Example: ```python from pasqal_cloud import PasqalCloudConnection fresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL") ``` """ available_remote_devices = connection.fetch_available_devices() if name not in available_remote_devices: raise ValueError(f"Device {name} is not available through the provided connection.") pulser_device = available_remote_devices[name] return cls(pulser_device=pulser_device)info() -> NoneShow the device short description and constraints.
Source code in qoolqit/devices/device.py
def info(self) -> None: """Show the device short description and constraints.""" print(self)
reset_converter
Section titled “
reset_converter
”reset_converter() -> NoneResets the unit converter to the default one.
Source code in qoolqit/devices/device.py
def reset_converter(self) -> None: """Resets the unit converter to the default one.""" # Create a NEW converter so mutations don't persist. self._converter = self._default_converter
set_distance_unit
Section titled “
set_distance_unit
”set_distance_unit(distance: float) -> NoneChanges the unit converter according to a reference distance unit.
Source code in qoolqit/devices/device.py
def set_distance_unit(self, distance: float) -> None: """Changes the unit converter according to a reference distance unit.""" self.converter.factors = self.converter.factors_from_distance(distance)
set_energy_unit
Section titled “
set_energy_unit
”set_energy_unit(energy: float) -> NoneChanges the unit converter according to a reference energy unit.
Source code in qoolqit/devices/device.py
def set_energy_unit(self, energy: float) -> None: """Changes the unit converter according to a reference energy unit.""" self.converter.factors = self.converter.factors_from_energy(energy)
AnalogDeviceWithDMM
Section titled “
AnalogDeviceWithDMM
”AnalogDeviceWithDMM()A realistic device with DMM for analog sequence execution.
Methods:
-
from_connection–Return the specified device from the selected device from a connection.
-
info–Show the device short description and constraints.
-
reset_converter–Resets the unit converter to the default one.
-
set_distance_unit–Changes the unit converter according to a reference distance unit.
-
set_energy_unit–Changes the unit converter according to a reference energy unit.
Attributes:
-
specs(dict[str, float | None]) –Return the device specification constraints.
Source code in qoolqit/devices/device.py
def __init__(self) -> None: dmm_channel = pulser.channels.dmm.DMM( clock_period=4, min_duration=16, max_duration=6000, mod_bandwidth=8, bottom_detuning=-2 * math.pi * 20, total_bottom_detuning=-2 * math.pi * 20, ) # Create a virtual device that can be modified to add a DMM channel. pulser_virtual_device = pulser.AnalogDevice.to_virtual() pulser_device = replace( pulser_virtual_device, dmm_objects=(dmm_channel,), name="AnalogDeviceWithDMM" ) super().__init__(pulser_device=pulser_device)
specs
property
Section titled “
specs
property
”specs: dict[str, float | None]Return the device specification constraints.
from_connection
classmethod
Section titled “
from_connection
classmethod
”from_connection( connection: RemoteConnection, name: str) -> Device (qoolqit.devices.device.Device)" href="#qoolqit.Device">DeviceReturn the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with
the connection.fetch_available_devices() method.
Parameters:
-
connection(RemoteConnection) –connection object to fetch the available devices.
-
name(str) –The name of the desired device.
Returns:
-
Device(Device) –The requested device.
Raises:
-
ValueError–If the requested device is not available through the provided connection.
Example:
from pasqal_cloud import PasqalCloudConnectionfresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL")Source code in qoolqit/devices/device.py
@classmethoddef from_connection(cls, connection: RemoteConnection, name: str) -> Device: """Return the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with the `connection.fetch_available_devices()` method.
Args: connection (RemoteConnection): connection object to fetch the available devices. name (str): The name of the desired device.
Returns: Device: The requested device.
Raises: ValueError: If the requested device is not available through the provided connection.
Example: ```python from pasqal_cloud import PasqalCloudConnection fresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL") ``` """ available_remote_devices = connection.fetch_available_devices() if name not in available_remote_devices: raise ValueError(f"Device {name} is not available through the provided connection.") pulser_device = available_remote_devices[name] return cls(pulser_device=pulser_device)info() -> NoneShow the device short description and constraints.
Source code in qoolqit/devices/device.py
def info(self) -> None: """Show the device short description and constraints.""" print(self)
reset_converter
Section titled “
reset_converter
”reset_converter() -> NoneResets the unit converter to the default one.
Source code in qoolqit/devices/device.py
def reset_converter(self) -> None: """Resets the unit converter to the default one.""" # Create a NEW converter so mutations don't persist. self._converter = self._default_converter
set_distance_unit
Section titled “
set_distance_unit
”set_distance_unit(distance: float) -> NoneChanges the unit converter according to a reference distance unit.
Source code in qoolqit/devices/device.py
def set_distance_unit(self, distance: float) -> None: """Changes the unit converter according to a reference distance unit.""" self.converter.factors = self.converter.factors_from_distance(distance)
set_energy_unit
Section titled “
set_energy_unit
”set_energy_unit(energy: float) -> NoneChanges the unit converter according to a reference energy unit.
Source code in qoolqit/devices/device.py
def set_energy_unit(self, energy: float) -> None: """Changes the unit converter according to a reference energy unit.""" self.converter.factors = self.converter.factors_from_energy(energy)
BlackmanWaveform
Section titled “
BlackmanWaveform
”BlackmanWaveform(duration: float, area: float)A Blackman window of a specified duration and area under the curve.
Implements the positive Blackman window shaped waveform blackman(t) = A(0.42 - 0.5cos(αt) + 0.08cos(2αt)) A = area/(0.42duration) α = 2π/duration
See: https://en.wikipedia.org/wiki/Window_function#:~:text=Blackman%20window (external)
Parameters:
-
duration(float) –The waveform duration.
-
area(float) –The integral of the waveform.
Example
blackman_wf = BlackmanWaveform(100.0, area=3.14)Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
__rshift__–Returns a new CompositeWaveform composed of this waveform and another.
Attributes:
-
duration(float) –Returns the duration of the waveform.
-
params(dict[str, float | ndarray]) –Dictionary of parameters used by the waveform.
Source code in qoolqit/waveforms/waveforms.py
def __init__(self, duration: float, area: float) -> None: """Initializes a new BlackmanWaveform.""" super().__init__(duration, area=float(area))
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)
__rshift__
Section titled “
__rshift__
”__rshift__(other: Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform) -> CompositeWaveform (qoolqit.waveforms.base_waveforms.CompositeWaveform)" href="../waveforms/#qoolqit.waveforms.CompositeWaveform">CompositeWaveformReturns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform: """Returns a new CompositeWaveform composed of this waveform and another.""" if isinstance(other, Waveform): if isinstance(other, CompositeWaveform): return CompositeWaveform(self, *other._waveforms) return CompositeWaveform(self, other) else: raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")
ConstantWaveform
Section titled “
ConstantWaveform
”ConstantWaveform(duration: float, value: float)A constant waveform over a given duration.
Parameters:
-
duration(float) –the total duration.
-
value(float) –the value to take during the duration.
Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
__rshift__–Returns a new CompositeWaveform composed of this waveform and another.
Attributes:
-
duration(float) –Returns the duration of the waveform.
-
params(dict[str, float | ndarray]) –Dictionary of parameters used by the waveform.
Source code in qoolqit/waveforms/waveforms.py
def __init__( self, duration: float, value: float,) -> None: super().__init__(duration, value=float(value))
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)
__rshift__
Section titled “
__rshift__
”__rshift__(other: Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform) -> CompositeWaveform (qoolqit.waveforms.base_waveforms.CompositeWaveform)" href="../waveforms/#qoolqit.waveforms.CompositeWaveform">CompositeWaveformReturns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform: """Returns a new CompositeWaveform composed of this waveform and another.""" if isinstance(other, Waveform): if isinstance(other, CompositeWaveform): return CompositeWaveform(self, *other._waveforms) return CompositeWaveform(self, other) else: raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")
DelayWaveform
Section titled “
DelayWaveform
”DelayWaveform( duration: float, *args: float, **kwargs: float | ndarray)An empty waveform.
Parameters:
-
duration(float) –the total duration of the waveform.
-
**kwargs(float | ndarray, default:{}) –optional keyword arguments for the waveform function.
Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
__rshift__–Returns a new CompositeWaveform composed of this waveform and another.
Attributes:
-
duration(float) –Returns the duration of the waveform.
-
params(dict[str, float | ndarray]) –Dictionary of parameters used by the waveform.
Source code in qoolqit/waveforms/base_waveforms.py
def __init__( self, duration: float, *args: float, **kwargs: float | np.ndarray,) -> None: """Initializes the Waveform.
Args: duration: the total duration of the waveform. **kwargs: optional keyword arguments for the waveform function. """
if duration <= 0: raise ValueError("Duration needs to be a positive non-zero value.")
if len(args) > 0: raise ValueError( f"Extra arguments in {type(self).__name__} need to be passed as keyword arguments" )
self._duration = float(duration) self._params_dict = kwargs
for key, value in kwargs.items(): setattr(self, key, value)
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)
__rshift__
Section titled “
__rshift__
”__rshift__(other: Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform) -> CompositeWaveform (qoolqit.waveforms.base_waveforms.CompositeWaveform)" href="../waveforms/#qoolqit.waveforms.CompositeWaveform">CompositeWaveformReturns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform: """Returns a new CompositeWaveform composed of this waveform and another.""" if isinstance(other, Waveform): if isinstance(other, CompositeWaveform): return CompositeWaveform(self, *other._waveforms) return CompositeWaveform(self, other) else: raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")
Device
Section titled “
Device
”Device( pulser_device: BaseDevice, default_converter: Optional[UnitConverter] = None,)QoolQit Device wrapper around a Pulser BaseDevice.
Parameters:
-
pulser_device(BaseDevice) –a
BaseDeviceto build the QoolQit device from. -
default_converter(Optional[UnitConverter], default:None) –optional unit converter to handle unit conversion.
Examples:
From Pulser device:
qoolqit_device = Device(pulser_device=pulser_device)From remote Pulser device:
from pasqal_cloud import PasqalCloudConnectionfrom qoolqit import Device
# Fetch the remote device from the connectionconnection = PasqalCloudConnection()pulser_fresnel_device = connection.fetch_available_devices()["FRESNEL"]
# Wrap a Pulser device object into a QoolQit Devicefresnel_device = Device(pulser_device=PulserFresnelDevice)From custom Pulser device:
from dataclasses import replacefrom pulser import AnalogDevicefrom qoolqit import Device
# Converting the pulser Device object in a VirtualDevice objectVirtualAnalog = AnalogDevice.to_virtual()# Replacing desired valuesModdedAnalogDevice = replace( VirtualAnalog, max_radial_distance=100, max_sequence_duration=7000 )
# Wrap a Pulser device object into a QoolQit Devicemod_analog_device = Device(pulser_device=ModdedAnalogDevice)- API reference
Methods:
-
from_connection–Return the specified device from the selected device from a connection.
-
info–Show the device short description and constraints.
-
reset_converter–Resets the unit converter to the default one.
-
set_distance_unit–Changes the unit converter according to a reference distance unit.
-
set_energy_unit–Changes the unit converter according to a reference energy unit.
Attributes:
-
specs(dict[str, float | None]) –Return the device specification constraints.
Source code in qoolqit/devices/device.py
def __init__( self, pulser_device: BaseDevice, default_converter: Optional[UnitConverter] = None,) -> None:
if not isinstance(pulser_device, BaseDevice): raise TypeError("`pulser_device` must be an instance of Pulser BaseDevice class.")
# Store it for all subsequent lookups self._pulser_device: BaseDevice = pulser_device self._name: str = self._pulser_device.name
# Physical constants / channel & limit lookups (assumes 'rydberg_global' channel) self._C6 = self._pulser_device.interaction_coeff self._clock_period = self._pulser_device.channels["rydberg_global"].clock_period # Relevant limits from the underlying device (float or None) self._max_duration = self._pulser_device.max_sequence_duration self._max_amp = self._pulser_device.channels["rydberg_global"].max_amp self._upper_amp = self._max_amp or 4 * math.pi self._max_abs_det = self._pulser_device.channels["rydberg_global"].max_abs_detuning self._min_distance = self._pulser_device.min_atom_distance self._lower_distance = self._min_distance or 5.0 self._max_radial_distance = self._pulser_device.max_radial_distance
# ratio between maximum amplitude and maximum interaction energy J_max = C6/r_min^6 self._energy_ratio: float = (self._upper_amp * self._lower_distance**6) / self._C6
# layouts self._requires_layout = self._pulser_device.requires_layout
if default_converter is not None: # Snapshot the caller-provided factors so reset() reproduces them exactly. t0, e0, d0 = default_converter.factors self._default_factory: Callable[[], UnitConverter] = lambda: UnitConverter( self._C6, t0, e0, d0 ) else: self._default_factory = lambda: UnitConverter.from_distance( self._C6, self._lower_distance )
self.reset_converter()
specs
property
Section titled “
specs
property
”specs: dict[str, float | None]Return the device specification constraints.
from_connection
classmethod
Section titled “
from_connection
classmethod
”from_connection( connection: RemoteConnection, name: str) -> Device (qoolqit.devices.device.Device)" href="#qoolqit.Device">DeviceReturn the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with
the connection.fetch_available_devices() method.
Parameters:
-
connection(RemoteConnection) –connection object to fetch the available devices.
-
name(str) –The name of the desired device.
Returns:
-
Device(Device) –The requested device.
Raises:
-
ValueError–If the requested device is not available through the provided connection.
Example:
from pasqal_cloud import PasqalCloudConnectionfresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL")Source code in qoolqit/devices/device.py
@classmethoddef from_connection(cls, connection: RemoteConnection, name: str) -> Device: """Return the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with the `connection.fetch_available_devices()` method.
Args: connection (RemoteConnection): connection object to fetch the available devices. name (str): The name of the desired device.
Returns: Device: The requested device.
Raises: ValueError: If the requested device is not available through the provided connection.
Example: ```python from pasqal_cloud import PasqalCloudConnection fresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL") ``` """ available_remote_devices = connection.fetch_available_devices() if name not in available_remote_devices: raise ValueError(f"Device {name} is not available through the provided connection.") pulser_device = available_remote_devices[name] return cls(pulser_device=pulser_device)info() -> NoneShow the device short description and constraints.
Source code in qoolqit/devices/device.py
def info(self) -> None: """Show the device short description and constraints.""" print(self)
reset_converter
Section titled “
reset_converter
”reset_converter() -> NoneResets the unit converter to the default one.
Source code in qoolqit/devices/device.py
def reset_converter(self) -> None: """Resets the unit converter to the default one.""" # Create a NEW converter so mutations don't persist. self._converter = self._default_converter
set_distance_unit
Section titled “
set_distance_unit
”set_distance_unit(distance: float) -> NoneChanges the unit converter according to a reference distance unit.
Source code in qoolqit/devices/device.py
def set_distance_unit(self, distance: float) -> None: """Changes the unit converter according to a reference distance unit.""" self.converter.factors = self.converter.factors_from_distance(distance)
set_energy_unit
Section titled “
set_energy_unit
”set_energy_unit(energy: float) -> NoneChanges the unit converter according to a reference energy unit.
Source code in qoolqit/devices/device.py
def set_energy_unit(self, energy: float) -> None: """Changes the unit converter according to a reference energy unit.""" self.converter.factors = self.converter.factors_from_energy(energy)
DigitalAnalogDevice
Section titled “
DigitalAnalogDevice
”DigitalAnalogDevice()A device with digital and analog capabilities.
Methods:
-
from_connection–Return the specified device from the selected device from a connection.
-
info–Show the device short description and constraints.
-
reset_converter–Resets the unit converter to the default one.
-
set_distance_unit–Changes the unit converter according to a reference distance unit.
-
set_energy_unit–Changes the unit converter according to a reference energy unit.
Attributes:
-
specs(dict[str, float | None]) –Return the device specification constraints.
Source code in qoolqit/devices/device.py
def __init__(self) -> None: super().__init__(pulser_device=pulser.DigitalAnalogDevice)
specs
property
Section titled “
specs
property
”specs: dict[str, float | None]Return the device specification constraints.
from_connection
classmethod
Section titled “
from_connection
classmethod
”from_connection( connection: RemoteConnection, name: str) -> Device (qoolqit.devices.device.Device)" href="#qoolqit.Device">DeviceReturn the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with
the connection.fetch_available_devices() method.
Parameters:
-
connection(RemoteConnection) –connection object to fetch the available devices.
-
name(str) –The name of the desired device.
Returns:
-
Device(Device) –The requested device.
Raises:
-
ValueError–If the requested device is not available through the provided connection.
Example:
from pasqal_cloud import PasqalCloudConnectionfresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL")Source code in qoolqit/devices/device.py
@classmethoddef from_connection(cls, connection: RemoteConnection, name: str) -> Device: """Return the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with the `connection.fetch_available_devices()` method.
Args: connection (RemoteConnection): connection object to fetch the available devices. name (str): The name of the desired device.
Returns: Device: The requested device.
Raises: ValueError: If the requested device is not available through the provided connection.
Example: ```python from pasqal_cloud import PasqalCloudConnection fresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL") ``` """ available_remote_devices = connection.fetch_available_devices() if name not in available_remote_devices: raise ValueError(f"Device {name} is not available through the provided connection.") pulser_device = available_remote_devices[name] return cls(pulser_device=pulser_device)info() -> NoneShow the device short description and constraints.
Source code in qoolqit/devices/device.py
def info(self) -> None: """Show the device short description and constraints.""" print(self)
reset_converter
Section titled “
reset_converter
”reset_converter() -> NoneResets the unit converter to the default one.
Source code in qoolqit/devices/device.py
def reset_converter(self) -> None: """Resets the unit converter to the default one.""" # Create a NEW converter so mutations don't persist. self._converter = self._default_converter
set_distance_unit
Section titled “
set_distance_unit
”set_distance_unit(distance: float) -> NoneChanges the unit converter according to a reference distance unit.
Source code in qoolqit/devices/device.py
def set_distance_unit(self, distance: float) -> None: """Changes the unit converter according to a reference distance unit.""" self.converter.factors = self.converter.factors_from_distance(distance)
set_energy_unit
Section titled “
set_energy_unit
”set_energy_unit(energy: float) -> NoneChanges the unit converter according to a reference energy unit.
Source code in qoolqit/devices/device.py
def set_energy_unit(self, energy: float) -> None: """Changes the unit converter according to a reference energy unit.""" self.converter.factors = self.converter.factors_from_energy(energy)
Drive
Section titled “
Drive
”Drive( *, amplitude: Waveform (qoolqit.waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform, detuning: Waveform (qoolqit.waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform | None = None, dmm: DetuningMapModulator
dataclass (qoolqit.drive.DetuningMapModulator)" href="../drive/#qoolqit.drive.DetuningMapModulator">DetuningMapModulator | None = None, phase: float = 0.0,)The drive Hamiltonian acting over a duration.
The Drive specifies the control parameters for the time-dependent drive Hamiltonian in the Rydberg model (see https://docs.pasqal.com/qoolqit/get_started/qoolqit_model/ (external) for details),
H_drive(t) = Σᵢ [Ω(t)/2 (cos φ(t) σˣᵢ - sin φ(t) σʸᵢ)] - Σᵢ [δ(t) + εᵢ Δ(t)] nᵢ
representing: - Amplitude Ω(t): Controls the Rabi frequency that drives qubits. - Detuning δ(t): Controls the energy offset of the Rydberg state. - dmm εᵢ, Δ(t): Detuning Map Modulator (DMM) for additional qubit-specific detunings. - Phase φ: Global phase applied to the amplitude term.
Parameters:
-
amplitude(Waveform) –Time-dependent amplitude waveform Ω(t) representing the Rabi frequency. Controls the strength of the coupling between ground and Rydberg states. Must be positive for all times.
-
detuning(Waveform | None, default:None) –Time-dependent detuning waveform δ(t) representing the energy offset of the Rydberg state relative to resonance. If None, defaults to zero detuning (Delay waveform) for the duration of the amplitude.
-
dmm(DetuningMapModulator | None, default:None) –DetuningMapModulator instance for additional negative detuning waveform Δ(t) ≤ 0 applied to individual qubits as specified by its
weightsattribute εᵢ. -
phase(float, default:0.0) –Global phase φ applied to the amplitude term in the Hamiltonian. Defaults to 0.0 (no phase).
Raises:
-
TypeError–If amplitude or detuning are not Waveform instances.
-
ValueError–If the amplitude waveform has negative values.
Note
- All arguments must be passed as keyword arguments.
- If amplitude and detuning have different durations, the shorter one is automatically extended with a Delay to match the longer duration.
- DetuningMapModulator waveform must be negative for all times (≤ 0) as it represents energy shifts below the resonance.
Example
from qoolqit import Drive from qoolqit.waveforms import ConstantWaveform, RampWaveform
Simple constant drive
Section titled “Simple constant drive”drive = Drive(amplitude=ConstantWaveform(10.0, 1.5))
Drive with time-varying amplitude and detuning
Section titled “Drive with time-varying amplitude and detuning”amp = RampWaveform(5.0, 0.0, 2.0) det = ConstantWaveform(5.0, -1.0) drive = Drive(amplitude=amp, detuning=det, phase=0.5)
- API reference
- API reference
Attributes:
-
amplitude(Waveform) –The amplitude waveform in the drive.
-
detuning(Waveform) –The detuning waveform in the drive.
-
dmm(DetuningMapModulator | None) –Detuning Map Modulator (DMM) applied to individual qubits.
-
phase(float) –The phase value in the drive.
Source code in qoolqit/drive.py
def __init__( self, *, amplitude: Waveform, detuning: Waveform | None = None, dmm: DetuningMapModulator | None = None, phase: float = 0.0,) -> None: """Initialize a Drive.
The Drive specifies the control parameters for the time-dependent drive Hamiltonian in the Rydberg model (see https://docs.pasqal.com/qoolqit/get_started/qoolqit_model/ for details),
H_drive(t) = Σᵢ [Ω(t)/2 (cos φ(t) σˣᵢ - sin φ(t) σʸᵢ)] - Σᵢ [δ(t) + εᵢ Δ(t)] nᵢ
representing: - Amplitude Ω(t): Controls the Rabi frequency that drives qubits. - Detuning δ(t): Controls the energy offset of the Rydberg state. - dmm εᵢ, Δ(t): Detuning Map Modulator (DMM) for additional qubit-specific detunings. - Phase φ: Global phase applied to the amplitude term.
Args: amplitude: Time-dependent amplitude waveform Ω(t) representing the Rabi frequency. Controls the strength of the coupling between ground and Rydberg states. Must be positive for all times. detuning: Time-dependent detuning waveform δ(t) representing the energy offset of the Rydberg state relative to resonance. If None, defaults to zero detuning (Delay waveform) for the duration of the amplitude. dmm: DetuningMapModulator instance for additional negative detuning waveform Δ(t) ≤ 0 applied to individual qubits as specified by its `weights` attribute εᵢ. phase: Global phase φ applied to the amplitude term in the Hamiltonian. Defaults to 0.0 (no phase).
Raises: TypeError: If amplitude or detuning are not Waveform instances. ValueError: If the amplitude waveform has negative values.
Note: - All arguments must be passed as keyword arguments. - If amplitude and detuning have different durations, the shorter one is automatically extended with a Delay to match the longer duration. - DetuningMapModulator waveform must be negative for all times (≤ 0) as it represents energy shifts below the resonance.
Example: >>> from qoolqit import Drive >>> from qoolqit.waveforms import ConstantWaveform, RampWaveform >>> >>> # Simple constant drive >>> drive = Drive(amplitude=ConstantWaveform(10.0, 1.5)) >>> >>> # Drive with time-varying amplitude and detuning >>> amp = RampWaveform(5.0, 0.0, 2.0) >>> det = ConstantWaveform(5.0, -1.0) >>> drive = Drive(amplitude=amp, detuning=det, phase=0.5) """
for arg in [amplitude, detuning]: if arg is not None and not isinstance(arg, Waveform): raise TypeError("'amplitude' and 'detuning' must be of type Waveform.")
if amplitude.min() < 0.0: raise ValueError("'amplitude' must be positive.")
self._amplitude = amplitude self._detuning = detuning if detuning is not None else DelayWaveform(amplitude.duration)
self._amplitude_orig = self._amplitude self._detuning_orig = self._detuning
# adjust amplitude and detuning waveforms to match the duration if self._amplitude.duration > self._detuning.duration: extra_duration = self._amplitude.duration - self._detuning.duration self._detuning = CompositeWaveform(self._detuning, DelayWaveform(extra_duration)) elif self._detuning.duration > self._amplitude.duration: extra_duration = self._detuning.duration - self._amplitude.duration self._amplitude = CompositeWaveform(self._amplitude, DelayWaveform(extra_duration))
self._duration = self._amplitude.duration if dmm is not None and not isinstance(dmm, DetuningMapModulator): raise TypeError("'dmm' must be of type DetuningMapModulator.") self._dmm = dmm self._phase = phase
amplitude
property
Section titled “
amplitude
property
”amplitude: Waveform (qoolqit.waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformThe amplitude waveform in the drive.
detuning
property
Section titled “
detuning
property
”detuning: Waveform (qoolqit.waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformThe detuning waveform in the drive.
dmm
property
Section titled “
dmm
property
”dmm: DetuningMapModulator
dataclass (qoolqit.drive.DetuningMapModulator)" href="../drive/#qoolqit.drive.DetuningMapModulator">DetuningMapModulator | NoneDetuning Map Modulator (DMM) applied to individual qubits.
phase
property
Section titled “
phase
property
”phase: floatThe phase value in the drive.
InterpolatedWaveform
Section titled “
InterpolatedWaveform
”InterpolatedWaveform( duration: float, values: ArrayLike, times: ArrayLike | None = None,)A waveform created from shape-preserving interpolation of data points.
This class creates a smooth waveform by interpolating between specified data points using PCHIP (Piecewise Cubic Hermite Interpolating Polynomial) interpolation. The interpolating curve preserves the shape of the input data: bounds (avoiding under/overshooting), monotonicity, and convexity.
Uses scipy's PchipInterpolator for the interpolation.
Attributes:
-
duration(float) –The waveform duration.
-
values(float) –Array-like sequence of waveform values at the interpolation points. Must be convertible to float. These values define the amplitude of the waveform at the corresponding time points.
-
times(float) –Optional array-like sequence of fractional times in the range [0, 1] indicating where to place each value on the time axis. Must have the same length as
values. If not provided, values are distributed evenly across the waveform duration. Default is None.
ValueError: If times contains values outside [0, 1] or if times and
values have different lengths.
Example
Create a waveform with 4 points over 100ns
Section titled “Create a waveform with 4 points over 100ns”values = [0.0, 1.0, 0.5, 0.0] wf = InterpolatedWaveform(100, values)
Create with custom timing
Section titled “Create with custom timing”times = [0.0, 0.2, 0.8, 1.0] # Non-uniform spacing wf = InterpolatedWaveform(100, values, times)
Parameters:
-
duration(float) –The total duration of the waveform. Must be positive.
-
values(ArrayLike) –Array-like sequence of waveform values at interpolation points. Can be a list, tuple, numpy array, or any sequence convertible to float.
-
times(ArrayLike | None, default:None) –Optional array-like sequence of fractional times in [0, 1]. If provided, must have the same length as
values. If None, values are evenly spaced across the duration. Default is None.
Raises:
-
ValueError–If any value in
timesis outside [0, 1], or iftimesandvalueshave different lengths.
Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
__rshift__–Returns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/waveforms.py
def __init__( self, duration: float, values: ArrayLike, times: ArrayLike | None = None,): """Initialize an Interpolated waveform.
Args: duration: The total duration of the waveform. Must be positive. values: Array-like sequence of waveform values at interpolation points. Can be a list, tuple, numpy array, or any sequence convertible to float. times: Optional array-like sequence of fractional times in [0, 1]. If provided, must have the same length as `values`. If None, values are evenly spaced across the duration. Default is None.
Raises: ValueError: If any value in `times` is outside [0, 1], or if `times` and `values` have different lengths. """ super().__init__(duration) self._values = np.array(values, dtype=float) if times is not None: self._times = np.array(times, dtype=float) if any([(ft < 0) or (ft > 1) for ft in self._times]): raise ValueError("All values in `times` must be in [0,1].") if len(self._times) != len(self._values): raise ValueError( "Arguments `values` and `times` must be arrays of the same length." ) else: self._times = np.linspace(0, 1, num=len(self._values))
self._interp_func = PchipInterpolator(duration * self._times, values)
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)
__rshift__
Section titled “
__rshift__
”__rshift__(other: Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform) -> CompositeWaveform (qoolqit.waveforms.base_waveforms.CompositeWaveform)" href="../waveforms/#qoolqit.waveforms.CompositeWaveform">CompositeWaveformReturns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform: """Returns a new CompositeWaveform composed of this waveform and another.""" if isinstance(other, Waveform): if isinstance(other, CompositeWaveform): return CompositeWaveform(self, *other._waveforms) return CompositeWaveform(self, other) else: raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")
MockDevice
Section titled “
MockDevice
”MockDevice()A virtual device for unconstrained prototyping.
Methods:
-
from_connection–Return the specified device from the selected device from a connection.
-
info–Show the device short description and constraints.
-
reset_converter–Resets the unit converter to the default one.
-
set_distance_unit–Changes the unit converter according to a reference distance unit.
-
set_energy_unit–Changes the unit converter according to a reference energy unit.
Attributes:
-
specs(dict[str, float | None]) –Return the device specification constraints.
Source code in qoolqit/devices/device.py
def __init__(self) -> None: super().__init__(pulser_device=pulser.MockDevice)
specs
property
Section titled “
specs
property
”specs: dict[str, float | None]Return the device specification constraints.
from_connection
classmethod
Section titled “
from_connection
classmethod
”from_connection( connection: RemoteConnection, name: str) -> Device (qoolqit.devices.device.Device)" href="#qoolqit.Device">DeviceReturn the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with
the connection.fetch_available_devices() method.
Parameters:
-
connection(RemoteConnection) –connection object to fetch the available devices.
-
name(str) –The name of the desired device.
Returns:
-
Device(Device) –The requested device.
Raises:
-
ValueError–If the requested device is not available through the provided connection.
Example:
from pasqal_cloud import PasqalCloudConnectionfresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL")Source code in qoolqit/devices/device.py
@classmethoddef from_connection(cls, connection: RemoteConnection, name: str) -> Device: """Return the specified device from the selected device from a connection.
Available devices through the provided connection are can be seen with the `connection.fetch_available_devices()` method.
Args: connection (RemoteConnection): connection object to fetch the available devices. name (str): The name of the desired device.
Returns: Device: The requested device.
Raises: ValueError: If the requested device is not available through the provided connection.
Example: ```python from pasqal_cloud import PasqalCloudConnection fresnel_device = Device.from_connection(connection=PasqalCloudConnection(), name="FRESNEL") ``` """ available_remote_devices = connection.fetch_available_devices() if name not in available_remote_devices: raise ValueError(f"Device {name} is not available through the provided connection.") pulser_device = available_remote_devices[name] return cls(pulser_device=pulser_device)info() -> NoneShow the device short description and constraints.
Source code in qoolqit/devices/device.py
def info(self) -> None: """Show the device short description and constraints.""" print(self)
reset_converter
Section titled “
reset_converter
”reset_converter() -> NoneResets the unit converter to the default one.
Source code in qoolqit/devices/device.py
def reset_converter(self) -> None: """Resets the unit converter to the default one.""" # Create a NEW converter so mutations don't persist. self._converter = self._default_converter
set_distance_unit
Section titled “
set_distance_unit
”set_distance_unit(distance: float) -> NoneChanges the unit converter according to a reference distance unit.
Source code in qoolqit/devices/device.py
def set_distance_unit(self, distance: float) -> None: """Changes the unit converter according to a reference distance unit.""" self.converter.factors = self.converter.factors_from_distance(distance)
set_energy_unit
Section titled “
set_energy_unit
”set_energy_unit(energy: float) -> NoneChanges the unit converter according to a reference energy unit.
Source code in qoolqit/devices/device.py
def set_energy_unit(self, energy: float) -> None: """Changes the unit converter according to a reference energy unit.""" self.converter.factors = self.converter.factors_from_energy(energy)
PiecewiseLinearWaveform
Section titled “
PiecewiseLinearWaveform
”PiecewiseLinearWaveform( durations: list[float] | tuple[float, ...] | ndarray, values: list[float] | tuple[float, ...] | ndarray,)A piecewise linear waveform.
Creates a composite waveform of N ramps that linearly interpolate through the given N+1 values.
Parameters:
-
durations(list[float] | tuple[float, ...] | ndarray) –list or tuple of N duration values.
-
values(list[float] | tuple[float, ...] | ndarray) –list or tuple of N+1 waveform values.
Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
max–Get the maximum value of the waveform.
-
min–Get the minimum value of the waveform.
Attributes:
-
duration(float) –Returns the duration of the waveform.
-
durations(list[float]) –Returns the list of durations of each individual waveform.
-
n_waveforms(int) –Returns the number of waveforms.
-
params(dict[str, float | ndarray]) –Dictionary of parameters used by the waveform.
-
times(list[float]) –Returns the list of times when each individual waveform starts.
-
waveforms(list[Waveform]) –Returns a list of the individual waveforms.
Source code in qoolqit/waveforms/waveforms.py
def __init__( self, durations: list[float] | tuple[float, ...] | np.ndarray, values: list[float] | tuple[float, ...] | np.ndarray,) -> None:
if len(durations) + 1 != len(values) or len(durations) == 1: raise ValueError( "A PiecewiseLinearWaveform requires N durations and N + 1 values, for N >= 2." )
for duration in durations: if duration == 0.0: raise ValueError("A PiecewiseLinearWaveform interval cannot have zero duration.")
# Stored as-is (not cast to float): unlike the per-segment RampWaveforms below, # this attribute can retain an int dtype if `values` is int-typed. self.values = values
wfs = [RampWaveform(dur, values[i], values[i + 1]) for i, dur in enumerate(durations)]
super().__init__(*wfs)
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
durations
property
Section titled “
durations
property
”durations: list[float]Returns the list of durations of each individual waveform.
n_waveforms
property
Section titled “
n_waveforms
property
”n_waveforms: intReturns the number of waveforms.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
times
property
Section titled “
times
property
”times: list[float]Returns the list of times when each individual waveform starts.
waveforms
property
Section titled “
waveforms
property
”waveforms: list[ Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform]Returns a list of the individual waveforms.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)max() -> floatGet the maximum value of the waveform.
Source code in qoolqit/waveforms/base_waveforms.py
def max(self) -> float: """Get the maximum value of the waveform.""" return max([wf.max() for wf in self.waveforms])min() -> floatGet the minimum value of the waveform.
Source code in qoolqit/waveforms/base_waveforms.py
def min(self) -> float: """Get the minimum value of the waveform.""" return min([wf.min() for wf in self.waveforms])
QuantumProgram
Section titled “
QuantumProgram
”QuantumProgram(register: Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">Register, drive: Drive (qoolqit.drive.Drive)" href="../drive/#qoolqit.drive.Drive">Drive)A program representing a Sequence acting on a Register of qubits.
Parameters:
-
register(Register) –the register of qubits, defining their positions.
-
drive(Drive) –the drive acting on qubits, defining amplitude, detuning and phase.
-
API reference
qoolqit.execution
execution
Methods:
-
compile_to–Compiles the quantum program for execution on a specific device.
Attributes:
-
compiled_sequence(Sequence) –The Pulser sequence compiled to a specific device.
-
drive(Drive) –The driving waveforms.
-
is_compiled(bool) –Check if the program has been compiled.
-
register(Register) –The register of qubits.
Source code in qoolqit/program.py
def __init__( self, register: Register, drive: Drive,) -> None:
if not isinstance(register, Register): raise TypeError("`register` must be of type Register.") self._register = register
if not isinstance(drive, Drive): raise TypeError("`drive` must be of type Drive.") if drive.dmm is not None: dmm_weights = drive.dmm.weights for qid in dmm_weights.keys(): if qid not in register.qubits: raise ValueError( "In this QuantumProgram, the drive's detuning modulator map (DMM) " f"and the register do not match: qubit {qid} appears in the DMM " "but is not defined in the register." )
self._drive = drive self._compiled_sequence: PulserSequence | None = None
compiled_sequence
property
Section titled “
compiled_sequence
property
”compiled_sequence: SequenceThe Pulser sequence compiled to a specific device.
drive
property
Section titled “
drive
property
”drive: Drive (qoolqit.drive.Drive)" href="../drive/#qoolqit.drive.Drive">DriveThe driving waveforms.
is_compiled
property
Section titled “
is_compiled
property
”is_compiled: boolCheck if the program has been compiled.
register
property
Section titled “
register
property
”register: Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterThe register of qubits.
compile_to
Section titled “
compile_to
”compile_to( device: Device (qoolqit.devices.Device)" href="../devices/#qoolqit.devices.Device">Device, profile: Literal["default", "max_energy"] | CompilerProfile = DEFAULT, device_max_duration_ratio: float | None = None,) -> NoneCompiles the quantum program for execution on a specific device.
The compilation process translates a program to make it runnable on a specific device:
- Dimensionalization: Rescale the drive amplitude and the register positions to physical units compatible with the device.
- Translation: Translate the program to a lower-level representation (Pulser) that can be executed on the device.
There are two compilation profiles:
- "default": Compile the program as it is. The drive and the register positions
must respect the hardware constraints of the device which can be inspected
using
device.specs(). TheCompilerProfile.WORKING_POINTis deprecated aliases for this profile. - "max_energy": Scale the program to utilize the device's maximum capabilities. The drive amplitude and the register positions are rescaled to achieve respectively the maximum amplitude and the minimum pairwise distance compatible with the input program and the device's constraints.
The following option does NOT preserve the input program, but rather adapts the program to the device's constraints. Programs compiled this way are not portable across devices.
- device_max_duration_ratio: Rescale the drive duration to a fraction of the device's maximum allowed duration. Useful in adiabatic protocols where one simply seeks to minimize the time derivative of the drive's amplitude.
Parameters:
-
device(Device) –The target device for compilation. Must be a QoolQit Device.
-
profile(Literal['default', 'max_energy'] | CompilerProfile, default:DEFAULT) –The compilation profile used to translate the program. Defaults to CompilerProfile.DEFAULT.
-
device_max_duration_ratio(float | None, default:None) –The fraction of the device's maximum allowed duration to set the program duration to, or None to leave it unset. Must be a number in the range (0, 1]. Can only be set if the device has a maximum allowed duration.
Raises:
-
TypeError–If
deviceis not a QoolQit Device. -
ValueError–If
device_max_duration_ratiois set but the device has no maximum allowed duration, or if it is not in the range (0, 1]. -
CompilationError–If the compilation fails due to device constraints.
Source code in qoolqit/program.py
def compile_to( self, device: Device, profile: Literal["default", "max_energy"] | CompilerProfile = CompilerProfile.DEFAULT, device_max_duration_ratio: float | None = None,) -> None: """Compiles the quantum program for execution on a specific device.
The compilation process translates a program to make it runnable on a specific device:
- Dimensionalization: Rescale the drive amplitude and the register positions to physical units compatible with the device. - Translation: Translate the program to a lower-level representation (Pulser) that can be executed on the device.
There are two compilation profiles:
- "default": Compile the program as it is. The drive and the register positions must respect the hardware constraints of the device which can be inspected using `device.specs()`. The `CompilerProfile.WORKING_POINT` is deprecated aliases for this profile. - "max_energy": Scale the program to utilize the device's maximum capabilities. The drive amplitude and the register positions are rescaled to achieve respectively the maximum amplitude and the minimum pairwise distance compatible with the input program and the device's constraints.
The following option does NOT preserve the input program, but rather adapts the program to the device's constraints. Programs compiled this way are not portable across devices.
- device_max_duration_ratio: Rescale the drive duration to a fraction of the device's maximum allowed duration. Useful in adiabatic protocols where one simply seeks to minimize the time derivative of the drive's amplitude.
Args: device: The target device for compilation. Must be a QoolQit Device. profile: The compilation profile used to translate the program. Defaults to CompilerProfile.DEFAULT. device_max_duration_ratio: The fraction of the device's maximum allowed duration to set the program duration to, or None to leave it unset. Must be a number in the range (0, 1]. Can only be set if the device has a maximum allowed duration.
Raises: TypeError: If `device` is not a QoolQit Device. ValueError: If `device_max_duration_ratio` is set but the device has no maximum allowed duration, or if it is not in the range (0, 1]. CompilationError: If the compilation fails due to device constraints. """ if not isinstance(device, Device): raise TypeError("`device` must be of type `qoolqit.devices.Device`.")
if device_max_duration_ratio is not None: if device._max_duration is None: raise ValueError( "Cannot set `device_max_duration_ratio` because the target device " "does not have a maximum allowed duration." ) if not (0 < device_max_duration_ratio <= 1): raise ValueError( "`device_max_duration_ratio` must be between 0 and 1, " f"got {device_max_duration_ratio} instead." )
# Check if device supports DMM and has a DMM channel if self.drive.dmm is not None: if not device._device.dmm_channels: raise CompilationError( "The device does not support DMM. Please use a device that supports DMM." )
profile = CompilerProfile(profile)
compiler = SequenceCompiler( self.register, self.drive, device, profile, device_max_duration_ratio ) self._device = device self._compiled_sequence = compiler.compile_sequence()
RampWaveform
Section titled “
RampWaveform
”RampWaveform( duration: float, initial_value: float, final_value: float,)A ramp that linearly interpolates between an initial and final value.
Parameters:
-
duration(float) –the total duration.
-
initial_value(float) –the initial value at t = 0.
-
final_value(float) –the final value at t = duration.
Methods:
-
__rmul__–Rescale this waveform by a scalar (right-hand multiplication).
-
__rshift__–Returns a new CompositeWaveform composed of this waveform and another.
Attributes:
-
duration(float) –Returns the duration of the waveform.
-
params(dict[str, float | ndarray]) –Dictionary of parameters used by the waveform.
Source code in qoolqit/waveforms/waveforms.py
def __init__( self, duration: float, initial_value: float, final_value: float,) -> None: super().__init__( duration, initial_value=float(initial_value), final_value=float(final_value) )
duration
property
Section titled “
duration
property
”duration: floatReturns the duration of the waveform.
params
property
Section titled “
params
property
”params: dict[str, float | ndarray]Dictionary of parameters used by the waveform.
__rmul__
Section titled “
__rmul__
”__rmul__(other: float) -> Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">WaveformRescale this waveform by a scalar (right-hand multiplication).
Source code in qoolqit/waveforms/base_waveforms.py
def __rmul__(self, other: float) -> Waveform: """Rescale this waveform by a scalar (right-hand multiplication).""" return self.__mul__(other)
__rshift__
Section titled “
__rshift__
”__rshift__(other: Waveform (qoolqit.waveforms.base_waveforms.Waveform)" href="../waveforms/#qoolqit.waveforms.Waveform">Waveform) -> CompositeWaveform (qoolqit.waveforms.base_waveforms.CompositeWaveform)" href="../waveforms/#qoolqit.waveforms.CompositeWaveform">CompositeWaveformReturns a new CompositeWaveform composed of this waveform and another.
Source code in qoolqit/waveforms/base_waveforms.py
def __rshift__(self, other: Waveform) -> CompositeWaveform: """Returns a new CompositeWaveform composed of this waveform and another.""" if isinstance(other, Waveform): if isinstance(other, CompositeWaveform): return CompositeWaveform(self, *other._waveforms) return CompositeWaveform(self, other) else: raise NotImplementedError(f"Composing with object of type {type(other)} not supported.")
Register
Section titled “
Register
”Register( qubits: Mapping[ str, Sequence[float] | NDArray[float64] | Tensor ] | Mapping[ int, Sequence[float] | NDArray[float64] | Tensor ],)A QoolQit register mapping qubit IDs to 2D coordinates.
Examples:
From a dictionary of qubit IDs and coordinates:
>>> reg = Register({"a": (0.0, 0.0), "b": (1.0, 0.0), "c": (0.0, 1.0)})>>> reg = Register({0: (0.0, 0.0), 1: (1.0, 0.0), 2: (0.0, 1.0)})From a list of coordinates (qubit IDs are assigned automatically as strings "0", "1", ...):
>>> reg = Register.from_coordinates([(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)])Using numpy arrays as coordinates:
>>> import numpy as np>>> reg = Register({"a": np.array([0.0, 0.0]), "b": np.array([1.0, 0.0])})Using torch tensors as coordinates:
>>> import torch>>> reg = Register({"a": torch.tensor([0.0, 0.0]), "b": torch.tensor([1.0, 0.0])})Parameters:
-
qubits(Mapping[str, Sequence[float] | NDArray[float64] | Tensor] | Mapping[int, Sequence[float] | NDArray[float64] | Tensor]) –a dictionary of qubits and respective 2D coordinates {q: (x, y), ...}. Each coordinate must be castable to a numpy or torch array of shape (2,).
Raises:
-
TypeError–If
qubitsis not a Mapping. -
ValueError–If
qubitsdictionary is empty. -
ValueError–If a qubit coordinate cannot be converted to an array of floats, or if the converted coordinate is not a point in 2D.
- API reference
- API reference
Methods:
-
circle–Initializes a Register with qubits arranged in a circle.
-
distances–Distance between each qubit pair.
-
draw–Draw the register.
-
from_coordinates–Initializes a Register from a sequence or array of coordinates.
-
from_graph–Initializes a Register from a graph that has coordinates.
-
interaction_matrix–Interaction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).
-
interactions–Interaction 1/r^6 between each qubit pair.
-
line–Initializes a Register with qubits arranged in a line.
-
max_radial_distance–Maximum radial distance between all qubits.
-
min_distance–Minimum distance between all qubit pairs.
-
radial_distances–Radial distance of each qubit from the origin.
-
rectangular–Initializes a rectangular Register of qubits.
-
square–Initializes a square Register of qubits.
-
triangular–Initializes a triangular lattice Register of qubits.
Attributes:
-
n_qubits(int) –Number of qubits in the Register.
-
qubits(dict) –Returns a dictionary of qubits and respective coordinates.
-
qubits_ids(tuple[str | int, ...]) –Returns the qubit IDs.
Source code in qoolqit/register.py
def __init__( self, qubits: ( Mapping[str, Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] | Mapping[int, Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] ),) -> None: """Default constructor for the Register.
Args: qubits: a dictionary of qubits and respective 2D coordinates {q: (x, y), ...}. Each coordinate must be castable to a numpy or torch array of shape (2,).
Raises: TypeError: If `qubits` is not a Mapping. ValueError: If `qubits` dictionary is empty. ValueError: If a qubit coordinate cannot be converted to an array of floats, or if the converted coordinate is not a point in 2D. """ if not isinstance(qubits, Mapping): raise TypeError("`qubits` must be a Mapping of qubit ids to coordinates.") if not qubits: raise ValueError("Register cannot be empty.")
self._qubits_ids: tuple[str | int, ...] = tuple(qubits.keys()) validated_coords = [self._validate_coord(k, c) for k, c in qubits.items()] self._coords = self._stack_coords(validated_coords)
n_qubits
property
Section titled “
n_qubits
property
”n_qubits: intNumber of qubits in the Register.
qubits
property
Section titled “
qubits
property
”qubits: dictReturns a dictionary of qubits and respective coordinates.
qubits_ids
property
Section titled “
qubits_ids
property
”qubits_ids: tuple[str | int, ...]Returns the qubit IDs.
circle
classmethod
Section titled “
circle
classmethod
”circle(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a Register with qubits arranged in a circle.
Parameters:
-
n(int) –number of qubits to place in the circle.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef circle(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a Register with qubits arranged in a circle.
Args: n: number of qubits to place in the circle. spacing: distance between adjacent qubits. Defaults to 1.0. """ if n < 1: raise ValueError("Number of qubits must be at least 1.") if spacing <= 0: raise ValueError("Spacing must be positive.") if n == 1: return cls.from_coordinates([(0.0, 0.0)])
step = 2.0 * math.pi / n r = spacing / (2.0 * math.sin(math.pi / n)) coords = [(math.cos(step * i) * r, math.sin(step * i) * r) for i in range(n)]
return cls.from_coordinates(coords)
distances
Section titled “
distances
”distances() -> dictDistance between each qubit pair.
Source code in qoolqit/register.py
def distances(self) -> dict: """Distance between each qubit pair.""" pairs = all_node_pairs(self.qubits_ids) return distances(self.qubits, pairs)draw( ax: Axes | None = None, marker_size: int = 100, node_color: str = "tab:green",) -> NoneDraw the register.
Parameters:
-
ax(Axes | None, default:None) –an optional matplotlib Axes instance to draw on. If None, a new Axes will be created.
-
marker_size(int, default:100) –size of the qubit markers in points squared. Defaults to 100.
-
node_color(str, default:'tab:green') –color of the qubit markers. Defaults to "tab:green".
Source code in qoolqit/register.py
def draw( self, ax: Axes | None = None, marker_size: int = 100, node_color: str = "tab:green") -> None: """Draw the register.
Args: ax: an optional matplotlib Axes instance to draw on. If None, a new Axes will be created. marker_size: size of the qubit markers in points squared. Defaults to 100. node_color: color of the qubit markers. Defaults to "tab:green". """ if ax is None: _, ax = plt.subplots()
marker_radius = marker_size**0.5 / 2 # in points annotation_offset = 1.5 * marker_radius # place label just outside the marker
coords = self._coords.detach().cpu().numpy() if _is_torch(self._coords) else self._coords for xi, yi, qid in zip(coords[:, 0], coords[:, 1], self.qubits_ids): ax.scatter(xi, yi, s=marker_size, color=node_color) ax.annotate( str(qid), xy=(xi, yi), xytext=(annotation_offset, annotation_offset), textcoords="offset points", ha="center", va="center", )
ax.grid(True, color="lightgray", linestyle="--", linewidth=0.7) ax.set_axisbelow(True) ax.set_xlabel("x") ax.set_ylabel("y") ax.margins(0.1)
from_coordinates
classmethod
Section titled “
from_coordinates
classmethod
”from_coordinates( coords: Sequence[ Sequence[float] | NDArray[float64] | Tensor ] | NDArray[float64] | Tensor,) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a Register from a sequence or array of coordinates.
Qubit IDs are assigned as integers 0,1,...,N-1, where N is the number of coordinates.
Parameters:
-
coords(Sequence[Sequence[float] | NDArray[float64] | Tensor] | NDArray[float64] | Tensor) –a sequence of 2D coordinates, i.e. [(x, y), ...]. Each coordinate must be castable to a numpy or torch array of shape (2,). If
coordsis a numpy array or a torch tensor, it must be 2D and of shape (N, 2).
Raises:
-
TypeError–If
coordsis a Mapping.
Source code in qoolqit/register.py
@classmethoddef from_coordinates( cls, coords: ( Sequence[Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] | npt.NDArray[np.float64] | torch.Tensor ),) -> Register: """Initializes a Register from a sequence or array of coordinates.
Qubit IDs are assigned as integers 0,1,...,N-1, where N is the number of coordinates.
Args: coords: a sequence of 2D coordinates, i.e. [(x, y), ...]. Each coordinate must be castable to a numpy or torch array of shape (2,). If `coords` is a numpy array or a torch tensor, it must be 2D and of shape (N, 2).
Raises: TypeError: If `coords` is a Mapping. """ if isinstance(coords, Mapping): raise TypeError( "Register.from_coordinates expects a sequence of coordinates [(x, y), ...]; " "pass an id-to-coordinate mapping to Register(...) directly." ) coords_dict = {i: pos for i, pos in enumerate(coords)} return cls(coords_dict)
from_graph
classmethod
Section titled “
from_graph
classmethod
”from_graph(graph: DataGraph (qoolqit.graphs.DataGraph)" href="../graphs/#qoolqit.graphs.DataGraph">DataGraph) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a Register from a graph that has coordinates.
Parameters:
-
graph(DataGraph) –a DataGraph instance.
Source code in qoolqit/register.py
@classmethoddef from_graph(cls, graph: DataGraph) -> Register: """Initializes a Register from a graph that has coordinates.
Args: graph: a DataGraph instance. """
if not graph.has_coords: raise ValueError("Initializing a register from a graph requires node coordinates.")
if len(graph.nodes) == 0: raise ValueError("Trying to initialize a register from an empty graph.")
return cls(graph.coords)
interaction_matrix
Section titled “
interaction_matrix
”interaction_matrix() -> NDArray[float64] | TensorInteraction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).
Source code in qoolqit/register.py
def interaction_matrix(self) -> npt.NDArray[np.float64] | torch.Tensor: """Interaction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).""" dist_matrix = _pdist(self._coords) interactions = _fill_diagonal(dist_matrix, 1.0) interactions **= -6 return _fill_diagonal(interactions, 0.0)
interactions
Section titled “
interactions
”interactions() -> dictInteraction 1/r^6 between each qubit pair.
Source code in qoolqit/register.py
def interactions(self) -> dict: """Interaction 1/r^6 between each qubit pair.""" return {p: 1.0 / (r**6) for p, r in self.distances().items()}
line
classmethod
Section titled “
line
classmethod
”line(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a Register with qubits arranged in a line.
Parameters:
-
n(int) –number of qubits to place in the line.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef line(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a Register with qubits arranged in a line.
Args: n: number of qubits to place in the line. spacing: distance between adjacent qubits. Defaults to 1.0. """ return cls.rectangular(n, 1, row_spacing=spacing)
max_radial_distance
Section titled “
max_radial_distance
”max_radial_distance() -> floatMaximum radial distance between all qubits.
Source code in qoolqit/register.py
def max_radial_distance(self) -> float: """Maximum radial distance between all qubits.""" max_radial_distance: float = max(self.radial_distances().values()) return max_radial_distance
min_distance
Section titled “
min_distance
”min_distance() -> floatMinimum distance between all qubit pairs.
Source code in qoolqit/register.py
def min_distance(self) -> float: """Minimum distance between all qubit pairs.""" distance: float = min(self.distances().values()) return distance
radial_distances
Section titled “
radial_distances
”radial_distances() -> dictRadial distance of each qubit from the origin.
Source code in qoolqit/register.py
def radial_distances(self) -> dict: """Radial distance of each qubit from the origin.""" return {qid: _norm(coord) for qid, coord in zip(self.qubits_ids, self._coords)}
rectangular
classmethod
Section titled “
rectangular
classmethod
”rectangular( rows: int, cols: int, row_spacing: float = 1.0, col_spacing: float = 1.0,) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a rectangular Register of qubits.
Parameters:
-
rows(int) –number of rows in the rectangle.
-
cols(int) –number of columns in the rectangle.
-
row_spacing(float, default:1.0) –distance between adjacent qubits in the row direction. Defaults to 1.0.
-
col_spacing(float, default:1.0) –distance between adjacent qubits in the column direction. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef rectangular( cls, rows: int, cols: int, row_spacing: float = 1.0, col_spacing: float = 1.0) -> Register: """Initializes a rectangular Register of qubits.
Args: rows: number of rows in the rectangle. cols: number of columns in the rectangle. row_spacing: distance between adjacent qubits in the row direction. Defaults to 1.0. col_spacing: distance between adjacent qubits in the column direction. Defaults to 1.0. """ if rows < 1 or cols < 1: raise ValueError("Number of rows and columns must be at least 1.") if row_spacing <= 0 or col_spacing <= 0: raise ValueError("Spacing must be positive.")
x_offset = (rows - 1) * row_spacing / 2.0 y_offset = (cols - 1) * col_spacing / 2.0 coords = [ (i * row_spacing - x_offset, j * col_spacing - y_offset) for i in range(rows) for j in range(cols) ]
return cls.from_coordinates(coords)
square
classmethod
Section titled “
square
classmethod
”square(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a square Register of qubits.
Parameters:
-
n(int) –number of qubits along each side of the square.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef square(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a square Register of qubits.
Args: n: number of qubits along each side of the square. spacing: distance between adjacent qubits. Defaults to 1.0. """ return cls.rectangular(n, n, row_spacing=spacing, col_spacing=spacing)
triangular
classmethod
Section titled “
triangular
classmethod
”triangular( rows: int, atoms_per_row: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">RegisterInitializes a triangular lattice Register of qubits.
Parameters:
-
rows(int) –number of rows in the lattice.
-
atoms_per_row(int) –number of qubits per row.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef triangular(cls, rows: int, atoms_per_row: int, spacing: float = 1.0) -> Register: """Initializes a triangular lattice Register of qubits.
Args: rows: number of rows in the lattice. atoms_per_row: number of qubits per row. spacing: distance between adjacent qubits. Defaults to 1.0. """ if rows < 1 or atoms_per_row < 1: raise ValueError("Number of rows and atoms per row must be at least 1.") if spacing <= 0: raise ValueError("Spacing must be positive.")
height = math.sqrt(3.0) / 2.0 x_offset = ((atoms_per_row - 1) / 2.0 + 0.5 * (rows // 2) / rows) * spacing y_offset = (rows - 1) * height * spacing / 2.0 coords = [ ((i + 0.5 * (j % 2)) * spacing - x_offset, j * height * spacing - y_offset) for j in range(rows) for i in range(atoms_per_row) ] return cls.from_coordinates(coords)
SequenceCompiler
Section titled “
SequenceCompiler
”SequenceCompiler( register: Register (qoolqit.register.Register)" href="../register/#qoolqit.register.Register">Register, drive: Drive (qoolqit.drive.Drive)" href="../drive/#qoolqit.drive.Drive">Drive, device: Device (qoolqit.devices.Device)" href="../devices/#qoolqit.devices.Device">Device, profile: CompilerProfile, device_max_duration_ratio: float | None = None,)Compiles a QoolQit Register and Drive to a Device.
Parameters:
-
register(Register) –the QoolQit Register.
-
drive(Drive) –the QoolQit Drive.
-
device(Device) –the QoolQit Device.
-
profile(CompilerProfile) –the CompilerProfile to use.
-
device_max_duration_ratio(float | None, default:None) –optionally set the program duration to a fraction of the device's maximum allowed duration.
Source code in qoolqit/execution/sequence_compiler.py
def __init__( self, register: Register, drive: Drive, device: Device, profile: CompilerProfile, device_max_duration_ratio: float | None = None,) -> None: """Initializes the compiler.
Args: register: the QoolQit Register. drive: the QoolQit Drive. device: the QoolQit Device. profile: the CompilerProfile to use. device_max_duration_ratio: optionally set the program duration to a fraction of the device's maximum allowed duration. """
self._register = register self._drive = drive self._device = device self._target_device = device._device self._profile = profile self._device_max_duration_ratio = device_max_duration_ratio self._compilation_function: Callable = basic_compilation
available_default_devices
Section titled “
available_default_devices
”available_default_devices() -> NoneShow the default available devices in QooQit.
Source code in qoolqit/devices/device.py
def available_default_devices() -> None: """Show the default available devices in QooQit.""" for dev in (AnalogDevice(), AnalogDeviceWithDMM(), MockDevice()): dev.info()