Pasqal QPU¶
Pasqal is the 100+ qubit analog quantum simulator hosted in the JUNIQ facility.
Getting Access¶
Access to the Pasqal QPU is available via the Qaptiva device which accepts jobs written using myqlm framework. The pulses used in the job are built using the pulser library. If you haven't set up the access to Qaptiva yet, please follow the instructions in the Qaptiva access documentation to get started. Use the project name relevant to Pasqal when signing up on the JuDoor portal.
Submitting first job¶
A sample job to submit to Pasqal is shown below.
In [1]:
Copied!
from qlmaas.qpus import PasqalQPU1 # Note that we are importing Pasqal QPU from qlmaas
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from pulser import Pulse, Sequence
from pulser.devices import Device
from pulser.waveforms import RampWaveform
from pulser.register.special_layouts import (
SquareLatticeLayout,
TriangularLatticeLayout,
)
from qat.qpus import RemoteQPU
from pulser_myqlm import FresnelQPU, IsingAQPU
from qlmaas.qpus import PasqalQPU1 # Note that we are importing Pasqal QPU from qlmaas
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from pulser import Pulse, Sequence
from pulser.devices import Device
from pulser.waveforms import RampWaveform
from pulser.register.special_layouts import (
SquareLatticeLayout,
TriangularLatticeLayout,
)
from qat.qpus import RemoteQPU
from pulser_myqlm import FresnelQPU, IsingAQPU
In [2]:
Copied!
QPU = PasqalQPU1()
QPU = PasqalQPU1()
In [3]:
Copied!
FRESNEL_DEVICE = Device.from_abstract_repr(QPU.get_specs().description)
FRESNEL_DEVICE = Device.from_abstract_repr(QPU.get_specs().description)
In [4]:
Copied!
# Simulation parameters
NBSHOTS = 0 # must be 0 for AnalogQPU
MODULATION = False # Whether or not to use Modulated Sequence in the simulation
# Simulation parameters
NBSHOTS = 0 # must be 0 for AnalogQPU
MODULATION = False # Whether or not to use Modulated Sequence in the simulation
In [14]:
Copied!
# Simulation
# Creating the layout
reg_layout = square_layout = SquareLatticeLayout(5, 2, spacing=5)
reg_layout.draw()
# Simulation
# Creating the layout
reg_layout = square_layout = SquareLatticeLayout(5, 2, spacing=5)
reg_layout.draw()
In [15]:
Copied!
# Pulse parameters
Omega_max = 2 * FRESNEL_DEVICE.rabi_from_blockade(10.0) # Spacing between atoms
U = Omega_max / 2.0
delta_0 = -6 * U
delta_f = 2 * U
t_rise = 250
t_fall = 500
t_sweep = (delta_f - delta_0) / (2 * np.pi) * 1000
# Pulse parameters
Omega_max = 2 * FRESNEL_DEVICE.rabi_from_blockade(10.0) # Spacing between atoms
U = Omega_max / 2.0
delta_0 = -6 * U
delta_f = 2 * U
t_rise = 250
t_fall = 500
t_sweep = (delta_f - delta_0) / (2 * np.pi) * 1000
In [16]:
Copied!
R_interatomic = FRESNEL_DEVICE.rydberg_blockade_radius(U)
reg = reg_layout.define_register(0,1,2)
N_atoms = len(reg.qubits)
print("Contains ", N_atoms, "atoms")
print(f"Interatomic Radius is: {R_interatomic}µm.")
rise = Pulse.ConstantDetuning(RampWaveform(t_rise, 0.0, Omega_max), delta_0, 0.0)
sweep = Pulse.ConstantAmplitude(Omega_max, RampWaveform(t_sweep, delta_0, delta_f), 0.0)
fall = Pulse.ConstantDetuning(RampWaveform(t_fall, Omega_max, 0.0), delta_f, 0.0)
R_interatomic = FRESNEL_DEVICE.rydberg_blockade_radius(U)
reg = reg_layout.define_register(0,1,2)
N_atoms = len(reg.qubits)
print("Contains ", N_atoms, "atoms")
print(f"Interatomic Radius is: {R_interatomic}µm.")
rise = Pulse.ConstantDetuning(RampWaveform(t_rise, 0.0, Omega_max), delta_0, 0.0)
sweep = Pulse.ConstantAmplitude(Omega_max, RampWaveform(t_sweep, delta_0, delta_f), 0.0)
fall = Pulse.ConstantDetuning(RampWaveform(t_fall, Omega_max, 0.0), delta_f, 0.0)
Contains 3 atoms Interatomic Radius is: 9.999999999999998µm.
UserWarning: A waveform duration of 1102.2727838515502 ns is below the supported precision of 1 ns. It was rounded down to 1102 ns.
In [18]:
Copied!
# Creating the Sequence
seq = Sequence(reg, FRESNEL_DEVICE)
seq.declare_channel("ising", "rydberg_global")
seq.add(rise, "ising")
seq.add(sweep, "ising")
seq.add(fall, "ising")
# Creating the Sequence
seq = Sequence(reg, FRESNEL_DEVICE)
seq.declare_channel("ising", "rydberg_global")
seq.add(rise, "ising")
seq.add(sweep, "ising")
seq.add(fall, "ising")
In [20]:
Copied!
# Simulate the Sequence on the QPU
job = IsingAQPU.convert_sequence_to_job(seq, nbshots=NBSHOTS, modulation=MODULATION)
results = QPU.submit(job)
# Print the most interesting samples
for sample in results:
if sample.probability > 0.01:
print(sample.state, sample.probability)
# Simulate the Sequence on the QPU
job = IsingAQPU.convert_sequence_to_job(seq, nbshots=NBSHOTS, modulation=MODULATION)
results = QPU.submit(job)
# Print the most interesting samples
for sample in results:
if sample.probability > 0.01:
print(sample.state, sample.probability)
Submitted a new batch: QCJob4227 |000> 0.154 |001> 0.219 |010> 0.2365 |100> 0.217 |101> 0.1735
In [21]:
Copied!
# Plot these results
def get_samples_from_result(result, n_qubits):
"""Converting the MyQLM Results into Pulser Samples."""
samples = {}
for sample in result.raw_data:
if len(sample.state.bitstring) > n_qubits:
raise ValueError(
f"State {sample.state} is incompatible with number of qubits"
f" declared {n_qubits}."
)
counts = sample.probability
samples[sample.state.bitstring.zfill(n_qubits)] = counts
return samples
# Plot these results
def get_samples_from_result(result, n_qubits):
"""Converting the MyQLM Results into Pulser Samples."""
samples = {}
for sample in result.raw_data:
if len(sample.state.bitstring) > n_qubits:
raise ValueError(
f"State {sample.state} is incompatible with number of qubits"
f" declared {n_qubits}."
)
counts = sample.probability
samples[sample.state.bitstring.zfill(n_qubits)] = counts
return samples
In [22]:
Copied!
count = get_samples_from_result(results, N_atoms)
most_freq = {k: v for k, v in count.items() if v > 10 / 1000}
plt.bar(list(most_freq.keys()), list(most_freq.values()))
plt.xticks(rotation="vertical")
plt.show()
count = get_samples_from_result(results, N_atoms)
most_freq = {k: v for k, v in count.items() if v > 10 / 1000}
plt.bar(list(most_freq.keys()), list(most_freq.values()))
plt.xticks(rotation="vertical")
plt.show()
Further reading¶
More details on writing and submitting jobs can be seen via mainly these resources:
Here are some useful topics: