Devices and Virtual Devices
import numpy as npfrom dataclasses import replacefrom pulser.devices import Device, VirtualDevice, AnalogDevice, MockDevicefrom pulser.channels import Rydberg, Raman, Microwavefrom pulser import Pulse, Sequence, Register
Physical devices
Section titled “Physical devices”pulser.devices
.Device
class. They are constrained by physical considerations and all their parameters are defined.As an example, we present below the specifications of the physical device AnalogDevice
, which can be accessed via the Device.print_specs()
method.
# Display AnalogDevice's specificationsAnalogDevice.print_specs()
---------------------------
AnalogDevice Specifications
---------------------------
A realistic device for analog sequence execution.
Register parameters:
- Dimensions: 2D
- Maximum number of atoms: 80
- Maximum distance from origin: 38 µm
- Minimum distance between neighbouring atoms: 5 μm
Layout parameters:
- Requires layout: Yes
- Accepts new layout: Yes
- Minimal number of traps: 1
- Maximum layout filling fraction: 0.5
Device parameters:
- Rydberg level: 60
- Ising interaction coefficient: 865723.02
- Channels can be reused: No
- Supported bases: ground-rydberg
- Supported states: r, g
- SLM Mask: No
- Maximum sequence duration: 6000 ns
- Maximum number of runs: 2000
Channels:
- 'rydberg_global': Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None)
Virtual Devices
Section titled “Virtual Devices”Converting a Device into a Virtual Device
Section titled “Converting a Device into a Virtual Device”However, we sometimes want to perform the computations on a more permissive device, a device that would have more dimensions or more atoms for instance, or more types of channels. This can be done on an emulator behaving like a device. The VirtualDevice
class is useful to define such an emulator, a virtual device.
Let’s start by configuring a virtual device having the same parameters as AnalogDevice
. To do this, we use the Device.to_virtual()
method that creates a virtual device from a physical one.
# Converting the Device object in a VirtualDevice objectVirtualAnalog = AnalogDevice.to_virtual()print(VirtualAnalog)
VirtualDevice(name='AnalogDevice', dimensions=2, rydberg_level=60, min_atom_distance=5, max_atom_num=80, max_radial_distance=38, interaction_coeff_xy=None, supports_slm_mask=False, max_layout_filling=0.5, optimal_layout_filling=0.45, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=6000, max_runs=2000, requires_layout=True, reusable_channels=False, channel_ids=('rydberg_global',), channel_objects=(Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None),), dmm_objects=(), default_noise_model=None)
Changing parameters of a virtual device with dataclasses.replace()
Section titled “Changing parameters of a virtual device with dataclasses.replace()”dataclasses.replace()
can be used to create a new VirtualDevice
having some parameters changed.AnalogDevice
but allowing working in 3 dimensions.# Adding a dimension to the emulatorVirtualAnalog3D = replace(VirtualAnalog, dimensions=3)print(VirtualAnalog3D)
VirtualDevice(name='AnalogDevice', dimensions=3, rydberg_level=60, min_atom_distance=5, max_atom_num=80, max_radial_distance=38, interaction_coeff_xy=None, supports_slm_mask=False, max_layout_filling=0.5, optimal_layout_filling=0.45, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=6000, max_runs=2000, requires_layout=True, reusable_channels=False, channel_ids=('rydberg_global',), channel_objects=(Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None),), dmm_objects=(), default_noise_model=None)
Unrealistic parameters of a virtual device
Section titled “Unrealistic parameters of a virtual device”VirtualDevice
, some are called unrealistic as they do not refer to something physically implementable.# Changing the Rydberg levelVirtualAnalog3D.change_rydberg_level(61)print(VirtualAnalog3D)
VirtualDevice(name='AnalogDevice', dimensions=3, rydberg_level=61, min_atom_distance=5, max_atom_num=80, max_radial_distance=38, interaction_coeff_xy=None, supports_slm_mask=False, max_layout_filling=0.5, optimal_layout_filling=0.45, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=6000, max_runs=2000, requires_layout=True, reusable_channels=False, channel_ids=('rydberg_global',), channel_objects=(Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None),), dmm_objects=(), default_noise_model=None)
# Enable the multiple declaration of a channel in a sequenceVirtualAnalog3D = replace(VirtualAnalog3D, reusable_channels=True)# Creating a square registerreg = Register.square( 4, spacing=5, prefix="q") # 4x4 array with atoms 5 um apart# Building a sequence with the register and the virtual deviceseq = Sequence(reg, VirtualAnalog3D)# Declare twice the channel "rydberg_global"seq.declare_channel("ch0", "rydberg_global")seq.declare_channel("ch1", "rydberg_global")# Show the declared channelsprint(seq.declared_channels)
{'ch0': Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None), 'ch1': Rydberg(addressing='Global', max_abs_detuning=125.66370614359172, max_amp=12.566370614359172, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=4, min_duration=16, max_duration=100000000, min_avg_amp=0, mod_bandwidth=8, custom_phase_jump_time=None, eom_config=RydbergEOM(limiting_beam=<RydbergBeam.RED: 2>, max_limiting_amp=188.49555921538757, intermediate_detuning=2827.4333882308138, controlled_beams=(<RydbergBeam.BLUE: 1>,), mod_bandwidth=40, custom_buffer_time=240, multiple_beam_control=True, blue_shift_coeff=1.0, red_shift_coeff=1.0), propagation_dir=None)}
Building your own virtual device
Section titled “Building your own virtual device”More generally, the VirtualDevice
class is more permissive than the Device
class. In fact, some parameters can be left undefined and simpler devices can be built with a VirtualDevice
instance. A virtual device only needs a name
, a dimension
and a rydberg_level
to be initialized.
BasicVirtualDevice = VirtualDevice( name="BasicMockDevice", dimensions=2, rydberg_level=61,)print(BasicVirtualDevice)
VirtualDevice(name='BasicMockDevice', dimensions=2, rydberg_level=61, 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, optimal_layout_filling=None, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=None, max_runs=None, requires_layout=False, reusable_channels=True, channel_ids=(), channel_objects=(), dmm_objects=(DMM(addressing='Global', max_abs_detuning=None, max_amp=0, 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, custom_phase_jump_time=None, eom_config=None, propagation_dir=None, bottom_detuning=None, total_bottom_detuning=None),), default_noise_model=None)
Defining the channels of your device
Section titled “Defining the channels of your device”channel_objects
. Their IDs can be defined in channel_ids
, but if no IDs are provided, they will be automatically generated as {channeltype}_adressing
.Rydberg.Global
channel is automatically named rydberg_global
in the specifications of AnalogDevice
.# This basic device can be used for digital quantum computingDigitalQCVirtualDevice = replace( BasicVirtualDevice, channel_ids=( "ryd_loc", "ram_loc", ), channel_objects=( Rydberg.Local(None, None, max_duration=None), Raman.Local(None, None, max_duration=None), ),)print(DigitalQCVirtualDevice)
VirtualDevice(name='BasicMockDevice', dimensions=2, rydberg_level=61, 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, optimal_layout_filling=None, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=None, max_runs=None, requires_layout=False, reusable_channels=True, channel_ids=('ryd_loc', 'ram_loc'), channel_objects=(Rydberg(addressing='Local', max_abs_detuning=None, max_amp=None, min_retarget_interval=0, fixed_retarget_t=0, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None), Raman(addressing='Local', max_abs_detuning=None, max_amp=None, min_retarget_interval=0, fixed_retarget_t=0, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None)), dmm_objects=(DMM(addressing='Global', max_abs_detuning=None, max_amp=0, 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, custom_phase_jump_time=None, eom_config=None, propagation_dir=None, bottom_detuning=None, total_bottom_detuning=None),), default_noise_model=None)
A built-in example of a virtual device: the MockDevice
Section titled “A built-in example of a virtual device: the MockDevice”Actually, there exists a virtual device having all the channels already implemented, with no constraints on the number of atoms, the distance between them. This virtual device is the MockDevice
.
MyMockDevice = replace(MockDevice, name="MyMockDevice")print(MyMockDevice)
VirtualDevice(name='MyMockDevice', dimensions=3, rydberg_level=70, min_atom_distance=0.0, max_atom_num=None, max_radial_distance=None, interaction_coeff_xy=3700.0, supports_slm_mask=True, max_layout_filling=0.5, optimal_layout_filling=None, min_layout_traps=1, max_layout_traps=None, max_sequence_duration=None, max_runs=None, requires_layout=False, reusable_channels=True, channel_ids=('rydberg_global', 'rydberg_local', 'raman_global', 'raman_local', 'mw_global'), channel_objects=(Rydberg(addressing='Global', max_abs_detuning=None, max_amp=None, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None), Rydberg(addressing='Local', max_abs_detuning=None, max_amp=None, min_retarget_interval=0, fixed_retarget_t=0, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None), Raman(addressing='Global', max_abs_detuning=None, max_amp=None, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None), Raman(addressing='Local', max_abs_detuning=None, max_amp=None, min_retarget_interval=0, fixed_retarget_t=0, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None), Microwave(addressing='Global', max_abs_detuning=None, max_amp=None, min_retarget_interval=None, fixed_retarget_t=None, max_targets=None, clock_period=1, min_duration=1, max_duration=None, min_avg_amp=0, mod_bandwidth=None, custom_phase_jump_time=None, eom_config=None, propagation_dir=None)), dmm_objects=(DMM(addressing='Global', max_abs_detuning=None, max_amp=0, 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, custom_phase_jump_time=None, eom_config=None, propagation_dir=None, bottom_detuning=None, total_bottom_detuning=None),), default_noise_model=None)