Pulser: An open-source package for the design of pulse sequences in programmable neutral-atom arrays

Programmable arrays of hundreds of Rydberg atoms have recently enabled the exploration of remarkable phenomena in many-body quantum physics. In addition, the development of high-fidelity quantum gates are making them promising architectures for the implementation of quantum circuits. We present here \textit{Pulser}, an open-source Python library for programming neutral-atom devices at the pulse level. The low-level nature of Pulser makes it a versatile framework for quantum control both in the digital and analog settings. The library also contains simulation routines for studying and exploring the outcome of pulse sequences for small systems.


Introduction
Individual neutral atoms trapped in optical tweezers [1][2][3][4][5][6][7][8][9][10] have emerged as a powerful platform for quantum information processing.In those systems, one uses the strong interaction between atoms excited to a Rydberg state to generate entanglement.This interaction can be exploited for various tasks, including the creation of fast and robust quantum gates [11][12][13][14] for digital quantum information processing, the generation of tunable spin models for the study of manybody quantum physics [15][16][17][18][19], or the deterministic creation of large highly entangled GHZ states with up to 20 atoms [19].
Quantum computing and quantum simulation schemes for neutral-atom Quantum Processing Units (QPUs) are extremely flexible, in part due to the fact that, unlike for most other platforms, the QPU (and therefore its qubit connectivity) is not hard-wired during the manufacturing process.In fact, in neutral-atom optical traps, the connectivity of the QPU can be reprogrammed at every single run.This opportunity opens up new avenues for exploration on these devices but also requires providing the user with a lower-level description of the physical setup.
We here introduce Pulser [20], an open-source software library for designing pulse sequences for neutral-atom QPUs.The main goal of this library is to serve as an interface between experienced users and neutral-atom quantum hardware.Using Pulser, users can control all the relevant physical parameters of a pulse-level quantum program.This program can subsequently be sent to QPUs via external tools and executed on the hardware after a device-specific compilation step.Providing users with a pulse-level access to QPUs will allow them to explore advanced pulseshaping techniques facilitating the design of new quantum gate protocols, the implementation of optimal control and error mitigation techniques, or the exploration of mixed digital-analog algorithms [21].Exposing the low-level details of the hardware will also enable algorithm developers to design software procedures while keeping the particularities of the hardware in mind.Besides providing an interface to a QPU, Pulser includes a built-in emulator that faithfully reproduces the hardware behavior.This is intended to make the design of experiments easier for both the theoretician and the experimentalist.
Pulser is an open-source Python library licensed under the Apache License 2.0 and intended for the community of quantum scientists and engineers working on neutral-atom devices.The development and use of open-source software has enabled the flexible and efficient simulation of quantum systems [22,23], the connection of quantum processors to the cloud [24,25] and their use to launch jobs running quantum hardware.These tasks appear as quantum circuits expressed in intermediate representation, or in the more recent framework of hybrid classical-quantum algorithms, which require a fast and tailored interoperability between quantum and classical computing units with classical optimization routines [26][27][28].More recently, specific tools and frameworks have also put more focus on the pulse-level description of quantum controls [29][30][31][32][33], and their optimization to mitigate the impact of noise on the coherence of the intended protocols [34] in the so-called era of noisy-intermediate scale quantum computing (NISQ) [35].However, no existing open-source tool has yet specialized its features to the physics of neutral-atom quantum processors, which, due to the peculiarities of their physical properties, provide largely untapped opportunities both for quantum simulation and quantum computing tasks.
In this paper, we start by briefly reviewing in Section 2 the main physical ingredients that determine the dynamics of Rydberg atom arrays.We then present in Section 3 a guided walk-through for designing pulse sequences with Pulser, followed by examples on how Pulser can be leveraged for some notable use-cases in Section 4. Finally, we conclude and comment on the future directions and extensions for this tool.

Description of the physical system
In neutral-atom devices, atoms are trapped by arrays of optical tweezers [36] in arbitrary, customizable patterns.In Pulser, we call this ensemble of atoms and their specific positions the Register.For each atom in a Register, the quantum information is encoded in specific electronic energy levels, which are reached through optical addressing techniques.In Pulser, the components responsible for driving these transitions are called Channels and they do so through the emission of Pulses.

Driving two-level transitions
We define a pulse as the modulation of a channel's output amplitude, detuning, and phase over a finite duration τ .For a channel targeting the transition between energy levels a and b, with resonance frequency ω ab = |E a − E b |/ , the output amplitude determines the Rabi frequency2 Ω(t), and the detuning δ(t) is defined relatively to ω ab and the frequency of the channel's output signal ω(t), as δ(t) = ω(t)−ω ab .Additionally, the phase ϕ of a pulse can be set to an arbitrary, constant value.
A pulse-driven transition between two energy levels can be mapped to a spin-1/2 system through the drive Hamiltonian: where σ = (σ x , σ y , σ z ) T is the Pauli vector and Ω(t) = (Ω(t) cos(ϕ), −Ω(t) sin(ϕ), −δ(t)) T the rotation vector.Since there can be multiple transitions being addressed overall, we explicitly define the Pauli matrices for a transition between states |a and |b (where E b > E a ) to be: In the Bloch sphere representation, for each instant t, this Hamiltonian describes a rotation around the axis Ω with angular velocity

Rydberg states
In neutral-atom devices, atoms are driven to Rydberg states as a way to make them interact over large distances.Depending on the electronic levels that are involved in the process, the atoms experience different types of interactions, translating into different Hamiltonians [6].
In the so-called "Ising" configuration, which is obtained when the spin states are one of the ground states |g and a Rydberg state |r [15,16,37,38] (the ground-rydberg basis in Pulser, see Fig. 2.), the interaction adds a term to the drive Hamiltonian describing the transition between those states: (5) where ni denotes the projector |r r| i on the i-th atom, R ij is the distance between atoms i and j, and C 6 is a constant depending on the specific Rydberg level |r .The effect of this interaction is expressed in the so-called Rydberg blockade, illustrated in Figure 3.When driving two atoms from |g to |r with a resonant pulse (δ = 0) of Rabi frequency Ω, the interaction prevents the simultaneous excitation of the two atoms in the state |r if Ω C 6 /R 6 .Instead, the system evolves between the |gg and the entangled state |ψ + = (|gr + |rg )/ √ 23 , with an effective Rabi frequency of √ 2Ω.Similarly, an atom's excitation from |g to |r is suppressed if there is another atom in the Rydberg state at a distance R R b , where is the Rydberg blockade radius.
< l a t e x i t s h a 1 _ b a s e 6 4 = "         By acting on all atoms with the same global pulse, addressing the |g ↔ |r transition with ϕ = 0, one obtains the Hamiltonian: 7) represents a quantum Ising Hamiltonian with transverse field Ω(t) and Ising couplings Other configurations exist, but the corresponding channels are currently not implemented in Pulser.In the so-called "XY" configuration, which is obtained when the spin states |↓ and |↑ are two Rydberg states that are dipole-coupled, such as |nS and |nP [18,[39][40][41], the dipolar interaction generates an exchange-like term of the form where C 3 is a coefficient which depends on the selected Rydberg states.In this configuration, the driving is induced by a microwave field instead of an optical laser field.
The continuous manipulation of a system's Hamiltonian is referred to as the analog approach to quantum computing.The very high level of control in this analog mode has several applications, the most direct one being the quantum simulation of interacting many-body systems.This includes observing the out-ofequilibrium dynamics of the system after a quench or a drive [16,42], or determining the ground-state of a specific Hamiltonian through adiabatic variation of its parameters [17,43,44].Additionally, one can use the blockade effect to reproduce a connectivity structure among the atoms, which can be exploited to solve combinatorial problems that can be mapped onto the Ising Hamiltonian [45][46][47].Those applications will be studied in more detail in Section 4.

Digital addressing and quantum gates
In opposition to the analog approach stands the digital approach, in which a system's state evolves through a series of discrete manipulations of its qubits' states, known as quantum gates.This is the underlying approach in quantum circuits and can be replicated on neutral-atom devices at the pulse-level.To achieve this, the qubit states are encoded in two hyperfine ground states of the system, named ground, |g ≡ |0 , and hyperfine, |h ≡ |1 .In Pulser, these states form the digital basis, which is addressed by Raman channels.
For these energy levels, the Rydberg blockade effect is not present, so the resulting dynamics from a pulse addressing the |h ↔ |g transition of an atom will be dictated by the driving Hamiltonian of eq. ( 1).For a pulse of duration τ , the time evolution of this system is dictated by the operator where T denotes the time-ordering operator.The unitary U describes a rotation around the timedependent axis Ω(t).For a resonant pulse (i.e. one with δ = 0) of phase ϕ, we get a rotation angle of around the fixed axis e(ϕ) = (cos ϕ, − sin ϕ, 0), (11) situated on the equator of the Bloch sphere.The corresponding unitary operator is which, as its decomposition shows, can be thought of as a rotation around the Bloch sphere's x-axis, conjugated by z-rotations (i.e.phase gates).By following this gate with another zrotation (which can be achieved virtually through a shift in the phase reference frame [48]), we can then construct any arbitrary single-qubit gate, which relies solely on resonant pulses and phase reference frame changes.
With the ability to perform arbitrary singlequbit gates, all that is missing in order to have a universal quantum gate set is an appropriate two-qubit gate.In neutral-atom devices, the native gate is the controlled-Z (CZ); its implementation leverages the Rydberg blockade effect to flip the phase of a two-qubit subsystem, conditionally on its initial state.To achieve this, the atoms, depending on their initial state, are sequentially brought to an auxiliary Rydberg state and back by a sequence of three consecutive laser pulses.The effect of this pulse sequence on the four computational states |00 , |01 , |10 and |11 is shown in Figure 4.The first π-pulse attempts to bring the control atom into the Rydberg state, which will condition whether the target will be able to go to |r and back with the second 2π-pulse, due to the Rydberg blockade.In particular, the |00 state does not experience two consecutive phase flips as it would if the atoms did not interact (see top right panel of Fig. 4, where the Rydberg energy level of the target atom experiences a shift in energy ∆E due to the control atom being in |r ).Finally, the third pulse brings the control back to its original state, in case it was excited.In the end, all states but |11 experience a phase flip (see bottom left panel of Fig. 4), and the process corresponds to an application of a CZ within a global phase of π (see table 1).Altogether, the space in which the atom arrays can evolve is here composed of three states: two non-interacting hyperfine states, {|g , |h } and an auxiliary Rydberg state |r which is only populated in the transient dynamics of the system during the application of multi-qubit gates.The Rydberg state thus plays both the role of an excited state in the ground-rydberg basis in the analog approach, and of an auxiliary state for realizing multi-qubit gates in the digital basis.
Since the most general sequence, with channels addressing both transitions, involves three energy levels, the size of the Hilbert space is 3 N , where N is the number of atoms in the array.Typically, a personal computer can efficiently simulate the evolution of systems of size below N ∼ 20.

Measurement
In neutral-atom devices, the measurement process encompasses all the atoms in the register and necessarily terminates the computation.The process is based on the fluorescence imaging of the atom array, where "bright" and "dark" sites are linked to the measured states [49].Due to there being multiple addressable transitions, the final state of each atom can be in more than two levels and, therefore, the measurement's outcome will be basis-dependent.In Pulser, the convention is to associate the state that is exclusive to a given basis to 1 and all other outcomes to 0, as summarized in table 2.

Code Architecture
The main components of Pulser are: (i) The Device, which consists of a series of specifications that characterize the hardware, including the chosen Rydberg level, the ranges of the amplitudes and frequencies of the lasers, the minimal and maximal distance between the atoms, and the different channels that can be declared (see (iii) below).
(ii) The Register stores the information about the coordinates of the atoms and their re- (iv ) Waveforms are the basic building blocks of a pulse.They can have custom or predetermined shapes, like a ramp waveform or a Blackman waveform, all of them indicating the specific profile of the waveform and its duration.
(v ) Pulses consist of waveforms for the amplitude and the detuning.They can be further shifted by a phase.Once a Pulse is constructed it has to be added to the sequence indicating which atom(s) are targeted and what channel will implement it.
(vi) The Sequence contains the schedule of the pulses in each channel.It is also linked with a Register and the Device in which it is to be executed.This is the information that can be sent to a real neutral-atom QPU or simulated on a classical computer.
(vii) Simulation is included to emulate results for the application of sequences on small instances.In Pulser, we have made use of the QuTiP libraries [22,23] for the simulation of quantum systems.Each simulation run returns a specialized object that holds the results and features methods for postprocessing them.

Pulse Sequence Creation: A guided walkthrough
We will show, step-by-step, how a basic pulse sequence is created with Pulser by going through the paradigmatic protocol for creating the Bell state Φ + = 1 √ 2 (|00 + |11 ).Starting from the archetypal circuit in Figure 6(a), we need to adapt it for execution on neutralatom devices.The major and necessary change is the decomposition of the CNOT gate, which is not native in neutral-atom devices, to an equivalent construction based on the CZ gate.Additionally, we replace the Hadamard with an equivalent gate (when starting from |0 ) that can be executed with a resonant pulse, which reduces the number of free parameters in the pulse, making it less error-prone.These changes result in the equivalent circuit of Figure 6(b).
From this quantum circuit, we can create the corresponding pulse sequence in Pulser.For this effect, the following modules will be needed:

Creating the Register
The Register defines the positions of the atoms and their respective names.There are multiple ways of defining a Register, the most customizable one being to create a dictionary that associates a name (the key) to a coordinate in micrometers (the value).In this case, we only need two qubits, so we will create a Register with two atoms, 4 µm apart, which we will name c and t .
# Coordinates in micrometers qubits = { c : (-2, 0), t : (2, 0)} reg = Register(qubits) Note that, although we can arbitrarily specify the position of each qubit, the Device with which we will associate it will impose some restrictions, limiting in particular the minimal distance between any two qubits and the maximal distance of each qubit from the center of the array.

Initializing the Sequence
To create a Sequence, one has to provide it with the Register instance and the Device in which the sequence will be executed.Each Device object is associated with a physical device and holds its particular constraints.When linked to a Sequence, it dictates whether the chosen register is valid and, as the sequence is created, validates all instructions.We import the device (in this case, Chadoq2, which is Pasqal's research and development prototype) from pulser.devices and initialize our sequence with the freshly created register: from pulser.devicesimport Chadoq2

Channel declaration
Each device has a set of available channels, which can be consulted through seq.available_channels.
Since we need local addressing on both the ground-rydberg basis (for the CZ gate) and the digital basis (for the single-qubit gates), we will declare the rydberg_local and raman_local channels, which we will name rydberg and digital , respectively.On real devices, each channel can only be declared once and will no longer appear in the list of available channels after declaration, appearing instead in seq.declared_channels.

Making the pulses
The different channels will be populated by pulses, which are specific objects that need to be created.A pulse is made up of an amplitude (i.e.Rabi frequency) waveform, a detuning waveform and a fixed phase, although special convenience methods exist when one or both waveforms are constant.In our example, all pulses will be resonant, so we will use Pulse.ConstantDetuning() to conveniently set δ = 0 without defining its waveform.
For the amplitude waveform, eq. ( 10) tells us that what defines the angle of rotation is simply the integral of the waveform.This ideal scenario does not distinguish between a rectangular waveform or something more complex, as long as its integral is the same.In practice, a properlyshaped waveform can mitigate unwanted modifications to the modulated signal, stemming from spectral leakage or noise sensitivity.Here, we will use the Blackman waveform, which is a tapering function designed to have close to minimum spectral leakage.
Starting with the single-qubit gates, all of those involved have θ = π/2, so we declare a Blackman waveform with an area of π/2 and duration of 200 ns, making up a relatively short pulse without exceeding the amplitude range allowed by the channel where it will be executed.The rotation axis is defined from eq. ( 11), from which we gather that a rotation around the yaxis corresponds to a phase ϕ = −π/2.Inversely, since R † y (π/2) = R −y (π/2), we will have ϕ = π/2 defining a rotation around −y.The corresponding pulse declarations are: Moving on to the CZ gate, which follows the protocol of Figure 4, we will need a π-pulse and a 2π-pulse, which we can shape with a Blackman waveform as well.However, because we are now dealing with Rydberg interactions, we have to make sure that the Rydberg blockade radius resulting from the chosen waveform is well above the spacing between the atoms.This concern does not extend to all the pulses assigned to the Rydberg channel, because a Rydberg blockade is only meaningful if multiple atoms are being excited to the Rydberg state simultaneously or if an atom is being excited after its neighbors.Thus, in this case, only the 2π-pulse will determine a relevant Rydberg blockade radius, which means the π-pulses surrounding it can be kept short: To figure out what is the Rabi frequency upper bound that corresponds to a certain Rydberg blockade radius, as dictated by eq. ( 6), we use the rabi_from_blockade() method of our chosen device.We set a conservative Rydberg blockade radius of 8µm, double the distance between the atoms.The corresponding maximum Rabi frequency value is then With an upper bound on the amplitude, we can create the appropriate Blackman waveform and corresponding pulse using the following formulation (which leverages the fact that there is a simple relationship between the duration, area and maximum value of a Blackman waveform): All the pulse objects necessary to program the circuit of Figure 6(b) have been created.As a remark, note that every Pulse and Waveform can be plotted by calling its draw() method, which can be useful to visualize the shape of the waveforms, as well as inspect the range of values they span.As an example, Figure 7 displays the plot of two_pi_pulse, showing both the amplitude and detuning waveforms in the same picture.Both the amplitude and detuning waveforms are displayed.

Composing the Sequence
As previously mentioned, the workings of neutralatom devices ultimately influence the sequences designed in Pulser.In many aspects -like the way single-qubit gates are realized as pulses -neutral-atom devices are very similar to other popular implementations.However, when compared to superconducting qubit architectures for instance, there are some marked differences, the most striking being in the connection between channels and qubits.
In superconducting qubit devices, each qubit has multiple dedicated channels, each serving a specific function, like that of manipulating or measuring the state of the qubit.This means that if one is to apply a pulse on a given qubit, that pulse will be allocated to the channel exclusively serving that qubit.
On the other hand, a channel in a neutral-atom QPU can serve all the qubits in the register, be it simultaneously or sequentially.In practice, this means that a channel needs to know on which qubit (or qubits) to apply the pulses to, and while there are some channels -specifically, those of the Global type -whose targets are fixed to be the entire register, the channels of type Local have the ability to change their target throughout the sequence.When the state of a single-qubit is changed, a Local channel targets it before applying the pulse, after which it can move on to target a different qubit onto which the next pulse will be applied.In this way, a Local channel can individually manipulate the state of all the qubits in a register, though it will do it sequentially rather than in parallel.
Thus, every channel needs to start with a target.For Global channels, all the atoms are the target by definition, but for Local channels, their target has to be explicitly defined.This initial target can be set at channel declaration (see how rydberg was set to target the c atom), or it can be done by using the standard target method of seq -the Sequence instance previously created.

seq.target( c , digital )
Now both channels have an initial target, so we can compose the sequence by allocating the Pulses to the declared Channels.
We start with the single-qubit gates, R y (π/2) and R † y (π/2).Recall that these transitions are addressed by the Raman-type channel, which we called digital .Thus, the first two gates of circuit 6 are added to the same channel as follows: seq.add(ry_pulse, digital ) seq.target( t , digital ) seq.add(ry_dag_pulse, digital ) Notice how the target is changed to t in between additions, so that the R † y (π/2) gate acts on the correct qubit.
Next, we implement the CZ gate by replicating the protocol of Figure 4.This will involve the other declared channel, so we must clarify how pulses in different channels are aligned in time.By default, when adding a pulse to a channel (which is targeting one or more qubits), it will be added as soon as all targeted qubits are free.This means that, if existing pulses on other channels are acting on one of the targeted qubits, the channel will be idle until they are done.On the other hand, if there is no overlap between the different channels' targets, the pulses will be played in parallel; this is called the min-delay protocol.The other addition protocols are the wait-for-all , in which the pulse will only play after all previously added pulses are finished, and the no-delay , where a delay is never added.
There is an additional command, called align(), which introduces delays that align a subset of channels with the one that finished the latest, such that the next pulse added to any of them will start right after the latest channel has finished.When all the declared channels are aligned, the outcome is identical to that of using the wait-for-all protocol; otherwise, when only some of the channels are aligned, it corresponds to a "wait-for-some" protocol.
As illustrated in Fig. 4, the CZ implementation starts with a π-pulse on channel rydberg , which is targeted to the c qubit.The channel starts empty, but the pulse will not be added at t = 0 by default because it would overlap with the first pulse of channel digital , which is also targeting c .Instead, it would wait for this first pulse to end and then start playing in parallel with the second pulse in the digital channel.Although this would be a valid implementation, we will instead use the align command to make the pulse start only after the digital channel is done with both pulses (the wait-for-all would work too because we only declared two channels, but this way can be generalized to the case were other channels are declared).This will avoid deadtimes in the CZ implementation, thus keeping the atoms in the Rydberg state no longer than necessary (which is desirable, since the atoms are more sensitive to noise when in the Rydberg state).
Thus, the CZ is implemented through Finally, there is still a single-qubit gate on the t qubit that must be applied after the CZ is done (recall that channel digital was left targeting t ), seq.align( digital , rydberg ) seq.add(ry_pulse, digital )

Measurement
At last, the measurement signals the end of a sequence, so after it no more changes are possible.We can measure a sequence by calling: When measuring, one has to select the desired measurement basis 4 .The available options depend on the device and can be consulted by calling the chosen device's supported_bases attribute.

Visualization
Throughout its creation process, the sequence can be visualized through the Sequence.draw()method.As an example, the final sequence is shown in Figure 8.Note that the phase of each pulse is not represented, only the amplitude and detuning modulations of each channel's outputthe latter being always zero in this example.To inspect the phase of each pulse, one can print out the sequence instead, through print(seq) This will list all the contents of each channel, alongside its start and finish times.

Simulation
The primary goal of Pulser is to serve as a frontend framework for designing pulse sequences for neutral-atom quantum processors.However, it is also possible to emulate the output of a sequence locally on a classical device through the Simulation class.Pulser's emulator relies on the open-source package QuTiP.Incorporating an emulator in Pulser is valuable for several reasons.First, it enables users to carefully design their pulse sequences and understand their effects before sending the instructions to a real device.It also enables them to gain intuition with simple setups, and explore new possible applications on limited-size systems.Coming back to our example, we use the emulator on our sequence by calling: 51 from pulser.simulationimport Simulation 52 sim = Simulation(seq) 53 res = sim.run()Every time the run() method is called, a SimulationResults object instance is returned, which holds the results of the simulation.
The simulation performed is a time evolution of the system at specific times, such that res holds the state of the system at each instant.All the states can be accessed through the states attribute, the final entry being the state of the system at the end of the sequence (before measurement).
In this case, since the three energy levels of the two atoms were involved, the final state will be a nine-entry vector.However, the population of the Rydberg levels should be negligible, so it is possible to reduce the final state to the digital basis of interest.We do so by calling 54 res.get_final_state(reduce_to_basis= digital ) which returns a qutip.Qobj instance holding the final state in the digital basis.For this example, the outcome is , which is very close to what we expect for Φ + .Another way to probe the results is to emulate a real experiment, in which case the only infor- The current target of each channel is displayed in the orange boxes and is part of the original output, but the gates corresponding to each part of the circuit were annotated on top of it.The blue boxes on the right specify the basis in which the system is measured at the end of the sequence.mation about the final state of the system is obtained in the measurement.For a given number N_samples of repetitions of the experiment, we call 55 res.sample_final_state(N_samples=1e4) Due to finite sampling errors, the outcome will vary slightly for each call.An example of an outcome is { 00 : 5005, 11 : 4995}.

Pulser in action : exploration of usecases with the emulator
In this section, we reproduce some results obtained experimentally using Pulser's built-in emulator.These examples, among several others, can be accessed online at Pulser's documentation site 5 , which includes the code for the optimization of parameters and the generation of the figures.

Preparing an antiferromagnetic state and observing the produced correlations
First we illustrate how to build a sequence for adiabatically preparing an antiferromagnetic state from the Ising-like model of eq.( 5), as well as studying its correlations.These types of states have been studied in neutral-atom setups up to hundreds of qubits, showing remarkable precision and allowing measurements that are beyond the best available classical simulation algorithms [16,17,43,44].
The atoms will be placed in a square array of interatomic distance R. We will shine a laser globally with a pulse sequence representing a path in the phase diagram of the quantum Ising model, that starts in the paramagnetic phase and ends in the antiferromagnetic dome, as shown in Fig. 9(a).We shall evaluate the quality of the resulting state by calculating the spin-spin correlation function, defined as: The function g (2) measures the correlation between local operators ni , nj at different positions, averaged over all pairs of atoms i, j separated by a vector (kR, lR) (N k,l is the total number of such pairs).The pulses will be constructed by indicating the values for the maximum Rabi frequency, and the initial and final detuning (as reported in [50]).Since we want to use the blockade effect for nearest-neighbors only, we tune Ω max to be of the same order as the van der Waals interaction magnitude for nearby atoms, Ω max ∼ U .This will fix an interatomic distance R interatomic , which we use to define our register: The sequence is readily plotted with the draw() method, as illustrated in Figure 9(b).

Simulation: Spin-Spin Correlation Function
We run a simulation of the sequence with the run() method of the Simulation class.For simple pulse sequences like the one we are using here, we can use a reduced sampling rate for faster emulation.A progress estimate can also be included if desired, with the parameter progress_bar=True.
Once the final state is obtained, we may sample from it using the sample_final_state() method.Since there was no measurement basis ( ground-rydberg or digital ) specified during the composition of the sequence, we include it as an argument with meas_basis: From the output of the simulation, we can plot the histogram of the sampled results, shown in Figure 10.Notice the peak corresponding to the antiferromagnetic state.From results, one can access the state of the system throughout the simulation (as a list of qutip.Qobjs) by calling results.states.This can be useful for post-processing the simulation results and computing observables.Alternatively, one can also call results.expect() to get the exact expectation value of a list of observables.For example, results.expect([qutip.basis(9,0).proj()]) will return the probability of measuring the all-excited state |r ⊗9 for every state in results.
We show in Figure 11(a) the output of the simulation for the correlation function g (2) , eq. ( 14).Note that the correlation function is expected to decay exponentially (modulo finite-size effects), which is best observed at larger system sizes [43].
Changing the endpoint δ f of the pulse's path results in different qualities of the final state.In order to evaluate how well it represents an antiferromagnetic state, we will explore the Ω = 0 line on the phase diagram, Fig. 9(a).Since the value of correlation function g (2) (k, l) (eq.( 14)) can be positive or negative, we compensate with alternating signs to construct a single score for the state [50]: which should be largest when the state is closest to an antiferromagnetic product state.By sweeping over different values of detuning δ f , we

Variational algorithms with Pulser: solving a graph problem with neutral atoms
The implementation of variational algorithms, such as the Quantum Approximation Optimization Algorithm [51] (QAOA), is facilitated by the use of a parametrized sequence in Pulser.We illustrate this aspect here, by solving the Maximum Independent Set (MIS) problem on Unit Disk graphs, which can be naturally studied on neutral-atom devices [45][46][47].

From a graph to an atomic register
An independent set of a graph is a subset of vertices where any two elements of this subset are not connected by an edge.The MIS corresponds to the largest of such subsets.The so-called Unit Disk (UD) version of this problem corresponds to the instances where the graph under consideration lives in 2D and displays an edge between two nodes if they are within a unit length of each other.
Interestingly, ensembles of interacting Rydberg atoms in 2D can be naturally represented by Unit Disk graph structures: the atoms are the nodes of the graphs and an edge in the graph corresponds to two atoms being within the blockade radius of each other.In this example, we will take Ω fixed to a frequency of 1 rad/µs, hence the blockade radius can be obtained by using Chadoq2.rydberg_blockade_radius(1.).The following code block instantiates the atomic register, and displays the graph induced by their interactions with the draw_graph=True and draw_half_radius=True arguments passed to the reg.draw() method, as illustrated in Figure 12.The graph G has two maximal independent sets: (1, 3, 4) and (2,3,4), respectively 01011 and 00111 in binary.One could try to prepare those states using an adiabatic approach such as the one illustrated in section 4.1.Another approach is to use QAOA, as we illustrate below.

Building the parametrized sequence
QAOA exploits both a quantum and a classical processor that exchange information within a feedback loop to solve an optimization problem.The role of the neutral-atom processor is to prepare and measure an N -atom parametrized wavefunction.The outcome of the measurement is then used by the classical processor in a standard classical optimization procedure, that updates the parameters for the next iteration.
More specifically, the preparation of the parametrized wavefunction is achieved through the successive application of two noncommutative Hamiltonians, with all atoms initially starting in the ground state |00 . . .0 of the ground-rydberg basis.The first one is realized by taking Ω = 1 rad/µs, and δ = 0 rad/µs in Eq. (7).The second Hamiltonian is realized with Ω = δ = 1 rad/µs.These two Hamiltonians are applied successively, for durations t j and s j , respectively.The dimension of t and s, i.e. the number of layers applied to the system, is referred to as the depth of the algorithm.The outcome of the measurement is then used as the objective function in a standard classical optimization procedure, that updates the parameters for the next iteration.
When implementing a variational procedure, multiple sequences are created that differ only by the durations t j and s j of the pulses.This is conveniently handled in Pulser by turning a regular sequence into a parametrized sequence.A Sequence is said to be parametrized once a variable is declared and used in a sequencebuilding call, from which point the sequence building process can continue as usual but the sequence is no longer built on the fly.Instead, all calls to a parametrized sequence are stored as a blueprint for generating a new Sequence, which may depend on the value of the declared variables.Consequently, it is not possible to progressively monitor the creation process of a sequence that is parametrized (e.g. by drawing the state of a sequence as new pulses are added).
The building of the sequence itself only happens when Sequence.build() is called, at which point specific values for all the declared variables have to be specified as arguments.
The Variable objects are obtained by calling Sequence.declare_variable()and can be used throughout the Sequence creation process (i) as parameters when creating new Waveforms and Pulses, or (ii) as arguments for standard sequence creation methods like add, target, align and delay.Moreover, they support basic arithmetic operations and, when they are of size> 1, iteration and item accessing.
The notion of parametrized sequence can become very handy with real world constraints such as those we find in cloud-based platforms.First, the bandwidth allocation of a program, variational or not, is greatly reduced thanks to this factorization.A user only needs to send the parametrized sequence that describes his program once, and then each new iteration only requires the associated set of parameters.Thanks to the high flexibility of Pulser, users can have a very fine-grained control over the waveforms that define their pulses.This results in needing larger objects to define these pulses, which makes such a factorization even more useful.
In addition, one area of improvement for cold atom platforms is the large calibration times for atom register configuration changes.This means that running randomly independent sequences on the same QPU can be very inefficient.The sequences of a given user's program on the other hand share some common parameters, including the register configuration.On the QPU side, we can treat the parametrized sequences as the basic block of the QPU scheduling to greatly reduce the latencies due to the calibration processes, make sure the different user programs are run efficiently and that all the sequences in a given program are run on the same QPU.
The example below shows how Sequence can be used to create a parametrized QAOA sequence with two layers, with the variable duration of each layer stored in the t_list and s_list arrays.Notice that no value is given to the contents of t_list and s_list.The sequence seq above will only be built once the user provides specific values for t_list and s_list while calling the Sequence.build()method.It thus enables to build a variety of sequences that share the same structure: # Build sequences with specific values my_seq_1 = seq.build(t_list=[2,4], s_list= [3,6]) my_seq_2 = seq.build(t_list=[1,3], s_list= [2,5])

Classical optimization and QAOA results
The parametrized sequence above can then be used in conjunction with a classical optimizer in order to determine a set of good values for t_list and s_list.When running the full QAOA procedure in closed loop, the optimizer is responsible for iteratively selecting the next set of parameters to be tested.The parametrized sequence can then be updated in Pulser and the new program sent externally to the quantum hardware.
The procedure can also be emulated locally: to try out the algorithm, we applied the nongradient method Nelder-Mead for a few dozen function evaluations, initializing the parameters in a convenient point (the implementation can be found at Pulser's online documentation).This is already sufficient in order to find some acceptable parameters t and s.The performance of QAOA can be tested by sampling from the final state |ψ(t f ) which returns both MISs of the graph with high probability.We show in Figure 13 the histogram of the recorded bitstrings.

Conclusion
With recent advances in the field, neutral-atom processors now provide unique opportunities for the exploration of uncharted territories in manybody quantum physics with hundreds of interacting quantum units [42][43][44].By using distinct electronic transitions for encoding the quantum information, one can implement various Hamiltonians depending on the task at hand.Beyond analog computing, recent developments in qubit addressing have opened the door to high-fidelity quantum gates [13,14].In addition to the flexibility in terms of information encoding and processing, the geometry of the quantum register itself is also highly programmable [5,52].This holds great promises for the implementation of graph-related algorithms [46,47,[53][54][55], the exploration of lattice models in condensed-matter physics [18,43,44], or the reduction of the gatecount for quantum circuits [7].
In this paper, we introduced Pulser, an opensource Python library allowing users to pilot such powerful devices at the pulse level.This tool will enable the exploration of new avenues in physics and quantum information science requiring an advanced control of the system.After their creation in Pulser, pulse sequences can be translated and read by an arbitrary waveform generator for implementation on a quantum processor.The architecture of the software makes it possible to use as an interface for any neutral-atom QPU as the specifics of the back-end can be encapsulated by creating new Device objects.Pulser currently enables the control of laser pulses during the quantum information processing phase, but it could be extended in the future to include other controls either in the processing phase, during the assembly of the register or the measurement phase.Being a low-level tool, Pulser could be interfaced with higher-level application-oriented libraries and frameworks for digital quantum information processing, such as Cirq [56], Qiskit [57], Atos myQLM, Pennylane [58] or tket [59], which abstract away many hardware features.
The primary purpose of Pulser's built-in emulator is to reproduce faithfully what the output of a real experiment would look like, in order to facilitate the design of hardware runs.In that spirit, some developments are currently underway for the inclusion of realistic error models [60].Some work could also be done to extend the simulations capabilities in terms of the number of qubits that can be efficiently simulated, including the development of tensor-network based methods and GPU acceleration.

Figure 1 :
Figure 1: Representation of the drive Hamiltonian's dynamics as a rotation in the Bloch sphere.

Figure 2 :
Figure 2: The excitation between a ground and Rydberg state is taken as two-level transition with Rabi frequency Ω and detuning δ.In Pulser, it is called the ground-rydberg basis and is addressed by Rydberg channels.
n e 1 2 I B K y l D n l d c h O I s n L 5 P G e c m 5 K N k 1 p 1 i u k B l y 5 J i c k D P i k E t S J j e k S u q E k Z Q 8 k R f y a j w a z 8 a b M Z 6 1 r h j z m Q L 5 A + P 9 B 0 n w m O I = < / l a t e x i t > R Blockade < l a t e x i t s h a 1 _ b a s e 6 4 = " o I 9 J F H E b 9 4 S I W n A r 9 U w J B 0 f e Z y 6 F C O l p W 7 2 1 H Y F w r E 1 j m 1 5 I x Q s j a F d p V 5 h 5 A l b I O 4 x A k / g S H i z R + I d d 7 N 5 s 2 h O A B e J N S P 5 S v n + b p j 7 3 q 9 1 s x 9 2 L 8 C R T 7 j C D E n Z t s x Q d W I k F M W M j D N 2 J E m I 8 A B 5 p K 0 p R z 6 R n X h y 3 B g e a a U H 3 U D o 4 g p O 1 N 8 T M f K l H P q O 7 v S R 6 s t 5 L x H / 8 9 q R c s 8 7 M e V h p A j H 0 4 /

2 ⇣
g D 4 z P H z e h p G w = < / l a t e x i t > 1 p |gri + |rgi ⌘ Energy < l a t e x i t s h a 1 _ b a s e 6 4 = " p 1 F 4 j x n a X 4 0 M Q 9 8 A X J W e m T 9 7 S i s R ij < l a t e x i t s h a 1 _ b a s e 6 4 = " 1 y I U + + C a e N 9 s u I o 1 a Z U L E p v b f w s = " > A A A B 8 X i c d Z D L S g M x F I Y z 9 V b r r e r S T W g R B K F k x t r W X d G N y w r 2 g p 1 S M m n a h m Y y Q 5 I R h r F v 0 Y 0 L R d z 6 N u 7 6 N m Z a B R X 9 I f D z / e e Q c 4 4 X c q Y 0 Q n M r s 7 K 6 t r 6 R 3 c x t b e / s 7 u X 3 D 1 o q b n 0 b d 3 0 b p 5 e F t v 4 w 8 P H / 5 z D n n C D l T G n b n l h r 6 x u b W 9 ul n f L u 3 v 7 B Y e X o u K W S T F J o 0 o Q n s h M Q B Z w J a G q m O X R S C S Q O O L S D 4 d 0 0 b z + D V C w R j z p P w Y 9 J J F j I K N H G e n q J I k 8 S E X H o V W p 2 3 Z 4 J r 4 K z g J p b 9 S 7 G E z d v 9 C r f X j + h W Q x C U 0 6 U 6 j p 2 q v 2 C S M 0 o h 1 H Z y x S k h A 5 J B F 2 D g s S g / G I 2 8 Q i f Ga e P w 0 S a J z S e u b 8 7 C h I r l c e B q Y y J H q j l b G r + l 3 U z H d 7 4 B R N p p k H j 9 I b e L W W 9 W h / W 5 7 x 0 z V r 0 n K A / s r 5 + A O s k l A 0 = < / l a t e x i t > |ggi < l a t e x i t s h a 1 _ b a s e 6 4 = " Z c y R V y t K a w 2 7 + t Y e G 5 j 9 5 b d 3 d v f 2 z Y P D h o o S y a D O I h H J l k 8 V C B 5 C H T k K a M U S a O A L a P r D 6 4 n f v A e p e B T e Y R q D G 9 B + y H u c U d S S Z x Z u v a y D 8 I B Z R U R s S L s w G n l m 0 S 7 Z U 1 j L x J m T Y v m o 9 s 3 H l n e 1 2 I B K y l D n l d c h O I s n L 5 P G e c m 5 K N k 1 p 1 i u k B l y 5 J i c k D P i k E t S J j e k S u q E k Z Q 8 k R f y a j w a z 8 a b M Z 6 1 r h j z m Q L 5 A + P 9 B 0 n w m O I = < / l a t e x i t > R Blockade < l a t e x i t s h a _ b a s e = " o I

2 ⇣Figure 3 :
Figure 3: Two nearby atoms interact via a van der Waals potential which shifts the energy level for the doubly excited state |rr .If the laser excites simultaneously both atoms, the lower-energy entangled state (|gr + |rg )/ √ 2 is produced instead.

Figure 4 :
Figure 4: CZ implementation protocol, where three consecutive pulses address the |g ↔ |r transition.Full (dashed) red lines illustrate if a given pulse is effective (not effective).

Figure 5 :
Figure5: Relationship between the main Pulser classes.The central object is the Sequence, which is linked to a Device.The Device holds the available Channels -which are selected and declared in the Sequence -and information of the hardware constraints.These constraints are enforced upon the Register, where the neutral-atom array is defined, and upon the Pulses.Each Pulse, defined by its amplitude and detuning Waveforms and a fixed phase, populates the declared channels alongside other commands like target -which points local addressing channels to specific qubits -and delay -which idles the channel.The resulting Sequence can then be sent for execution on the neutral-atom QPU or emulated through Pulser's Simulation class.

1 import
numpy as np Accepted in Quantum 2022-01-11, click title to verify.Published under CC-BY 4.0.

Figure 6 :
Figure 6: (a) Typical quantum circuit for generating the Bell state |Φ + .(b) Equivalent circuit to that of Figure 6(a), adapted for execution on a neutral-atom device.

Figure 7 :
Figure 7: The outcome of calling two_pi_pulse.draw().Both the amplitude and detuning waveforms are displayed.

Figure 8 :
Figure 8: The final Bell state creation sequence, displayed by calling seq.draw().The current target of each channel is displayed in the orange boxes and is part of the original output, but the gates corresponding to each part of the circuit were annotated on top of it.The blue boxes on the right specify the basis in which the system is measured at the end of the sequence.

Figure 9 :
Figure 9: (a) Schematic phase diagram of a two-dimensional quantum Ising system, with respect to the ratio of applied Rabi frequency Ω/U and detuning δ/U .The blue region indicates the antiferromagnetic (AFM) phase, and outside of this region a paramagnetic (PM) phase is found.(b) The pulse sequence for the adiabatic preparation of the antiferromagnetic state in the Ising model, displayed by calling seq.draw().

Figure 10 :
Figure 10: Most frequent results from the sampling of the final state.

Figure 12 :
Figure 12: The register for the MIS graph problem.The shaded circles show the blockade half-radius, such that the intersecting regions indicate existing links.

Figure 13 :
Figure 13: Histogram of most frequent bitstrings after the optimization loop.The MIS graphs (in red) are the ones that are observed most frequently.

Table 1 :
Effect of the CZ pulse sequence in the computational basis.

Table 2 :
Corresponding measurement outcome of each state, depending on the measurement basis.