Emulators Cloud Integration
EMU-SV (State Vector) and EMU-MPS (Matrix Product States) are two emulators for simulating quantum sequences, both are fully integrated into the Pasqal cloud platform with configurable noise models, observables, and simulation parameters.
EMU-SV performs exact state vector simulation, tracking the full quantum state throughout the computation. The memory required grows as 2^N for N qubits, which limits the system size but provides exact results without approximation. This makes it ideal for smaller systems where high precision is required.
EMU-MPS uses matrix product states to encode quantum states such that the memory required depends on the entanglement in the system. For product states, an MPS only takes d×N numbers to store the state for N d-level qudits, while maximally entangled states require memory similar to a full state vector. For many systems of interest, MPS is more efficient than state vectors, allowing simulation of more qubits.
This article covers how to use both emulators through the Pasqal cloud platform. For detailed documentation on the emulators themselves, see:
- EMU-SV documentation (external) or EMU-SV emulation tools doc (external) .
- EMU-MPS documentation (external) or EMU-MPS emulation tools doc (external) or arXiv Paper (external) .
Comparison between emulators
Section titled “Comparison between emulators”| Aspect | EMU-SV | EMU-MPS |
|---|---|---|
| Method | State Vector | Matrix Product States |
| Max qubits | ≤25 | ≤80 |
| GPU allocation | 0 or 1 GPU per job | 0 or 1 GPU per job |
| GPU allocation by default | 1 GPU per job | 1 GPU per job |
| Min SDK version | 0.20.7 | 0.12.7 |
| Observables | BitStrings, Fidelity, CorrelationMatrix, Occupation, Energy, EnergyVariance, EnergySecondMoment, Expectation | BitStrings, Fidelity, CorrelationMatrix, Occupation, Energy, EnergyVariance, EnergySecondMoment, Expectation |
Note:
StateResultis not supported on remote backends. Use a local backend if you need access to the full quantum state.
Basic usage with the SDK
Section titled “Basic usage with the SDK”This example demonstrates how to submit a job for execution on a cloud-hosted emulator. It assumes you have created a Pulser sequence using the Pasqal Pulser library (external) .
from pasqal_cloud import SDKfrom pasqal_cloud.device import DeviceTypeName
sdk = SDK( username="your username", password="your password", project_id="your project id")
# Define your jobsfirst = {"runs": 20}second = {"runs": 50}
# For EMU-SVbatch = sdk.create_batch( serialized_sequence, jobs=[first, second], device_type=DeviceTypeName.EMU_SV,)
# For EMU-MPSbatch = sdk.create_batch( serialized_sequence, jobs=[first, second], device_type=DeviceTypeName.EMU_MPS,)You can pass the wait argument to create_batch to poll Pasqal’s cloud service until your results are ready. See the batches documentation (external)
for more details.
Default output format with bitstrings (default observable)
Section titled “Default output format with bitstrings (default observable)”An emulation returns results with three keys:
{ "raw": null, "counter": { "100000": 15, "100010": 1, "100100": 1, "110000": 8, "110001": 1, "111010": 1, "111100": 1, "000000": 830, "000010": 26, "001010": 13, "001000": 13, "000100": 22, "010000": 13, "000110": 14, "000011": 12, "011000": 2, "000001": 13, "001100": 13, "000101": 1 }, "serialised_results": "{serialised_results}"}raw: Raw measurement data,counter: A proxy to the bitstrings observable sampled at the final time step of the simulation, if it is defined as an observable. Otherwise, it is set to None. This ensures a consistent result format with QPU outputs.serialised_results: Detailed emulation data (deserialize with Pulser).
To deserialize the serialised_results using pulser:
from pulser.backend import Results
deserialized_result = Results.from_abstract_repr(json_result["serialised_results"])Custom configuration
Section titled “Custom configuration”Both emulators support custom configurations for noise models and observables. The pattern is similar: create a config object and serialize it with .to_abstract_repr().
For EMU-SV:
import pulserfrom pulser.backend import BitStrings, CorrelationMatrixfrom emu_sv import SVConfig
# Create noise modelnoise = pulser.NoiseModel(relaxation_rate=1, dephasing_rate=1.0)
# Set up observablesdt = 100bitstrings = BitStrings(evaluation_times=[0.8], num_shots=1000)correlation_matrix = CorrelationMatrix(evaluation_times=[0.8])
# Create and serialize configconfig = SVConfig(noise_model=noise, dt=dt, observables=[bitstrings, correlation_matrix])serialized_configuration = config.to_abstract_repr()For EMU-MPS:
import pulserfrom pulser.backend import BitStrings, CorrelationMatrixfrom emu_mps import MPSConfig
# Create noise modelnoise = pulser.NoiseModel(relaxation_rate=1, dephasing_rate=1.0)
# Set up observablesdt = 100bitstrings = BitStrings(evaluation_times=[0.8], num_shots=1000)correlation_matrix = CorrelationMatrix(evaluation_times=[0.8])
# Create and serialize configconfig = MPSConfig(noise_model=noise, dt=dt, observables=[bitstrings, correlation_matrix])serialized_configuration = config.to_abstract_repr()Submitting with configuration
Section titled “Submitting with configuration”Pass your serialized configuration using the backend_configuration parameter:
batch = sdk.create_batch( serialized_sequence, jobs=[first, second], device_type=DeviceTypeName.EMU_SV, # or DeviceTypeName.EMU_MPS backend_configuration=serialized_configuration)Using pulser-pasqal
Section titled “Using pulser-pasqal”You can also submit jobs directly through the pulser-pasqal package using the appropriate backend class.
Using pulser-pasqal instead of the SDK directly makes it easy to switch between local and remote execution. Since all Pulser backends share the same interface, you can develop and test locally with a local backend, then swap to EmuSVBackend or EmuMPSBackend to run on the cloud without changing the rest of your code.
For EMU-SV:
from pulser_pasqal import PasqalCloud, EmuSVBackend
connection = PasqalCloud( username="your_username", password="your_password", project_id="your_project_id")
backend = EmuSVBackend(sequence, connection=connection)
job_params = [ {"runs": 100}, {"runs": 50},]
results = backend.run(job_params=job_params, wait=True)For EMU-MPS:
from pulser_pasqal import PasqalCloud, EmuMPSBackend
connection = PasqalCloud( username="your_username", password="your_password", project_id="your_project_id")
backend = EmuMPSBackend(sequence, connection=connection)
job_params = [ {"runs": 100}, {"runs": 50},]
results = backend.run(job_params=job_params, wait=True)