Skip to content
Pasqal Documentation

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:

AspectEMU-SVEMU-MPS
MethodState VectorMatrix Product States
Max qubits≤25≤80
GPU allocation0 or 1 GPU per job0 or 1 GPU per job
GPU allocation by default1 GPU per job1 GPU per job
Min SDK version0.20.70.12.7
ObservablesBitStrings, Fidelity, CorrelationMatrix, Occupation, Energy, EnergyVariance, EnergySecondMoment, ExpectationBitStrings, Fidelity, CorrelationMatrix, Occupation, Energy, EnergyVariance, EnergySecondMoment, Expectation

Note: StateResult is not supported on remote backends. Use a local backend if you need access to the full quantum state.

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 SDK
from pasqal_cloud.device import DeviceTypeName
sdk = SDK(
username="your username",
password="your password",
project_id="your project id"
)
# Define your jobs
first = {"runs": 20}
second = {"runs": 50}
# For EMU-SV
batch = sdk.create_batch(
serialized_sequence,
jobs=[first, second],
device_type=DeviceTypeName.EMU_SV,
)
# For EMU-MPS
batch = 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"])

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 pulser
from pulser.backend import BitStrings, CorrelationMatrix
from emu_sv import SVConfig
# Create noise model
noise = pulser.NoiseModel(relaxation_rate=1, dephasing_rate=1.0)
# Set up observables
dt = 100
bitstrings = BitStrings(evaluation_times=[0.8], num_shots=1000)
correlation_matrix = CorrelationMatrix(evaluation_times=[0.8])
# Create and serialize config
config = SVConfig(noise_model=noise, dt=dt, observables=[bitstrings, correlation_matrix])
serialized_configuration = config.to_abstract_repr()

For EMU-MPS:

import pulser
from pulser.backend import BitStrings, CorrelationMatrix
from emu_mps import MPSConfig
# Create noise model
noise = pulser.NoiseModel(relaxation_rate=1, dephasing_rate=1.0)
# Set up observables
dt = 100
bitstrings = BitStrings(evaluation_times=[0.8], num_shots=1000)
correlation_matrix = CorrelationMatrix(evaluation_times=[0.8])
# Create and serialize config
config = MPSConfig(noise_model=noise, dt=dt, observables=[bitstrings, correlation_matrix])
serialized_configuration = config.to_abstract_repr()

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
)

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)

Last updated: