Executing a quantum program
A QuantumProgram can be easily run on multiple backends provided by Pasqal:
- locally installed emulators
- remote cloud emulators
- QPUs
Remote emulators and QPU require credentials to submit a job. More information on how to access a QPU through your favorite cloud provider, is available at Pasqal's website (external). Later, we will briefly show how to authenticate and send a remote job.
A simple quantum program
Section titled “A simple quantum program”Let us revisit the quantum program definition described before in the Quantum programs page.
from qoolqit import Drive, Ramp, Register, Constantfrom qoolqit import QuantumProgramfrom qoolqit import MockDevice
# Create the registerregister = Register.from_coordinates([(0,1), (0,-1), (2,0)])
# Defining the drive parametersomega = 0.8delta_i = -2.0 * omegadelta_f = -delta_iT = 25.0
# Defining the drivewf_amp = Constant(T, omega)wf_det = Ramp(T, delta_i, delta_f)drive = Drive(amplitude = wf_amp, detuning = wf_det)
# Creating the programprogram = QuantumProgram(register, drive)
# Compiling the Programdevice = MockDevice()program.compile_to(device)Executing locally
Section titled “Executing locally”Executing your program locally is as simple as importing the local emulator and just run your program on it
from qoolqit.execution import LocalEmulator
emulator = LocalEmulator()results = emulator.run(program)The LocalEmulator is a flexible object which allows to emulate the program run on different backends:
from qoolqit.execution import LocalEmulatorfrom qoolqit.execution import QutipBackendV2, SVBackend, MPSBackend
emulator = LocalEmulator(backend_type=SVBackend)QutipBackendV2: Based on Qutip, runs programs with up to ~12 qubits and return qutip objects in the results.SVBackend: PyTorch based state vectors and sparse matrices emulator. Runs programs with up to ~25 qubits and return torch objects in the results.MPSBackend: PyTorch based emulator using Matrix Product States (MPS). Runs programs with up to ~80 qubits and return torch objects in the results.
More experienced users, might also want to configure an emulator.
To fully exploit the potential of each emulator backend, they can be configured through the generic EmulationConfig object. For example, the following configuration,
from qoolqit.execution import EmulationConfig, Occupation
observables = (Occupation(evaluation_times=[0.1, 0.5, 1.0]),)emulation_config = EmulationConfig( observables=observables, with_modulation=True )simply asks the backend to compute some observable during runtime and to emulate the hardware more closely by considering finite-bandwidth hardware modulation of the drive.
Finally, to run a program on a configured emulator (local or remote), we can simply pass the configuration as an additional argument to the emulator instance as:
from qoolqit.execution import EmulationConfig
emulator = LocalEmulator(emulation_config=emulation_config)Dedicated and specific configuration for each backend also exist: QutipConfig, SVConfig, MPSConfig. They should be used by pairing them with the corresponding backend type.
For more information about how the configuration options, please, refer to Pulser documentation (external).
Handling local results
Section titled “Handling local results”The call emulator.run(program) will return a Sequence[Results] object type. This is where the results of the computation are stored.
For more info about this specific object, please, have a look at Pulser documentation (external).
As an example, lets inspect the results we got in the previous run:
# single result in the sequenceresults[0].get_result_tags()['bitstrings']
# single result in the sequencefinal_bitstrings = results[0].final_bitstringsCounter({'111': 85, '011': 8, '110': 6, '101': 1})
Executing remotely
Section titled “Executing remotely”As anticipated, credentials to create a connection is required for most remote workflows. Here we will show how to create the specific handler of Pasqal Cloud services. Again, for more information about Pasqal Cloud and other providers, please refer to the Pasqal Cloud website (external).
Let's first initialize a connection as:
from pulser_pasqal import PasqalCloudconnection = PasqalCloud( username=USERNAME, # Your username or email address for the Pasqal Cloud Platform password=PASSWORD, # The password for your Pasqal Cloud Platform account project_id=PROJECT_ID, # The ID of the project associated to your account)To use such connection, and to send jobs to the cloud, we first need to initialize a remote emulator:
from qoolqit.execution import RemoteEmulator
emulator = RemoteEmulator(connection=connection)As before, also RemoteEmulator can be instantiated with:
- backend_type: remote counterpart of backends, namely EmuFreeBackendV2, EmuSVBackend (not available yet), EmuMPSBackend.
- emulation_config: same as before.
- runs: same as before.
from qoolqit.execution import RemoteEmulator, EmuMPSBackend
remote_emulator = RemoteEmulator( backend_type=EmuMPSBackend, connection=connection, emulation_config = emulation_config runs=200)results = remote_emulator.run(program)Handling remote results
Section titled “Handling remote results”Remote emulators and QPU both have a run() method that will return a Sequence[Results] object type.
However, if your program requires intensive resources to be run, or if QPU happens to be on maintenance, the use of this method is discouraged since it might leave your script hanging.
In these situations prefer the use of the submit(program) -> RemoteResults instead:
remote_emulator = RemoteEmulator(.., connection=connection, ...)remote_results = remote_emulator.submit(program)Here, the remote results can act as a job handler: - Query the batch status: PENDING, RUNNING, DONE, etc.:
batch_status = remote_results.get_batch_status()batch_id = remote_results.get_batch_id()batch_idconnectionfrom qoolqit.execution import RemoteResults
remote_results = RemoteResults(batch_id, connection)Once the batch has been completed (batch_status returns DONE), the complete results can be finally fetched as:
results = remote_results.resultsExecuting remotely on a QPU
Section titled “Executing remotely on a QPU”A connection object can also be used to run the program directly on a QPU. To see the list of available devices, run:
connection = PasqalCloud()connection.fetch_available_devices(){'FRESNEL': FRESNEL}
Finally, on a QPU there is no configuration and, as per the properties of the quantum hardware, results will come as a bitstrings counter of length specified by the runs parameter.
from qoolqit.execution import QPU
qpu = QPU(connection=connection, runs=500)