Core Features

Sequence

The Sequence class, where a pulse sequence is defined.

class pulser.sequence.sequence.Sequence(register, device)

A sequence of operations on a device.

A sequence is composed by

  • The device in which we want to implement it

  • The register of qubits on which to act

  • The device’s channels that are used

  • The schedule of operations on each channel

A Sequence also supports variable parameters, which have to be obtained through Sequence.declare_variable(). From the moment a variable is declared, a Sequence becomes parametrized and stops being built on the fly, instead storing the sequence building calls for later execution. This forgoes some specific functionalities of a “regular” Sequence, like the ability to validate a Pulse or to draw the sequence as it is being built. Instead, all validation happens upon building (through Sequence.build()), where values for all declared variables have to be specified and a “regular” Sequence is created and returned. By changing the values given to the variables, multiple sequences can be generated from a single “parametrized” Sequence.

Parameters:
  • register (Union[BaseRegister, MappableRegister]) – The atom register on which to apply the pulses. If given as a MappableRegister instance, the traps corrresponding to each qubit ID must be given when building the sequence.

  • device (TypeVar(DeviceType, bound= BaseDevice)) – A valid device in which to execute the Sequence (import it from pulser.devices).

Note

The register and device do not support variable parameters. As such, they are the same for all Sequences built from a parametrized Sequence.

property qubit_info

Dictionary with the qubit’s IDs and positions.

property device

Device that the sequence is using.

property register

Register with the qubit’s IDs and positions.

get_register(include_mappable=True)

The atom register on which to apply the pulses.

Return type:

BaseRegister | MappableRegister

property declared_channels

Channels declared in this Sequence.

property declared_variables

Variables declared in this Sequence.

property available_channels

Channels still available for declaration.

property magnetic_field

The magnetic field acting on the array of atoms.

The magnetic field vector is defined on the reference frame of the atoms in the Register (with the z-axis coming outside of the plane).

Note

Only defined in “XY Mode”, the default value being (0, 0, 30) G.

is_parametrized()

States whether the sequence is parametrized.

A parametrized sequence is one that depends on the values assigned to variables declared within it. Sequence-building calls are not executed right away, but rather stored for deferred execution when all variables are given a value (when Sequence.build() is called).

Return type:

bool

Returns:

Whether the sequence is parametrized.

is_in_eom_mode(channel)

States whether a channel is currently in EOM mode.

Parameters:

channel (str) – The name of the declared channel to inspect.

Return type:

bool

Returns:

Whether the channel is in EOM mode.

is_register_mappable()

States whether the sequence’s register is mappable.

A sequence with a mappable register will require its qubit Id’s to be mapped to trap Ids of its associated RegisterLayout through the Sequence.build() call.

Return type:

bool

Returns:

Whether the register is a MappableRegister.

is_measured()

States whether the sequence has been measured.

Return type:

bool

get_measurement_basis()

Gets the sequence’s measurement basis.

Raises:

RuntimeError – When the sequence has not been measured.

Return type:

str

get_duration(channel=None, include_fall_time=False)

Returns the current duration of a channel or the whole sequence.

Parameters:
  • channel (Optional[str], default: None) – A specific channel to return the duration of. If left as None, it will return the duration of the whole sequence.

  • include_fall_time (bool, default: False) – Whether to include in the duration the extra time needed by the last pulse to finish, if there is modulation.

Return type:

int

Returns:

The duration of the channel or sequence, in ns.

get_addressed_bases()

Returns the bases addressed by the declared channels.

Return type:

tuple[str, ...]

current_phase_ref(qubit, basis='digital')

Current phase reference of a specific qubit for a given basis.

Parameters:
  • qubit (Union[int, str]) – The id of the qubit whose phase shift is desired.

  • basis (str, default: 'digital') – The basis (i.e. electronic transition) the phase reference is associated with. Must correspond to the basis of a declared channel.

Return type:

float

Returns:

Current phase reference of ‘qubit’ in ‘basis’.

set_magnetic_field(bx=0.0, by=0.0, bz=30.0)

Sets the magnetic field acting on the entire array.

The magnetic field vector is defined on the reference frame of the atoms in the Register (with the z-axis coming outside of the plane). Can only be defined before there are pulses added to the sequence.

Return type:

None

Note

The magnetic field only work in the “XY Mode”. If not already defined through the declaration of a Microwave channel, calling this function will enable the “XY Mode”.

Parameters:
  • bx (float, default: 0.0) – The magnetic field in the x direction (in Gauss).

  • by (float, default: 0.0) – The magnetic field in the y direction (in Gauss).

  • bz (float, default: 30.0) – The magnetic field in the z direction (in Gauss).

config_slm_mask(qubits, dmm_id='dmm_0')

Setup an SLM mask by specifying the qubits it targets.

If the sequence is in XY mode, masked qubits don’t interact with the incoming pulses until the end of the first pulse of the global channel starting the earliest in the schedule.

If the sequence is in Ising, the SLM Mask is a DetuningMap where the detuning of each masked qubit is 1.0. DMM “dmm_id” is configured using this Detuning Map, and modulated by a pulse having a large negative detuning and either a duration defined from pulses already present in the sequence (same as in XY mode) or by the first pulse added after this operation.

Parameters:
  • qubits (Collection[Union[int, str]]) – Collection of qubit ID’s to mask during the first global pulse of the sequence.

  • dmm_id (str, default: 'dmm_0') – Id of the DMM channel to use in the device.

Return type:

None

config_detuning_map(detuning_map, dmm_id)

Declares a new DMM channel to the Sequence.

Associates a DetuningMap to a DMM channel of the Device.

Return type:

None

Note

Regular devices only allow a DMM to be declared once, but MockDevice DMM can be repeatedly declared if needed.

Parameters:
  • detuning_map (DetuningMap) – A DetuningMap defining the amount of detuning each atom receives.

  • dmm_id (str) – How the channel is identified in the device. See in Sequence.available_channels which DMM IDs are still available (start by “dmm” ) and the associated description.

switch_device(new_device, strict=False)

Replicate the sequence with a different device.

This method is designed to replicate the sequence with as few changes to the original contents as possible. If the strict option is chosen, the device switch will fail whenever it cannot guarantee that the new sequence’s contents will not be modified in the process.

Parameters:
  • new_device (TypeVar(DeviceType, bound= BaseDevice)) – The target device instance.

  • strict (bool, default: False) – Enforce a strict match between devices and channels to guarantee the pulse sequence is left unchanged.

Return type:

Sequence

Returns:

The sequence on the new device, using the match channels of the former device declared in the sequence.

declare_channel(name, channel_id, initial_target=None)

Declares a new channel to the Sequence.

The first declared channel implicitly defines the sequence’s mode of operation (i.e. the underlying Hamiltonian). In particular, if the first declared channel is of type Microwave, the sequence will work in “XY Mode” and will not allow declaration of channels that do not address the ‘XY’ basis. Inversely, declaration of a channel of another type will block the declaration of Microwave channels.

Return type:

None

Note

Regular devices only allow a channel to be declared once, but MockDevice channels can be repeatedly declared if needed.

Parameters:
  • name (str) – Unique name for the channel in the sequence.

  • channel_id (str) – How the channel is identified in the device. Consult Sequence.available_channels to see which channel ID’s are still available and the associated channel’s description.

  • initial_target (Union[int, str, Collection[Union[int, str]], None], default: None) – For ‘Local’ addressing channels only. Declares the initial target of the channel. If left as None, the initial target will have to be set manually as the first addition to this channel.

declare_variable(name, size=None, dtype=<class 'float'>)

Declare a new variable within this Sequence.

The declared variables can be used to create parametrized versions of Waveform and Pulse objects, which in turn can be added to the Sequence. Additionally, simple arithmetic operations involving variables are also supported and will return parametrized objects that are dependent on the involved variables.

Parameters:
  • name (str) – The name for the variable. Must be unique within a Sequence.

  • size (Optional[int], default: None) – The number of entries stored in the variable. If defined, returns an array of variables with the given size. If left as None, returns a single variable.

  • dtype (Union[type[int], type[float]], default: <class 'float'>) – The type of the data that will be assigned to the variable. Must be float or int.

Returns:

The declared Variable instance.

Return type:

Union[Variable, VariableItem]

Note

To avoid confusion, it is recommended to store the returned Variable instance in a Python variable with the same name.

enable_eom_mode(channel, amp_on, detuning_on, optimal_detuning_off=0.0, correct_phase_drift=False)

Puts a channel in EOM mode operation.

For channels with a finite modulation bandwidth and an EOM, operation in EOM mode allows for the execution of square pulses with a higher bandwidth than that which is tipically available. It can be turned on and off through the Sequence.enable_eom_mode() and Sequence.disable_eom_mode() methods. A channel in EOM mode can only execute square pulses with a given amplitude (amp_on) and detuning (detuning_on), which are chosen at the moment the EOM mode is enabled. Furthermore, the detuning when there is no pulse being played (detuning_off) is restricted to a set of values that depends on amp_on and detuning_on. While in EOM mode, one can only add pulses of variable duration (through Sequence.add_eom_pulse()) or delays.

Return type:

None

Note

Enabling the EOM mode will automatically enforce a buffer unless the channel is empty. The detuning will go to the detuning_off value during this buffer. This buffer will not wait for pulses on other channels to finish, so calling Sequence.align() or Sequence.delay() before enabling the EOM mode is necessary to avoid eventual conflicts.

Parameters:
  • channel (str) – The name of the channel to put in EOM mode.

  • amp_on (Union[float, Parametrized]) – The amplitude of the EOM pulses (in rad/µs).

  • detuning_on (Union[float, Parametrized]) – The detuning of the EOM pulses (in rad/µs).

  • optimal_detuning_off (Union[float, Parametrized], default: 0.0) – The optimal value of detuning (in rad/µs) when there is no pulse being played. It will choose the closest value among the existing options.

  • correct_phase_drift (bool, default: False) – Performs a phase shift to correct for the phase drift incurred while turning on the EOM mode.

disable_eom_mode(channel, correct_phase_drift=False)

Takes a channel out of EOM mode operation.

For channels with a finite modulation bandwidth and an EOM, operation in EOM mode allows for the execution of square pulses with a higher bandwidth than that which is tipically available. It can be turned on and off through the Sequence.enable_eom_mode() and Sequence.disable_eom_mode() methods. A channel in EOM mode can only execute square pulses with a given amplitude (amp_on) and detuning (detuning_on), which are chosen at the moment the EOM mode is enabled. Furthermore, the detuning when there is no pulse being played (detuning_off) is restricted to a set of values that depends on amp_on and detuning_on. While in EOM mode, one can only add pulses of variable duration (through Sequence.add_eom_pulse()) or delays.

Return type:

None

Note

Disabling the EOM mode will automatically enforce a buffer time from the moment it is turned off.

Parameters:
  • channel (str) – The name of the channel to take out of EOM mode.

  • correct_phase_drift (bool, default: False) – Performs a phase shift to correct for the phase drift that occured since the last pulse (or the start of the EOM mode, if no pulse was added).

add_eom_pulse(channel, duration, phase, post_phase_shift=0.0, protocol='min-delay', correct_phase_drift=False)

Adds a square pulse to a channel in EOM mode.

For channels with a finite modulation bandwidth and an EOM, operation in EOM mode allows for the execution of square pulses with a higher bandwidth than that which is tipically available. It can be turned on and off through the Sequence.enable_eom_mode() and Sequence.disable_eom_mode() methods. A channel in EOM mode can only execute square pulses with a given amplitude (amp_on) and detuning (detuning_on), which are chosen at the moment the EOM mode is enabled. Furthermore, the detuning when there is no pulse being played (detuning_off) is restricted to a set of values that depends on amp_on and detuning_on. While in EOM mode, one can only add pulses of variable duration (through Sequence.add_eom_pulse()) or delays.

Return type:

None

Note

When the phase between pulses is changed, the necessary buffer time for a phase jump will still be enforced (unless protocol='no-delay').

Parameters:
  • channel (str) – The name of the channel to add the pulse to.

  • duration (Union[int, Parametrized]) – The duration of the pulse (in ns).

  • phase (Union[float, Parametrized]) – The pulse phase (in radians).

  • post_phase_shift (Union[float, Parametrized], default: 0.0) – Optionally lets you add a phase shift (in rads) immediately after the end of the pulse.

  • protocol (Literal['min-delay', 'no-delay', 'wait-for-all'], default: 'min-delay') – Stipulates how to deal with eventual conflicts with other channels (see Sequence.add() for more details).

  • correct_phase_drift (bool, default: False) – Adjusts the phase to correct for the phase drift that occured since the last pulse (or the start of the EOM mode, if adding the first pulse). This effectively changes the phase of the EOM pulse, so an extra delay might be added to enforce the phase jump time.

add(pulse, channel, protocol='min-delay')

Adds a pulse to a channel.

Parameters:
  • pulse (Union[Pulse, Parametrized]) – The pulse object to add to the channel.

  • channel (str) – The channel’s name provided when declared.

  • protocol (Literal['min-delay', 'no-delay', 'wait-for-all'], default: 'min-delay') –

    Stipulates how to deal with eventual conflicts with other channels, specifically in terms of having multiple channels act on the same target simultaneously.

    • 'min-delay': Before adding the pulse, introduces the smallest possible delay that avoids all exisiting conflicts.

    • 'no-delay': Adds the pulse to the channel, regardless of existing conflicts.

    • 'wait-for-all': Before adding the pulse, adds a delay that idles the channel until the end of the other channels’ latest pulse.

Return type:

None

Note

When the phase of the pulse to add is different than the phase of the previous pulse on the channel, a delay between the two pulses might be automatically added to ensure the channel’s phase_jump_time is respected. To override this behaviour, use the 'no-delay' protocol.

add_dmm_detuning(waveform, dmm_name, protocol='no-delay')

Add a waveform to the detuning of a dmm.

Parameters:
  • waveform (Union[Waveform, Parametrized]) – The waveform to add to the detuning of the dmm.

  • dmm_name (str) – The id of the dmm to modulate.

  • protocol (Literal['min-delay', 'no-delay', 'wait-for-all'], default: 'no-delay') –

    Stipulates how to deal with eventual conflicts with other channels, specifically in terms of having multiple channels act on the same target simultaneously (defaults to “no-delay”).

    • 'min-delay': Before adding the pulse, introduces the smallest possible delay that avoids all exisiting conflicts.

    • 'no-delay': Adds the pulse to the channel, regardless of existing conflicts.

    • 'wait-for-all': Before adding the pulse, adds a delay that idles the channel until the end of the other channels’ latest pulse.

Return type:

None

target(qubits, channel)

Changes the target qubit of a ‘Local’ channel.

Parameters:
  • qubits (Union[int, str, Collection[Union[int, str]]]) – The new target for this channel. Must correspond to a qubit ID in device or a collection of qubit IDs, when multi-qubit addressing is possible.

  • channel (str) – The channel’s name provided when declared. Must be a channel with ‘Local’ addressing.

Return type:

None

target_index(qubits, channel)

Changes the target qubit of a ‘Local’ channel.

Parameters:
  • qubits (Union[int, Collection[int], Parametrized]) – The new target for this channel. Must correspond to a qubit index or an collection of qubit indices, when multi-qubit addressing is possible. A qubit index is a number between 0 and the number of qubits. It is then converted to a Qubit ID using the order in which they were declared when instantiating the Register or MappableRegister.

  • channel (str) – The channel’s name provided when declared. Must be a channel with ‘Local’ addressing.

Return type:

None

Note

Cannot be used on non-parametrized sequences using a mappable register.

delay(duration, channel, at_rest=False)

Idles a given channel for a specific duration.

Parameters:
  • duration (Union[int, Parametrized]) – Time to delay (in ns).

  • channel (str) – The channel’s name provided when declared.

  • at_rest (bool, default: False) – Whether to wait until the previous pulse on the channel has finished (including output modulation) before starting the delay.

Return type:

None

Note

Delays added automatically by other instructions will generally take into account the output modulation.

measure(basis='ground-rydberg')

Measures in a valid basis.

Return type:

None

Note

In addition to the supported bases of the selected device, allowed measurement bases will depend on the mode of operation. In particular, if using Microwave channels (XY mode), only measuring in the ‘XY’ basis is allowed. Inversely, it is not possible to measure in the ‘XY’ basis outside of XY mode.

Parameters:

basis (str, default: 'ground-rydberg') – Valid basis for measurement (consult the supported_bases attribute of the selected device for the available options).

phase_shift(phi, *targets, basis='digital')

Shifts the phase of a qubit’s reference by ‘phi’, on a given basis.

This is equivalent to an \(R_z(\phi)\) gate (i.e. a rotation of the target qubit’s state by an angle \(\phi\) around the z-axis of the Bloch sphere).

Parameters:
  • phi (Union[float, Parametrized]) – The intended phase shift (in rads).

  • targets (Union[int, str]) – The ids of the qubits to apply the phase shift to.

  • basis (str, default: 'digital') – The basis (i.e. electronic transition) to associate the phase shift to. Must correspond to the basis of a declared channel.

Return type:

None

phase_shift_index(phi, *targets, basis='digital')

Shifts the phase of a qubit’s reference by ‘phi’, on a given basis.

This is equivalent to an \(R_z(\phi)\) gate (i.e. a rotation of the target qubit’s state by an angle \(\phi\) around the z-axis of the Bloch sphere).

Parameters:
  • phi (Union[float, Parametrized]) – The intended phase shift (in rads).

  • targets (Union[int, Parametrized]) – The indices of the qubits to apply the phase shift to. A qubit index is a number between 0 and the number of qubits. It is then converted to a Qubit ID using the order in which they were declared when instantiating the Register or MappableRegister.

  • basis (str, default: 'digital') – The basis (i.e. electronic transition) to associate the phase shift to. Must correspond to the basis of a declared channel.

Return type:

None

Note

Cannot be used on non-parametrized sequences using a mappable register.

align(*channels, at_rest=True)

Aligns multiple channels in time.

Introduces delays that align the provided channels with the one that finished the latest, such that the next action added to any of them will start right after the latest channel has finished.

Parameters:
  • channels (str) – The names of the channels to align, as given upon declaration.

  • at_rest (bool, default: True) – Whether to consider the output modulation of a channel’s contents when determining that it has finished.

Return type:

None

build(*, qubits=None, **vars)

Builds a sequence from the programmed instructions.

Parameters:
  • qubits (Optional[Mapping[Union[int, str], int]], default: None) – A mapping between qubit IDs and trap IDs used to define the register. Must only be provided when the sequence is initialized with a MappableRegister.

  • vars (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The values for all the variables declared in this Sequence instance, indexed by the name given upon declaration. Check Sequence.declared_variables to see all the variables.

Returns:

The Sequence built with the given variable values.

Return type:

Sequence

Example

# Check which variables are declared
>>> print(seq.declared_variables)
{'x': Variable(name='x', dtype=<class 'float'>, size=1),
 'y': Variable(name='y', dtype=<class 'int'>, size=3)}
# Build a sequence with specific values for both variables
>>> seq1 = seq.build(x=0.5, y=[1, 2, 3])
serialize(**kwargs)

Serializes the Sequence into a JSON formatted string.

Parameters:

kwargs (Any) – Valid keyword-arguments for json.dumps(), except for cls.

Returns:

The sequence encoded in a JSON formatted string.

Return type:

str

Warning

This method has been deprecated and is scheduled for removal in Pulser v1.0.0. For sequence serialization and deserialization, use Sequence.to_abstract_repr() and Sequence.from_abstract_repr() instead.

See also

json.dumps: Built-in function for serialization to a JSON formatted string.

to_abstract_repr(seq_name='pulser-exported', json_dumps_options={}, **defaults)

Serializes the Sequence into an abstract JSON object.

Keyword Arguments:
  • seq_name (str) – A name for the sequence. If not defined, defaults to “pulser-exported”.

  • json_dumps_options – A mapping between optional parameters of json.dumps() (as string) and their value (parameter cannot be “cls”).

  • defaults – The default values for all the variables declared in this Sequence instance, indexed by the name given upon declaration. Check Sequence.declared_variables to see all the variables. When using a MappableRegister, the Qubit IDs to trap IDs mapping must also be provided under the qubits keyword.

Return type:

str

Note

Providing the defaults is optional but, when done, it is mandatory to give default values for all the expected parameters.

Returns:

The sequence encoded as an abstract JSON object.

Return type:

str

static deserialize(obj, **kwargs)

Deserializes a JSON formatted string.

Parameters:
  • obj (str) – The JSON formatted string to deserialize, coming from the serialization of a Sequence through Sequence.serialize().

  • kwargs (Any) – Valid keyword-arguments for json.loads(), except for cls and object_hook.

Returns:

The deserialized Sequence object.

Return type:

Sequence

Warning

This method has been deprecated and is scheduled for removal in Pulser v1.0.0. For sequence serialization and deserialization, use Sequence.to_abstract_repr() and Sequence.from_abstract_repr() instead.

See also

json.loads: Built-in function for deserialization from a JSON formatted string.

static from_abstract_repr(obj_str)

Deserialize a sequence from an abstract JSON object.

Parameters:

obj_str (str) – the JSON string representing the sequence encoded in the abstract JSON format.

Returns:

The Pulser sequence.

Return type:

Sequence

draw(mode='input+output', draw_phase_area=False, draw_interp_pts=True, draw_phase_shifts=False, draw_register=False, draw_phase_curve=False, draw_detuning_maps=False, draw_qubit_amp=False, draw_qubit_det=False, fig_name=None, kwargs_savefig={}, show=True)

Draws the sequence in its current state.

Parameters:
  • mode (str, default: 'input+output') – The curves to draw. ‘input’ draws only the programmed curves, ‘output’ the excepted curves after modulation. ‘input+output’ will draw both curves except for channels without a defined modulation bandwidth, in which case only the input is drawn.

  • draw_phase_area (bool, default: False) – Whether phase and area values need to be shown as text on the plot, defaults to False. Doesn’t work in ‘output’ mode. If draw_phase_curve=True, phase values are ommited.

  • draw_interp_pts (bool, default: True) – When the sequence has pulses with waveforms of type InterpolatedWaveform, draws the points of interpolation on top of the respective input waveforms (defaults to True). Doesn’t work in ‘output’ mode.

  • draw_phase_shifts (bool, default: False) – Whether phase shift and reference information should be added to the plot, defaults to False.

  • draw_register (bool, default: False) – Whether to draw the register before the pulse sequence, with a visual indication (square halo) around the qubits masked by the SLM, defaults to False. Can’t be set to True if the sequence is defined with a mappable register.

  • draw_phase_curve (bool, default: False) – Draws the changes in phase in its own curve (ignored if the phase doesn’t change throughout the channel).

  • draw_detuning_maps (bool, default: False) – Whether to draw the detuning maps applied on the qubits of the register of the sequence. Shown before the pulse sequence, defaults to False.

  • draw_qubit_amp (bool, default: False) – Draws the amplitude seen by the qubits locally after the drawing of the sequence.

  • draw_qubit_det (bool, default: False) – Draws the detuning seen by the qubits locally after the drawing of the sequence.

  • fig_name (str | None, default: None) – The name on which to save the figures. Figures are saved if fig_name is not None. If draw_register, draw_qubit_amp and draw_qubit_det are False, only the pulses are saved, with no suffix. If one of them is True, the pulses will be saved with a suffix _pulses. If draw_register is True, the register is saved in another figure, with a suffix _register in the file name. If draw_qubit_amp or draw_qubit_det is True, the evolution of the quantities along time for group of qubits is saved in another figure with the prefix ‘_per_qubit’, and the group of qubits having same evolution of quantities along time are saved in a figure with suffix ‘_per_qubit_legend’.

  • kwargs_savefig (dict, default: {}) – Keywords arguments for matplotlib.pyplot.savefig. Not applicable if fig_name is None.

  • show (bool, default: True) – Whether or not to call plt.show() before returning. When combining this plot with other ones in a single figure, one may need to set this flag to False.

Return type:

None

See also

Simulation.draw(): Draws the provided sequence and the one used by the solver.

Register

Register classes

The register classes allow for the creation of arbitrary registers.

class pulser.register.base_register.BaseRegister(qubits, **kwargs)

The abstract class for a register.

property qubits

Dictionary of the qubit names and their position coordinates.

property qubit_ids

The qubit IDs of this register.

property layout

The layout used to define the register.

find_indices(id_list)

Computes indices of qubits.

This can especially be useful when building a Pulser Sequence with a parameter denoting qubits.

Return type:

list[int]

Example

Let reg be a register with qubit Ids “a”, “b” and “c”:

>>> reg.find_indices(["a", "b", "c", "a"])

It returns [0, 1, 2, 0], following the qubit order of the register.

Then, it is possible to use these indices when building a sequence, typically by assigning them to an array of variables that can be provided as an argument to target_index and phase_shift_index.

Parameters:

id_list (Sequence[Union[int, str]]) – IDs of the qubits to find.

Returns:

Indices of the qubits to denote, only valid for the given mapping.

classmethod from_coordinates(coords, center=True, prefix=None, labels=None, **kwargs)

Creates the register from an array of coordinates.

Parameters:
  • coords (ndarray) – The coordinates of each qubit to include in the register.

  • center (bool, default: True) – Whether or not to center the entire array around the origin.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

  • labels (Optional[Sequence[Union[int, str]]], default: None) – The list of qubit ids. If defined, each qubit id will be set to the corresponding value.

Return type:

TypeVar(T, bound= BaseRegister)

Returns:

A register with qubits placed on the given coordinates.

define_detuning_map(detuning_weights, slug=None)

Defines a DetuningMap for some qubits of the register.

Parameters:
  • detuning_weights (Mapping[QubitId, float]) – A mapping between the IDs of the targeted qubits and detuning weights (between 0 and 1).

  • slug (str | None, default: None) – An optional identifier for the detuning map.

Return type:

DetuningMap

Returns:

A DetuningMap associating detuning weights to the trap coordinates

of the targeted qubits.

coords_hex_hash()

Returns the idempotent hash of the coordinates.

Returns:

An hexstring encoding the hash.

Return type:

str

Note

This hash will be returned as an hexstring without the ‘0x’ prefix (unlike what is returned by ‘hex()’).

class pulser.register.register.Register(qubits, **kwargs)

Bases: BaseRegister, RegDrawer

A 2D quantum register containing a set of qubits.

Parameters:

qubits (Mapping[Any, Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]]) – Dictionary with the qubit names as keys and their position coordinates (in μm) as values (e.g. {‘q0’:(2, -1, 0), ‘q1’:(-5, 10, 0), …}).

classmethod square(side, spacing=4.0, prefix=None)

Initializes the register with the qubits in a square array.

Parameters:
  • side (int) – Side of the square in number of qubits.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

A register with qubits placed in a square array.

classmethod rectangle(rows, columns, spacing=4.0, prefix=None)

Initializes the register with the qubits in a rectangular array.

Parameters:
  • rows (int) – Number of rows.

  • columns (int) – Number of columns.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …)

Return type:

Register

Returns:

A register with qubits placed in a rectangular array.

classmethod triangular_lattice(rows, atoms_per_row, spacing=4.0, prefix=None)

Initializes the register with the qubits in a triangular lattice.

Initializes the qubits in a triangular lattice pattern, more specifically a triangular lattice with horizontal rows, meaning the triangles are pointing up and down.

Parameters:
  • rows (int) – Number of rows.

  • atoms_per_row (int) – Number of atoms per row.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

A register with qubits placed in a triangular lattice.

classmethod hexagon(layers, spacing=4.0, prefix=None)

Initializes the register with the qubits in a hexagonal layout.

Parameters:
  • layers (int) – Number of layers around a central atom.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

A register with qubits placed in a hexagonal layout.

classmethod max_connectivity(n_qubits, device, spacing=None, prefix=None)

Initializes the register with maximum connectivity for a device.

In order to maximize connectivity, the basic pattern is the triangle. Atoms are first arranged as layers of hexagons around a central atom. Extra atoms are placed in such a manner that C3 and C6 rotational symmetries are enforced as often as possible.

Parameters:
  • n_qubits (int) – Number of qubits.

  • device (pulser.devices._device_datacls.BaseDevice) – The device whose constraints must be obeyed.

  • spacing (float | None, default: None) – The distance between neighbouring qubits in μm. If omitted, the minimal distance for the device is used.

  • prefix (str | None, default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

A register with qubits placed for maximum connectivity.

rotated(degrees)

Makes a new rotated register.

All coordinates are rotated counter-clockwise around the origin.

Parameters:

degrees (float) – The angle of rotation in degrees.

Returns:

A new register rotated around the origin by the given angle.

Return type:

Register

draw(with_labels=True, blockade_radius=None, draw_graph=True, draw_half_radius=False, qubit_colors={}, fig_name=None, kwargs_savefig={}, custom_ax=None, show=True)

Draws the entire register.

Parameters:
  • with_labels (bool, default: True) – If True, writes the qubit ID’s next to each qubit.

  • blockade_radius (Optional[float], default: None) – The distance (in μm) between atoms below the Rydberg blockade effect occurs.

  • draw_half_radius (bool, default: False) – Whether or not to draw the half the blockade radius surrounding each atoms. If True, requires blockade_radius to be defined.

  • draw_graph (bool, default: True) – Whether or not to draw the interaction between atoms as edges in a graph. Will only draw if the blockade_radius is defined.

  • qubit_colors (Mapping[QubitId, str], default: {}) – By default, atoms are drawn with a common default color. If this parameter is present, it replaces the colors for the specified atoms. Non-specified ones are stilled colored with the default value.

  • fig_name (str | None, default: None) – The name on which to save the figure. If None the figure will not be saved.

  • kwargs_savefig (dict, default: {}) – Keywords arguments for matplotlib.pyplot.savefig. Not applicable if fig_name is None.

  • custom_ax (Optional[Axes], default: None) – If present, instead of creating its own Axes object, the function will use the provided one. Warning: if fig_name is set, it may save content beyond what is drawn in this function.

  • show (bool, default: True) – Whether or not to call plt.show() before returning. When combining this plot with other ones in a single figure, one may need to set this flag to False.

Return type:

None

Note

When drawing half the blockade radius, we say there is a blockade effect between atoms whenever their respective circles overlap. This representation is preferred over drawing the full Rydberg radius because it helps in seeing the interactions between atoms.

to_abstract_repr()

Serializes the register into an abstract JSON object.

Return type:

str

static from_abstract_repr(obj_str)

Deserialize a register from an abstract JSON object.

Parameters:

obj_str (str) – the JSON string representing the register encoded in the abstract JSON format.

Return type:

Register

class pulser.register.register3d.Register3D(qubits, **kwargs)

Bases: BaseRegister, RegDrawer

A 3D quantum register containing a set of qubits.

Parameters:

qubits (Mapping[Any, Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]]) – Dictionary with the qubit names as keys and their position coordinates (in μm) as values (e.g. {‘q0’:(2, -1, 0), ‘q1’:(-5, 10, 0), …}).

classmethod cubic(side, spacing=4.0, prefix=None)

Initializes the register with the qubits in a cubic array.

Parameters:
  • side (int) – Side of the cube in number of qubits.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register3D

Returns:

A 3D register with qubits placed in a cubic array.

classmethod cuboid(rows, columns, layers, spacing=4.0, prefix=None)

Initializes the register with the qubits in a cuboid array.

Parameters:
  • rows (int) – Number of rows.

  • columns (int) – Number of columns.

  • layers (int) – Number of layers.

  • spacing (float, default: 4.0) – The distance between neighbouring qubits in μm.

  • prefix (Optional[str], default: None) – The prefix for the qubit ids. If defined, each qubit id starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …)

Return type:

Register3D

Returns:

A 3D register with qubits placed in a cuboid array.

to_2D(tol_width=0.0)

Converts a Register3D into a Register (if possible).

Parameters:
  • tol_width (float, default: 0.0) – The allowed transverse width of

  • projected. (the register to be) –

Return type:

Register

Returns:

Returns a 2D register with the coordinates of the atoms in a plane, if they are coplanar.

Raises:

ValueError – If the atoms are not coplanar.

draw(with_labels=False, blockade_radius=None, draw_graph=True, draw_half_radius=False, qubit_colors={}, projection=False, fig_name=None, kwargs_savefig={})

Draws the entire register.

Parameters:
  • with_labels (bool, default: False) – If True, writes the qubit ID’s next to each qubit.

  • blockade_radius (Optional[float], default: None) – The distance (in μm) between atoms below the Rydberg blockade effect occurs.

  • draw_half_radius (bool, default: False) – Whether or not to draw the half the blockade radius surrounding each atoms. If True, requires blockade_radius to be defined.

  • draw_graph (bool, default: True) – Whether or not to draw the interaction between atoms as edges in a graph. Will only draw if the blockade_radius is defined.

  • qubit_colors (Mapping[QubitId, str], default: {}) – By default, atoms are drawn with a common default color. If this parameter is present, it replaces the colors for the specified atoms. Non-specified ones are stilled colored with the default value.

  • projection (bool, default: False) – Whether to draw a 2D projection instead of a perspective view.

  • fig_name (str | None, default: None) – The name on which to save the figure. If None the figure will not be saved.

  • kwargs_savefig (dict, default: {}) – Keywords arguments for matplotlib.pyplot.savefig. Not applicable if fig_name is None.

Return type:

None

Note

When drawing half the blockade radius, we say there is a blockade effect between atoms whenever their respective circles overlap. This representation is preferred over drawing the full Rydberg radius because it helps in seeing the interactions between atoms.

Register layout

A RegisterLayout is used to define a register from a set of traps. It is intended to be given to the user by the hardware provider as a way of showing which layouts are already available on a given device. In turn, the user can create a Register by selecting the traps on which to place atoms, or even a MappableRegister, which allows for the creation of sequences whose register can be defined at build time.

class pulser.register.register_layout.RegisterLayout(trap_coordinates, slug=None)

A layout of traps out of which registers can be defined.

The traps are always sorted under the same convention: ascending order along x, then along y, then along z (if applicable). Respecting this order, the traps are then numbered starting from 0.

Parameters:
  • trap_coordinates (ArrayLike) – The trap coordinates defining the layout.

  • slug (str | None, default: None) – An optional identifier for the layout.

property coords

A shorthand for ‘sorted_coords’.

define_register(*trap_ids, qubit_ids=None)

Defines a register from selected traps.

Parameters:
  • trap_ids (int) – The trap IDs selected to form the Register.

  • qubit_ids (Optional[Sequence[Union[int, str]]], default: None) – A sequence of unique qubit IDs to associated to the selected traps. Must be of the same length as the selected traps.

Return type:

BaseRegister

Returns:

The respective register instance.

define_detuning_map(detuning_weights, slug=None)

Defines a DetuningMap for some trap ids of the register layout.

Parameters:
  • detuning_weights (Mapping[int, float]) – A mapping between the IDs of the targeted traps and detuning weights (between 0 and 1).

  • slug (str | None, default: None) – An optional identifier for the detuning map.

Return type:

DetuningMap

Returns:

A DetuningMap associating detuning weights to the trap coordinates

of the targeted traps.

draw(blockade_radius=None, draw_graph=False, draw_half_radius=False, projection=True, fig_name=None, kwargs_savefig={})

Draws the entire register layout.

Parameters:
  • blockade_radius (Optional[float], default: None) – The distance (in μm) between atoms below which the Rydberg blockade effect occurs.

  • draw_half_radius (bool, default: False) – Whether or not to draw half the blockade radius surrounding each trap. If True, requires blockade_radius to be defined.

  • draw_graph (bool, default: False) – Whether or not to draw the interaction between atoms as edges in a graph. Will only draw if the blockade_radius is defined.

  • projection (bool, default: True) – If the layout is in 3D, draws it as projections on different planes.

  • fig_name (str | None, default: None) – The name on which to save the figure. If None the figure will not be saved.

  • kwargs_savefig (dict, default: {}) – Keywords arguments for matplotlib.pyplot.savefig. Not applicable if fig_name is None.

Return type:

None

Note

When drawing half the blockade radius, we say there is a blockade effect between atoms whenever their respective circles overlap. This representation is preferred over drawing the full Rydberg radius because it helps in seeing the interactions between atoms.

make_mappable_register(n_qubits, prefix='q')

Creates a mappable register associated with this layout.

A mappable register is a register whose atoms’ positions have not yet been defined. It can be used to create a sequence whose register is only defined when it is built. Note that not all the qubits ‘reserved’ in a MappableRegister need to be in the final Register, as qubits not associated with trap IDs won’t be included. If you intend on defining registers of different sizes from the same mappable register, reserve as many qubits as you need for your largest register.

Parameters:
  • n_qubits (int) – The number of qubits to reserve in the mappable register.

  • prefix (str, default: 'q') – The prefix for the qubit ids. Each qubit ID starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

MappableRegister

Returns:

A substitute for a regular register that can be used to initialize a Sequence.

to_abstract_repr()

Serializes the layout into an abstract JSON object.

Return type:

str

static from_abstract_repr(obj_str)

Deserialize a layout from an abstract JSON object.

Parameters:

obj_str (str) – the JSON string representing the layout encoded in the abstract JSON format.

Return type:

RegisterLayout

property dimensionality

The dimensionality of the coordinates (2 or 3).

get_traps_from_coordinates(*coordinates)

Finds the trap ID for a given set of trap coordinates.

Parameters:

coordinates (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The coordinates to return the trap IDs.

Return type:

list[int]

Returns:

The list of trap IDs corresponding to the coordinates.

property number_of_traps

The number of traps in the layout.

property sorted_coords

The sorted coordinates.

static_hash()

Returns the idempotent hash.

Python’s standard hash is not idempotent as it changes between sessions. This hash can be used when an idempotent hash is required.

Returns:

An hexstring encoding the hash.

Return type:

str

Note

This hash will be returned as an hexstring without the ‘0x’ prefix (unlike what is returned by ‘hex()’).

property traps_dict

Mapping between trap IDs and coordinates.

class pulser.register.mappable_reg.MappableRegister(register_layout, *qubit_ids)

A register with the traps of each qubit still to be defined.

Parameters:
  • register_layout (RegisterLayout) – The register layout on which this register will be defined.

  • qubit_ids (Union[int, str]) – The Ids for the qubits to pre-declare on this register.

property qubit_ids

The qubit IDs of this mappable register.

property layout

The layout used to define the register.

build_register(qubits)

Builds an actual register.

Parameters:

qubits (Mapping[Union[int, str], int]) – A map between the qubit IDs to use and the layout traps where the qubits will be placed. Qubit IDs declared in the MappableRegister but not defined here will simply be left out of the final register.

Return type:

BaseRegister

Returns:

The resulting register.

find_indices(id_list)

Computes indices of qubits.

This can especially be useful when building a Pulser Sequence with a parameter denoting qubits.

Return type:

list[int]

Example

Let reg be a mappable register with qubit Ids “a”, “b”, “c” and “d”.

>>> reg.find_indices(["a", "b", "d", "a"])

It returns [0, 1, 3, 0], following the qubits order of the mappable register (defined by qubit_ids).

Then, it is possible to use these indices when building a sequence, typically to instanciate an array of variables that can be provided as an argument to target_index and phase_shift_index.

When building a sequence and declaring N qubits, their ids should refer to the first N elements of qubit_id.

Parameters:

id_list (Sequence[Union[int, str]]) – IDs of the qubits to denote.

Returns:

Indices of the qubits to denote, only valid for the given mapping.

define_detuning_map(detuning_weights, slug=None)

Defines a DetuningMap for some trap ids of the register layout.

Parameters:
  • detuning_weights (Mapping[int, float]) – A mapping between the IDs of the targeted traps and detuning weights (between 0 and 1).

  • slug (str | None, default: None) – An optional identifier for the detuning map.

Return type:

DetuningMap

Returns:

A DetuningMap associating detuning weights to the trap coordinates

of the targeted traps.

Special cases

Special register layouts defined for convenience.

class pulser.register.special_layouts.SquareLatticeLayout(rows, columns, spacing)

Bases: RegisterLayout

A RegisterLayout with a square lattice pattern in a rectangular shape.

Parameters:
  • rows (int) – The number of rows of traps.

  • columns (int) – The number of columns of traps.

  • spacing (float) – The distance between neighbouring traps (in µm).

square_register(side, prefix='q')

Defines a register with a square shape.

Parameters:
  • side (int) – The length of the square’s side, in number of atoms.

  • prefix (str, default: 'q') – The prefix for the qubit ids. Each qubit ID starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

The register instance created from this layout.

rectangular_register(rows, columns, prefix='q')

Defines a register with a rectangular shape.

Parameters:
  • rows (int) – The number of rows in the register.

  • columns (int) – The number of columns in the register.

  • prefix (str, default: 'q') – The prefix for the qubit ids. Each qubit ID starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

The register instance created from this layout.

class pulser.register.special_layouts.TriangularLatticeLayout(n_traps, spacing)

Bases: RegisterLayout

A RegisterLayout with a triangular lattice pattern in a hexagonal shape.

Parameters:
  • n_traps (int) – The number of traps in the layout.

  • spacing (float) – The distance between neighbouring traps (in µm).

hexagonal_register(n_atoms, prefix='q')

Defines a register with an hexagonal shape.

Parameters:
  • n_atoms (int) – The number of atoms in the register.

  • prefix (str, default: 'q') – The prefix for the qubit ids. Each qubit ID starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

The register instance created from this layout.

rectangular_register(rows, atoms_per_row, prefix='q')

Defines a register with a rectangular shape.

Parameters:
  • rows (int) – The number of rows in the register.

  • atoms_per_row (int) – The number of atoms in each row.

  • prefix (str, default: 'q') – The prefix for the qubit ids. Each qubit ID starts with the prefix, followed by an int from 0 to N-1 (e.g. prefix=’q’ -> IDs: ‘q0’, ‘q1’, ‘q2’, …).

Return type:

Register

Returns:

The register instance created from this layout.

DetuningMap

A DetuningMap is associated to a DMM in a Sequence. It links a set of weights to a set of trap coordinates. It is intended to be defined by the user from a RegisterLayout, a Register or a MappableRegister using define_detuning_map.

class pulser.register.weight_maps.DetuningMap(trap_coordinates, weights, slug=None)

Defines a DetuningMap.

A DetuningMap associates a detuning weight (a value between 0 and 1) to the coordinates of a trap.

Parameters:
  • trap_coordinates (ArrayLike) – An array containing the coordinates of the traps.

  • weights (Sequence[float]) – A list of detuning weights (between 0 and 1) to associate to the traps.

property dimensionality

The dimensionality of the coordinates (2 or 3).

draw(labels=None, fig_name=None, kwargs_savefig={}, custom_ax=None, show=True)

Draws the detuning map.

Parameters:
  • labels (typing.Sequence[QubitId] | None, default: None) – If defined, writes the labels next to each site. Must have the same length and order like the trap_coordinates.

  • fig_name (str | None, default: None) – The name on which to save the figure. If None the figure will not be saved.

  • kwargs_savefig (dict, default: {}) – Keywords arguments for matplotlib.pyplot.savefig. Not applicable if fig_name is None.

  • custom_ax (Optional[Axes], default: None) – If present, instead of creating its own Axes object, the function will use the provided one. Warning: if fig_name is set, it may save content beyond what is drawn in this function.

  • show (bool, default: True) – Whether or not to call plt.show() before returning. When combining this plot with other ones in a single figure, one may need to set this flag to False.

Return type:

None

get_qubit_weight_map(qubits)

Creates a map between qubit IDs and the weight on their sites.

Return type:

dict[Union[int, str], float]

get_traps_from_coordinates(*coordinates)

Finds the trap ID for a given set of trap coordinates.

Parameters:

coordinates (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The coordinates to return the trap IDs.

Return type:

list[int]

Returns:

The list of trap IDs corresponding to the coordinates.

property number_of_traps

The number of traps in the layout.

property sorted_coords

The sorted coordinates.

property sorted_weights

The weights sorted to match the sorted trap coordinates.

static_hash()

Returns the idempotent hash.

Python’s standard hash is not idempotent as it changes between sessions. This hash can be used when an idempotent hash is required.

Returns:

An hexstring encoding the hash.

Return type:

str

Note

This hash will be returned as an hexstring without the ‘0x’ prefix (unlike what is returned by ‘hex()’).

property trap_coordinates

The array of trap coordinates, in the order they were given.

property traps_dict

Mapping between trap IDs and coordinates.

Pulse

Contains the Pulse class, the building block of a pulse sequence.

class pulser.pulse.Pulse(amplitude, detuning, phase, post_phase_shift=0.0)

A generic pulse.

In Pulser, a Pulse is a modulation of a frequency signal in amplitude and/or frequency, with a specific phase, over a given duration. Amplitude and frequency modulations are defined by Waveform child classes. Frequency modulation is determined by a detuning waveform, which describes the shift in frequency from the channel’s central frequency over time. If either quantity is constant throughout the entire pulse, use the ConstantDetuning, ConstantAmplitude or ConstantPulse class method to create it.

Note

We define the amplitude of a pulse to be its Rabi frequency, \(\Omega\), in rad/µs. Equivalently, the detuning is \(\delta\), also in rad/µs.

Parameters:
  • amplitude (Union[Waveform, Parametrized]) – The pulse amplitude waveform.

  • detuning (Union[Waveform, Parametrized]) – The pulse detuning waveform.

  • phase (Union[float, Parametrized]) – The pulse phase (in radians).

  • post_phase_shift (Union[float, Parametrized], default: 0.0) – Optionally lets you add a phase shift(in rads) immediately after the end of the pulse. This allows for enconding of arbitrary single-qubit gates into a single pulse (see Sequence.phase_shift() for more information).

property duration

The duration of the pulse (in ns).

classmethod ConstantDetuning(cls, amplitude, detuning, phase, post_phase_shift=0.0)

Creates a Pulse with an amplitude waveform and a constant detuning.

Parameters:
  • amplitude (Union[Waveform, Parametrized]) – The pulse amplitude waveform.

  • detuning (Union[float, Parametrized]) – The detuning value (in rad/µs).

  • phase (Union[float, Parametrized]) – The pulse phase (in radians).

  • post_phase_shift (Union[float, Parametrized], default: 0.0) – Optionally lets you add a phase shift (in rads) immediately after the end of the pulse.

Return type:

Pulse

classmethod ConstantAmplitude(cls, amplitude, detuning, phase, post_phase_shift=0.0)

Pulse with a constant amplitude and a detuning waveform.

Parameters:
  • amplitude (Union[float, Parametrized]) – The pulse amplitude value (in rad/µs).

  • detuning (Union[Waveform, Parametrized]) – The pulse detuning waveform.

  • phase (Union[float, Parametrized]) – The pulse phase (in radians).

  • post_phase_shift (Union[float, Parametrized], default: 0.0) – Optionally lets you add a phase shift (in rads) immediately after the end of the pulse.

Return type:

Pulse

classmethod ConstantPulse(duration, amplitude, detuning, phase, post_phase_shift=0.0)

Pulse with a constant amplitude and a constant detuning.

Parameters:
  • duration (Union[int, Parametrized]) – The pulse duration (in ns).

  • amplitude (Union[float, Parametrized]) – The pulse amplitude value (in rad/µs).

  • detuning (Union[float, Parametrized]) – The detuning value (in rad/µs).

  • phase (Union[float, Parametrized]) – The pulse phase (in radians).

  • post_phase_shift (Union[float, Parametrized], default: 0.0) – Optionally lets you add a phase shift (in rads) immediately after the end of the pulse.

Return type:

Pulse

draw()

Draws the pulse’s amplitude and frequency waveforms.

Return type:

None

fall_time(channel, in_eom_mode=False)

Calculates the extra time needed to ramp down to zero.

Return type:

int

get_full_duration(channel, in_eom_mode=False)

Calculates the pulse’s full duration after output modulation.

The full duration of a pulse is the total time between the start of the input signal and the end of the output signal, as shown in the sequence.

Parameters:
  • channel (Channel) – The pulse executing the channel.

  • in_eom_mode (bool, default: False) – Whether the pulse is executed in EOM mode.

Return type:

int

Waveforms

All built-in types of waveforms and their Waveform parent class.

class pulser.waveforms.Waveform(duration)

Bases: ABC

The abstract class for a pulse’s waveform.

abstract property duration

The duration of the pulse (in ns).

property samples

The value at each time step that describes the waveform.

Returns:

A numpy array with a value for each time step.

property first_value

The first value in the waveform.

property last_value

The last value in the waveform.

property integral

Integral of the waveform (time in ns, value in rad/µs).

draw(output_channel=None)

Draws the waveform.

Parameters:

output_channel (Optional[Channel], default: None) – The output channel. If given, will draw the modulated waveform on top of the input one.

Return type:

None

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

Waveform

modulated_samples(channel, eom=False)

The waveform samples as output of a given channel.

This duration is adjusted according to the minimal buffer times.

Parameters:
  • channel (Channel) – The channel modulating the waveform.

  • eom (bool, default: False) – Whether to modulate for the EOM.

Return type:

ndarray

Returns:

The array of samples after modulation.

modulation_buffers(channel, eom=False)

The minimal buffers needed around a modulated waveform.

Parameters:
  • channel (Channel) – The channel modulating the waveform.

  • eom (bool, default: False) – Whether to calculate the modulation buffers with the EOM bandwidth.

Return type:

tuple[int, int]

Returns:

The minimum buffer times at the start and end of the samples, in ns.

class pulser.waveforms.CompositeWaveform(*waveforms)

Bases: Waveform

A waveform combining multiple smaller waveforms.

Parameters:

waveforms (Union[Parametrized, Waveform]) – Two or more waveforms to combine.

property duration

The duration of the pulse (in ns).

property waveforms

The waveforms encapsulated in the composite waveform.

class pulser.waveforms.CustomWaveform(samples)

Bases: Waveform

A custom waveform.

Parameters:

samples (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The modulation values at each time step (in rad/µs). The number of samples dictates the duration, in ns.

property duration

The duration of the pulse (in ns).

class pulser.waveforms.ConstantWaveform(duration, value)

Bases: Waveform

A waveform of constant value.

Parameters:
  • duration (Union[int, Parametrized]) – The waveform duration (in ns).

  • value (Union[float, Parametrized]) – The modulation value (in rad/µs).

property duration

The duration of the pulse (in ns).

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

ConstantWaveform

Returns:

The new waveform with the given duration.

class pulser.waveforms.RampWaveform(duration, start, stop)

Bases: Waveform

A linear ramp waveform.

Parameters:
  • duration (Union[int, Parametrized]) – The waveform duration (in ns).

  • start (Union[float, Parametrized]) – The value (in rad/µs) at the initial sample.

  • stop (Union[float, Parametrized]) – The value (in rad/µs) at the final sample.

property duration

The duration of the pulse (in ns).

property slope

Slope of the ramp, in \(s^{-15}\).

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

RampWaveform

Returns:

The new waveform with the given duration.

class pulser.waveforms.BlackmanWaveform(duration, area)

Bases: Waveform

A Blackman window of a specified duration and area.

Parameters:
  • duration (Union[int, Parametrized]) – The waveform duration (in ns).

  • area (Union[float, Parametrized]) – The integral of the waveform. Can be negative, in which case it takes the positive waveform and changes the sign of all its values.

classmethod from_max_val(cls, max_val, area)

Creates a Blackman waveform with a threshold on the maximum value.

Instead of defining a duration, the waveform is defined by its area and the maximum value. The duration is chosen so that the maximum value is not surpassed, but approached as closely as possible.

Parameters:
  • max_val (Union[float, Parametrized]) – The maximum value threshold (in rad/µs). If negative, it is taken as the lower bound i.e. the minimum value that can be reached. The sign of max_val must match the sign of area.

  • area (Union[float, Parametrized]) – The area under the waveform.

Return type:

BlackmanWaveform

property duration

The duration of the pulse (in ns).

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

BlackmanWaveform

Returns:

The new waveform with the same area but a new duration.

class pulser.waveforms.InterpolatedWaveform(duration, values, times=None, interpolator='PchipInterpolator', **interpolator_kwargs)

Bases: Waveform

Creates a waveform from interpolation of a set of data points.

Parameters:
  • duration (Union[int, Parametrized]) – The waveform duration (in ns).

  • values (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]], Parametrized]) – Values of the interpolation points (in rad/µs).

  • times (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]], Parametrized, None], default: None) – Fractions of the total duration (between 0 and 1), indicating where to place each value on the time axis. If not given, the values are spread evenly throughout the full duration of the waveform.

  • interpolator (str, default: 'PchipInterpolator') – The SciPy interpolation class to use. Supports “PchipInterpolator” and “interp1d”.

  • **interpolator_kwargs (Any) – Extra parameters to give to the chosen interpolator class.

property duration

The duration of the pulse (in ns).

property interp_function

The interpolating function.

property data_points

Points (t[ns], value[rad/µs]) that define the interpolation.

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

InterpolatedWaveform

Returns:

The new waveform with the same coordinates for interpolation but a new duration.

class pulser.waveforms.KaiserWaveform(duration, area, beta=14.0)

Bases: Waveform

A Kaiser window of a specified duration and beta parameter.

For more information on the Kaiser window and the beta parameter, check the numpy documentation for the kaiser(M, beta) function: https://numpy.org/doc/stable/reference/generated/numpy.kaiser.html

Parameters:
  • duration (Union[int, Parametrized]) – The waveform duration (in ns).

  • area (Union[float, Parametrized]) – The integral of the waveform. Can be negative, in which case it takes the positive waveform and changes the sign of all its values.

  • beta (Union[float, Parametrized, None], default: 14.0) – The beta parameter of the Kaiser window. The default value is 14.

classmethod from_max_val(cls, max_val, area, beta=14.0)

Creates a Kaiser waveform with a threshold on the maximum value.

Instead of defining a duration, the waveform is defined by its area and the maximum value. The duration is chosen so that the maximum value is not surpassed, but approached as closely as possible.

Parameters:
  • max_val (Union[float, Parametrized]) – The maximum value threshold (in rad/µs). If negative, it is taken as the lower bound i.e. the minimum value that can be reached. The sign of max_val must match the sign of area.

  • area (Union[float, Parametrized]) – The area under the waveform.

  • beta (Union[float, Parametrized, None], default: 14.0) – The beta parameter of the Kaiser window. The default value is 14.

Return type:

KaiserWaveform

property duration

The duration of the pulse (in ns).

change_duration(new_duration)

Returns a new waveform with modified duration.

Parameters:

new_duration (int) – The duration of the new waveform.

Return type:

KaiserWaveform

Returns:

The new waveform with the same area and beta but a new duration.

Devices

Structure of a Device

The Device class sets the structure of a physical device, while VirtualDevice is a more permissive device type which can only be used in emulators, as it does not necessarily represent the constraints of a physical device.

Illustrative instances of Device (see Physical Devices) and VirtualDevice (the MockDevice) come included in the pulser.devices module.

class pulser.devices._device_datacls.Device(name, dimensions, rydberg_level, min_atom_distance, max_atom_num, max_radial_distance, interaction_coeff_xy=None, supports_slm_mask=False, max_layout_filling=0.5, max_sequence_duration=None, max_runs=None, channel_ids=None, channel_objects=<factory>, dmm_objects=<factory>, pre_calibrated_layouts=<factory>)

Specifications of a neutral-atom device.

A Device instance is immutable and must have all of its parameters defined. For usage in emulations, it can be converted to a VirtualDevice through the Device.to_virtual() method.

name

The name of the device.

dimensions

Whether it supports 2D or 3D arrays.

rybderg_level

The value of the principal quantum number \(n\) when the Rydberg level used is of the form \(|nS_{1/2}, m_j = +1/2\rangle\).

max_atom_num

Maximum number of atoms supported in an array.

Type:

int

max_radial_distance

The furthest away an atom can be from the center of the array (in μm).

Type:

int

min_atom_distance

The closest together two atoms can be (in μm).

interaction_coeff_xy

\(C_3/\hbar\) (in \(rad \cdot \mu s^{-1} \cdot \mu m^3\)), which sets the van der Waals interaction strength between atoms in different Rydberg states. Needed only if there is a Microwave channel in the device. If unsure, 3700.0 is a good default value.

supports_slm_mask

Whether the device supports the SLM mask feature.

max_layout_filling

The largest fraction of a layout that can be filled with atoms.

max_sequence_duration

The maximum allowed duration for a sequence (in ns).

max_runs

The maximum number of runs allowed on the device. Only used for backend execution.

pre_calibrated_layouts

RegisterLayout instances that are already available on the Device.

Type:

tuple[RegisterLayout, …]

property calibrated_register_layouts

Register layouts already calibrated on this device.

is_calibrated_layout(register_layout)

Checks whether a layout is within the calibrated layouts.

Parameters:

register_layout (RegisterLayout) – The RegisterLayout to check.

Return type:

bool

Returns:

True if register_layout is found among calibrated_register_layouts, False otherwise.

register_is_from_calibrated_layout(register)

Checks whether a register was constructed from a calibrated layout.

If the register is a BaseRegister, checks that it has a layout. If so, or if it is a MappableRegister, check that its layout is within the calibrated layouts.

Parameters:

register_layout – the Register or MappableRegister to check.

Return type:

bool

Returns:

True if register has a layout and it is found among calibrated_register_layouts, False otherwise.

to_virtual()

Converts the Device into a VirtualDevice.

Return type:

VirtualDevice

print_specs()

Prints the device specifications.

Return type:

None

property channels

Dictionary of available channels on this device.

property dmm_channels

Dictionary of available DMM channels on this device.

property interaction_coeff

The interaction coefficient for the chosen Rydberg level.

Corresponds to \(C_6/\hbar\) (in units of \(rad \cdot \mu s^{-1} \cdot \mu m^6\)) for the interaction term of the Ising hamiltonian.

rabi_from_blockade(blockade_radius)

The maximum Rabi frequency value to enforce a given blockade radius.

Parameters:

blockade_radius (float) – The Rydberg blockade radius, in µm.

Return type:

float

Returns:

The maximum rabi frequency value, in rad/µs.

rydberg_blockade_radius(rabi_frequency)

Calculates the Rydberg blockade radius for a given Rabi frequency.

Parameters:

rabi_frequency (float) – The Rabi frequency, in rad/µs.

Return type:

float

Returns:

The rydberg blockade radius, in μm.

property supported_bases

Available electronic transitions for control and measurement.

to_abstract_repr()

Serializes the device into an abstract JSON object.

Return type:

str

validate_layout(layout)

Checks if a register layout is compatible with this device.

Parameters:

layout (RegisterLayout) – The RegisterLayout to validate.

Return type:

None

validate_layout_filling(register)

Checks if a register properly fills its layout.

Parameters:

register (BaseRegister | MappableRegister) – The register to validate. Must be created from a register layout.

Return type:

None

validate_register(register)

Checks if ‘register’ is compatible with this device.

Parameters:

register (BaseRegister) – The Register to validate.

Return type:

None

class pulser.devices._device_datacls.VirtualDevice(name, dimensions, rydberg_level, min_atom_distance=0, max_atom_num=None, max_radial_distance=None, interaction_coeff_xy=None, supports_slm_mask=True, max_layout_filling=0.5, max_sequence_duration=None, max_runs=None, reusable_channels=True, channel_ids=None, channel_objects=<factory>, dmm_objects=(DMM.Global(Max Absolute Detuning: None, Max Amplitude: 0, Clock period: 1 ns, Minimum pulse duration: 1 ns, Maximum pulse duration: 100000000 ns, Basis: 'ground-rydberg'), ))

Specifications of a virtual neutral-atom device.

A VirtualDevice can only be used for emulation and allows some parameters to be left undefined. Furthermore, it optionally allows the same channel to be declared multiple times in the same Sequence (when reusable_channels=True) and allows the Rydberg level to be changed.

name

The name of the device.

dimensions

Whether it supports 2D or 3D arrays.

rybderg_level

The value of the principal quantum number \(n\) when the Rydberg level used is of the form \(|nS_{1/2}, m_j = +1/2\rangle\).

max_atom_num

Maximum number of atoms supported in an array.

Type:

int | None

max_radial_distance

The furthest away an atom can be from the center of the array (in μm).

Type:

int | None

min_atom_distance

The closest together two atoms can be (in μm).

Type:

float

interaction_coeff_xy

\(C_3/\hbar\) (in \(rad \cdot \mu s^{-1} \cdot \mu m^3\)), which sets the van der Waals interaction strength between atoms in different Rydberg states. Needed only if there is a Microwave channel in the device. If unsure, 3700.0 is a good default value.

supports_slm_mask

Whether the device supports the SLM mask feature.

Type:

bool

max_layout_filling

The largest fraction of a layout that can be filled with atoms.

max_sequence_duration

The maximum allowed duration for a sequence (in ns).

max_runs

The maximum number of runs allowed on the device. Only used for backend execution.

reusable_channels

Whether each channel can be declared multiple times on the same pulse sequence.

Type:

bool

change_rydberg_level(ryd_lvl)

Changes the Rydberg level used in the Device.

Find the \(C_6/\hbar\) coefficient matching the Rydberg level on this page

Parameters:

ryd_lvl (int) – the Rydberg level to use (between 50 and 100).

Return type:

None

property channels

Dictionary of available channels on this device.

property dmm_channels

Dictionary of available DMM channels on this device.

property interaction_coeff

The interaction coefficient for the chosen Rydberg level.

Corresponds to \(C_6/\hbar\) (in units of \(rad \cdot \mu s^{-1} \cdot \mu m^6\)) for the interaction term of the Ising hamiltonian.

rabi_from_blockade(blockade_radius)

The maximum Rabi frequency value to enforce a given blockade radius.

Parameters:

blockade_radius (float) – The Rydberg blockade radius, in µm.

Return type:

float

Returns:

The maximum rabi frequency value, in rad/µs.

rydberg_blockade_radius(rabi_frequency)

Calculates the Rydberg blockade radius for a given Rabi frequency.

Parameters:

rabi_frequency (float) – The Rabi frequency, in rad/µs.

Return type:

float

Returns:

The rydberg blockade radius, in μm.

property supported_bases

Available electronic transitions for control and measurement.

to_abstract_repr()

Serializes the device into an abstract JSON object.

Return type:

str

validate_layout(layout)

Checks if a register layout is compatible with this device.

Parameters:

layout (RegisterLayout) – The RegisterLayout to validate.

Return type:

None

validate_layout_filling(register)

Checks if a register properly fills its layout.

Parameters:

register (BaseRegister | MappableRegister) – The register to validate. Must be created from a register layout.

Return type:

None

validate_register(register)

Checks if ‘register’ is compatible with this device.

Parameters:

register (BaseRegister) – The Register to validate.

Return type:

None

Physical Devices

Each Device` instance holds the characteristics of a physical device, which when associated with a pulser.Sequence condition its development.

pulser.devices.AnalogDevice = AnalogDevice
Register parameters:
  • Dimensions: 2D

  • Rydberg level: 60

  • Maximum number of atoms: 25

  • Maximum distance from origin: 35 μm

  • Minimum distance between neighbouring atoms: 5 μm

  • Maximum layout filling fraction: 0.5

  • SLM Mask: No

  • Maximum sequence duration: 4000 ns

Channels:
  • ID: ‘rydberg_global’
    • Type: Rydberg (ground-rydberg basis)

    • Addressing: Global

    • Maximum \(\Omega\): 12.57 rad/µs

    • Maximum \(|\delta|\): 125.7 rad/µs

    • Minimum average amplitude: 0 rad/µs

    • Clock period: 4 ns

    • Minimum instruction duration: 16 ns

pulser.devices.DigitalAnalogDevice = DigitalAnalogDevice
Register parameters:
  • Dimensions: 2D

  • Rydberg level: 70

  • Maximum number of atoms: 100

  • Maximum distance from origin: 50 μm

  • Minimum distance between neighbouring atoms: 4 μm

  • Maximum layout filling fraction: 0.5

  • SLM Mask: Yes

Channels:
  • ID: ‘rydberg_global’
    • Type: Rydberg (ground-rydberg basis)

    • Addressing: Global

    • Maximum \(\Omega\): 15.71 rad/µs

    • Maximum \(|\delta|\): 125.7 rad/µs

    • Minimum average amplitude: 0 rad/µs

    • Clock period: 4 ns

    • Minimum instruction duration: 16 ns

  • ID: ‘rydberg_local’
    • Type: Rydberg (ground-rydberg basis)

    • Addressing: Local

    • Maximum \(\Omega\): 62.83 rad/µs

    • Maximum \(|\delta|\): 125.7 rad/µs

    • Minimum average amplitude: 0 rad/µs

    • Minimum time between retargets: 220 ns

    • Fixed retarget time: 0 ns

    • Maximum simultaneous targets: 1

    • Clock period: 4 ns

    • Minimum instruction duration: 16 ns

  • ID: ‘raman_local’
    • Type: Raman (digital basis)

    • Addressing: Local

    • Maximum \(\Omega\): 62.83 rad/µs

    • Maximum \(|\delta|\): 125.7 rad/µs

    • Minimum average amplitude: 0 rad/µs

    • Minimum time between retargets: 220 ns

    • Fixed retarget time: 0 ns

    • Maximum simultaneous targets: 1

    • Clock period: 4 ns

    • Minimum instruction duration: 16 ns

  • ID: ‘dmm_0’
    • Type: DMM (ground-rydberg basis)

    • Addressing: Global

    • Maximum \(\Omega\): 0 rad/µs

    • Bottom \(|\delta|\): -125.7 rad/µs

    • Minimum average amplitude: 0 rad/µs

    • Clock period: 4 ns

    • Minimum instruction duration: 16 ns

Channels

Base Channel

Defines the Channel ABC.

class pulser.channels.base_channel.Channel(addressing, max_abs_detuning, max_amp, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=100000000, min_avg_amp=0, mod_bandwidth=None)

Base class of a hardware channel.

Not to be initialized itself, but rather through a child class and the Local or Global classmethods.

Parameters:
  • addressing (Literal['Global', 'Local']) – “Local” or “Global”.

  • max_abs_detuning (Optional[float]) – Maximum possible detuning (in rad/µs), in absolute value.

  • max_amp (Optional[float]) – Maximum pulse amplitude (in rad/µs).

  • min_retarget_interval (Optional[int], default: None) – Minimum time required between the ends of two target instructions (in ns).

  • fixed_retarget_t (Optional[int], default: None) – Time taken to change the target (in ns).

  • max_targets (Optional[int], default: None) – How many qubits can be addressed at once by the same beam.

  • clock_period (int, default: 1) – The duration of a clock cycle (in ns). The duration of a pulse or delay instruction is enforced to be a multiple of the clock cycle.

  • min_duration (int, default: 1) – The shortest duration an instruction can take.

  • max_duration (Optional[int], default: 100000000) – The longest duration an instruction can take.

  • min_avg_amp (int, default: 0) – The minimum average amplitude of a pulse (when not zero).

  • mod_bandwidth (Optional[float], default: None) – The modulation bandwidth at -3dB (50% reduction), in MHz.

Example

To create a channel targeting the ‘ground-rydberg’ transition globally, call Rydberg.Global(...).

property name

The name of the channel.

abstract property basis

The addressed basis name.

property rise_time

The rise time (in ns).

Defined as the time taken to go from 10% to 90% output in response to a step change in the input.

property phase_jump_time

Time taken to change the phase between consecutive pulses (in ns).

Corresponds to two times the rise time.

is_virtual()

Whether the channel is virtual (i.e. partially defined).

Return type:

bool

supports_eom()

Whether the channel supports EOM mode operation.

Return type:

bool

classmethod Local(max_abs_detuning, max_amp, min_retarget_interval=0, fixed_retarget_t=0, max_targets=None, **kwargs)

Initializes the channel with local addressing.

Parameters:
  • max_abs_detuning (Optional[float]) – Maximum possible detuning (in rad/µs), in absolute value.

  • max_amp (Optional[float]) – Maximum pulse amplitude (in rad/µs).

  • min_retarget_interval (int, default: 0) – Minimum time required between two target instructions (in ns).

  • fixed_retarget_t (int, default: 0) – Time taken to change the target (in ns).

  • max_targets (Optional[int], default: None) – Maximum number of atoms the channel can target simultaneously.

Keyword Arguments:
  • clock_period (int, default=4) – The duration of a clock cycle (in ns). The duration of a pulse or delay instruction is enforced to be a multiple of the clock cycle.

  • min_duration (int, default=1) – The shortest duration an instruction can take.

  • max_duration (Optional[int], default=10000000) – The longest duration an instruction can take.

  • mod_bandwidth (Optional[float], default=None) – The modulation bandwidth at -3dB (50% reduction), in MHz.

  • min_avg_amp – The minimum average amplitude of a pulse (when not zero).

Return type:

TypeVar(ChannelType, bound= Channel)

classmethod Global(max_abs_detuning, max_amp, **kwargs)

Initializes the channel with global addressing.

Parameters:
  • max_abs_detuning (Optional[float]) – Maximum possible detuning (in rad/µs), in absolute value.

  • max_amp (Optional[float]) – Maximum pulse amplitude (in rad/µs).

Keyword Arguments:
  • clock_period (int, default=4) – The duration of a clock cycle (in ns). The duration of a pulse or delay instruction is enforced to be a multiple of the clock cycle.

  • min_duration (int, default=1) – The shortest duration an instruction can take.

  • max_duration (Optional[int], default=10000000) – The longest duration an instruction can take.

  • mod_bandwidth (Optional[float], default=None) – The modulation bandwidth at -3dB (50% reduction), in MHz.

  • min_avg_amp – The minimum average amplitude of a pulse (when not zero).

Return type:

TypeVar(ChannelType, bound= Channel)

validate_duration(duration)

Validates and adapts the duration of an instruction on this channel.

Parameters:

duration (int) – The duration to validate.

Return type:

int

Returns:

The duration, potentially adapted to the channels specs.

validate_pulse(pulse)

Checks if a pulse can be executed this channel.

Parameters:

pulse (Pulse) – The pulse to validate.

Return type:

None

modulate(input_samples, keep_ends=False, eom=False)

Modulates the input according to the channel’s modulation bandwidth.

Parameters:
  • input_samples (ndarray) – The samples to modulate.

  • keep_ends (bool, default: False) – Assume the end values of the samples were kept constant (i.e. there is no ramp from zero on the ends).

  • eom (bool, default: False) – Whether to calculate the modulation using the EOM bandwidth.

Return type:

ndarray

Returns:

The modulated output signal.

static apply_modulation(input_samples, mod_bandwidth)

Applies the modulation transfer fuction to the input samples.

Return type:

ndarray

Note

This is strictly the application of the modulation transfer function. The samples should be padded beforehand.

Parameters:
  • input_samples (ndarray) – The samples to modulate.

  • mod_bandwidth (float) – The modulation bandwidth at -3dB (50% reduction), in MHz.

calc_modulation_buffer(input_samples, mod_samples, max_allowed_diff=0.01, eom=False)

Calculates the minimal buffers needed around a modulated waveform.

Parameters:
  • input_samples (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The input samples.

  • mod_samples (Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]) – The modulated samples. Must be of size len(input_samples) + 2 * self.rise_time.

  • max_allowed_diff (float, default: 0.01) – The maximum allowed difference between the input and modulated samples at the end points.

  • eom (bool, default: False) – Whether to calculate the modulation buffers with the EOM bandwidth.

Return type:

tuple[int, int]

Returns:

The minimum buffer times at the start and end of the samples, in ns.

default_id()

Generates the default ID for indexing this channel in a Device.

Return type:

str

Available Channels

The Channel subclasses.

class pulser.channels.channels.Raman(addressing, max_abs_detuning, max_amp, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=100000000, min_avg_amp=0, mod_bandwidth=None)

Bases: Channel

Raman beam channel.

Channel targeting the transition between the hyperfine ground states, in which the ‘digital’ basis is encoded. See base class.

property basis

The addressed basis name.

class pulser.channels.channels.Rydberg(addressing, max_abs_detuning, max_amp, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=100000000, min_avg_amp=0, mod_bandwidth=None, eom_config=None)

Bases: Channel

Rydberg beam channel.

Channel targeting the transition between the ground and rydberg states, thus encoding the ‘ground-rydberg’ basis. See base class.

property basis

The addressed basis name.

class pulser.channels.channels.Microwave(addressing, max_abs_detuning, max_amp, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=100000000, min_avg_amp=0, mod_bandwidth=None)

Bases: Channel

Microwave adressing channel.

Channel targeting the transition between two rydberg states, thus encoding the ‘XY’ basis. See base class.

property basis

The addressed basis name.

default_id()

Generates the default ID for indexing this channel in a Device.

Return type:

str

class pulser.channels.dmm.DMM(clock_period=1, min_duration=1, max_duration=100000000, min_avg_amp=0, mod_bandwidth=None, bottom_detuning=None, total_bottom_detuning=None)

Bases: Channel

Defines a Detuning Map Modulator (DMM) Channel.

A Detuning Map Modulator can be used to define Global detuning Pulses (of zero amplitude and phase). These Pulses are locally modulated by the weights of a DetuningMap, thus providing a local control over the detuning. The detuning of the pulses added to a DMM has to be negative, between 0 and bottom_detuning, and the sum of the weights multiplied by that detuning has to be below total_bottom_detuning. Channel targeting the transition between the ground and rydberg states, thus encoding the ‘ground-rydberg’ basis.

Note

The protocol to add pulses to the DMM Channel is by default “no-delay”.

Parameters:
  • bottom_detuning (float | None, default: None) – Minimum possible detuning per atom (in rad/µs), must be below zero.

  • total_bottom_detuning (float | None, default: None) – Minimum possible detuning distributed on all atoms (in rad/µs), must be below zero.

  • clock_period (int, default: 1) – The duration of a clock cycle (in ns). The duration of a pulse or delay instruction is enforced to be a multiple of the clock cycle.

  • min_duration (int, default: 1) – The shortest duration an instruction can take.

  • max_duration (Optional[int], default: 100000000) – The longest duration an instruction can take.

  • min_avg_amp (int, default: 0) – The minimum average amplitude of a pulse (when not zero).

  • mod_bandwidth (Optional[float], default: None) – The modulation bandwidth at -3dB (50% reduction), in MHz.

property basis

The addressed basis name.

is_virtual()

Whether the channel is virtual (i.e. partially defined).

Return type:

bool

validate_pulse(pulse, detuning_map=DetuningMap_9bac4c689e17c53052ff99b9305bfdc6be69a86f17e60e68f62375e7b5ef871a)

Checks if a pulse can be executed via this DMM on a DetuningMap.

Parameters:
  • pulse (Pulse) – The pulse to validate.

  • detuning_map (DetuningMap, default: DetuningMap_9bac4c689e17c53052ff99b9305bfdc6be69a86f17e60e68f62375e7b5ef871a) – The detuning map on which the pulse is applied (defaults to a detuning map with weight 1.0).

Return type:

None

EOM Mode Configuration

Configuration parameters for a channel’s EOM.

class pulser.channels.eom.RydbergBeam(value)

Bases: Flag

The beams that make up a Rydberg channel.

class pulser.channels.eom.BaseEOM(mod_bandwidth, custom_buffer_time=None)

Bases: _BaseEOMDefaults, _BaseEOM

A base class for the EOM configuration.

mod_bandwidth

The EOM modulation bandwidth at -3dB (50% reduction), in MHz.

custom_buffer_time

A custom wait time to enforce during EOM buffers.

Type:

int | None

property rise_time

The rise time (in ns).

Defined as the time taken to go from 10% to 90% output in response to a step change in the input.

class pulser.channels.eom.RydbergEOM(limiting_beam, max_limiting_amp, intermediate_detuning, controlled_beams, mod_bandwidth, custom_buffer_time=None, multiple_beam_control=True)

Bases: _RydbergEOMDefaults, BaseEOM, _RydbergEOM

The EOM configuration for a Rydberg channel.

limiting_beam

The beam with the smallest amplitude range.

max_limiting_amp

The maximum amplitude the limiting beam can reach, in rad/µs.

intermediate_detuning

The detuning between the two beams, in rad/µs.

controlled_beams

The beams that can be switched on/off with an EOM.

mod_bandwidth

The EOM modulation bandwidth at -3dB (50% reduction), in MHz.

custom_buffer_time

A custom wait time to enforce during EOM buffers.

multiple_beam_control

Whether both EOMs can be used simultaneously. Ignored when only one beam can be controlled.

Type:

bool

calculate_detuning_off(amp_on, detuning_on, optimal_detuning_off)

Calculates the detuning when the amplitude is off in EOM mode.

Parameters:
  • amp_on (float) – The amplitude of the EOM pulses (in rad/µs).

  • detuning_on (float) – The detuning of the EOM pulses (in rad/µs).

  • optimal_detuning_off (float) – The optimal value of detuning (in rad/µs) when there is no pulse being played. It will choose the closest value among the existing options.

Return type:

float

detuning_off_options(rabi_frequency, detuning_on)

Calculates the possible detuning values when the amplitude is off.

Parameters:
  • rabi_frequency (float) – The Rabi frequency when executing a pulse, in rad/µs.

  • detuning_on (float) – The detuning when executing a pulse, in rad/µs.

Return type:

ndarray

Returns:

The possible detuning values when in between pulses.

Sampler

The main function for sequence sampling.

pulser.sampler.sampler.sample(seq, modulation=False, extended_duration=None)

Construct samples of a Sequence.

Parameters:
  • seq (Sequence) – The sequence to sample.

  • modulation (bool, default: False) – Whether to modulate the samples.

  • extended_duration (Optional[int], default: None) – If defined, extends the samples duration to the desired value.

Return type:

SequenceSamples

Dataclasses for storing and processing the samples.

class pulser.sampler.samples.ChannelSamples(amp, det, phase, slots=<factory>, eom_blocks=<factory>, eom_start_buffers=<factory>, eom_end_buffers=<factory>, target_time_slots=<factory>)

Gathers samples of a channel.

property initial_targets

Returns the initial targets.

extend_duration(new_duration)

Extends the duration of the samples.

Pads the amplitude and detuning samples with zeros and the phase with its last value (or zero if empty).

Parameters:

new_duration (int) – The new duration for the samples (in ns). Must be greater than or equal to the current duration.

Return type:

ChannelSamples

Returns:

The extended channel samples.

is_empty()

Whether the channel is effectively empty.

The channel is considered empty if all amplitude and detuning samples are zero.

Return type:

bool

get_eom_mode_intervals()

Returns EOM mode intervals.

Return type:

list[tuple[int, int]]

in_eom_mode(slot)

States if a time slot is inside an EOM mode block.

Return type:

bool

modulate(channel_obj, max_duration=None)

Modulates the samples for a given channel.

It assumes that the detuning and phase start at their initial values and are kept at their final values.

Parameters:
  • channel_obj (Channel) – The channel object for which to modulate the samples.

  • max_duration (Optional[int], default: None) – The maximum duration of the modulation samples. If defined, truncates them to have a duration less than or equal to the given value.

Return type:

ChannelSamples

Returns:

The modulated channel samples.

class pulser.sampler.samples.DMMSamples(amp, det, phase, slots=<factory>, eom_blocks=<factory>, eom_start_buffers=<factory>, eom_end_buffers=<factory>, target_time_slots=<factory>, detuning_map=None, qubits=<factory>)

Gathers samples of a DMM channel.

class pulser.sampler.samples.SequenceSamples(channels, samples_list, _ch_objs, _basis_ref=<factory>, _slm_mask=<factory>, _magnetic_field=None, _measurement=None)

Gather samples for each channel in a sequence.

property channel_samples

Mapping between the channel name and its samples.

property max_duration

The maximum duration among the channel samples.

property used_bases

The bases with non-zero pulses.

extend_duration(new_duration)

Extend the duration of each samples to a new duration.

Return type:

SequenceSamples

to_nested_dict(all_local=False)

Format in the nested dictionary form.

This is the format expected by pulser_simulation.Simulation().

Parameters:

all_local (bool, default: False) – Forces all samples to be distributed by their individual targets, even when applied by a global channel.

Return type:

dict

Returns:

A nested dictionary splitting the samples according to their addressing (‘Global’ or ‘Local’), the targeted basis and, in the ‘Local’ case, the targeted qubit.

Result

Classes to store measurement results.

class pulser.result.Result(atom_order, meas_basis)

Bases: ABC

Base class for storing the result of a sequence run.

property sampling_dist

Sampling distribution of the measured bitstring.

Parameters:
  • atom_order – The order of the atoms in the bitstrings that represent the measured states.

  • meas_basis – The measurement basis.

abstract property sampling_errors

The sampling error associated to each bitstring’s sampling rate.

Uses the standard error of the mean as a quantifier for sampling error.

get_samples(n_samples)

Takes multiple samples from the sampling distribution.

Parameters:

n_samples (int) – Number of samples to return.

Return type:

Counter[str]

Returns:

Samples of bitstrings corresponding to measured quantum states.

get_state()

Gets the quantum state associated with the result.

Can only be defined for emulation results that don’t resort to sampling a quantum state (which is the case for certain types of noise).

Return type:

Any

plot_histogram(min_rate=0.001, max_n_bitstrings=None, show=True)

Plots the result in an histogram.

Parameters:
  • min_rate (float, default: 0.001) – The minimum sampling rate a bitstring must have to be displayed.

  • max_n_bitstrings (int | None, default: None) – An optional limit on the number of bitrstrings displayed.

  • show (bool, default: True) – Whether or not to call plt.show() before returning.

Return type:

None

class pulser.result.SampledResult(atom_order, meas_basis, bitstring_counts)

Bases: Result

Represents the result of a run from a series of samples.

Parameters:
  • atom_order (tuple[Union[int, str], ...]) – The order of the atoms in the bitstrings that represent the measured states.

  • meas_basis (str) – The measurement basis.

  • bitstring_counts (dict[str, int]) – The number of times each bitstring was measured.

property sampling_errors

The sampling error associated to each bitstring’s sampling rate.

Uses the standard error of the mean as a quantifier for sampling error.

class pulser.result.Results

Bases: Sequence[ResultType]

An immutable sequence of results.