Skip to content

qoolqit.execution

execution

QoolQit module to execute quantum programs on QPUs or local/remote emulators.

Modules:

  • backends
  • compilation_functions
  • job
  • sequence_compiler

Classes:

  • LocalEmulator

    Run QoolQit QuantumPrograms on a Pasqal local emulator backends.

  • QPU

    Execute QoolQit QuantumPrograms on Pasqal quantum processing units.

  • RemoteEmulator

    Run QoolQit QuantumPrograms on a Pasqal remote emulator backends.

  • SequenceCompiler

    Compiles a QoolQit Register and Drive to a Device.

Functions:

  • get_batch_id

    Return the batch ID associated with a remote job.

  • retrieve_remote_job

    Retrieve a previously submitted remote job by its identifiers.

Attributes:

  • JobStatus (TypeAlias) –

    Alias for :class:~pulser.backend.remote.JobStatus.

JobStatus: TypeAlias = remote.JobStatus module-attribute

Alias for :class:~pulser.backend.remote.JobStatus.

Terminal states (where :meth:Job.has_ended returns True):

  • :attr:~remote.JobStatus.DONE
  • :attr:~remote.JobStatus.ERROR
  • :attr:~remote.JobStatus.CANCELED

LocalEmulator(*, backend_type: type[EmulatorBackend] = QutipBackendV2, emulation_config: EmulationConfig | None = None, num_shots: int | None = None)

Run QoolQit QuantumPrograms on a Pasqal local emulator backends.

This class serves as a primary interface between tools written using QoolQit (including solvers) and local emulator backends.

Parameters:

  • backend_type

    (type, default: QutipBackendV2 ) –

    backend type. Must be a subtype of pulser.backend.EmulatorBackend.

  • emulation_config

    (EmulationConfig, default: None ) –

    optional configuration object emulators.

  • num_shots

    (int, default: None ) –

    number of bitstring samples to collect from the final quantum state.

Examples:

from qoolqit.execution import LocalEmulator, BackendType
backend = LocalEmulator(backend_type=BackendType.QutipBackendV2)
result = backend.run(program)

Methods:

Source code in qoolqit/execution/backends.py
def __init__(
    self,
    *,
    backend_type: type[EmulatorBackend] = QutipBackendV2,
    emulation_config: EmulationConfig | None = None,
    num_shots: int | None = None,
) -> None:
    """Instantiates a LocalEmulator."""
    super().__init__(num_shots=num_shots)
    if not issubclass(backend_type, EmulatorBackend):
        raise TypeError(
            "Error in `LocalEmulator`: `backend_type` must be a EmulatorBackend type."
        )
    self._backend_type = backend_type
    self._emulation_config = self.validate_emulation_config(emulation_config)

default_emulation_config() -> EmulationConfig

Return a unique emulation config for all emulators.

Defaults to a configuration that asks for the final bitstring, sampled num_shots times.

Source code in qoolqit/execution/backends.py
def default_emulation_config(self) -> EmulationConfig:
    """Return a unique emulation config for all emulators.

    Defaults to a configuration that asks for the final bitstring, sampled `num_shots` times.
    """
    return EmulationConfig(observables=(BitStrings(num_shots=self._num_shots),))

run(program: QuantumProgram) -> job.Job[Results]

Run a compiled QuantumProgram and return the results.

Source code in qoolqit/execution/backends.py
def run(self, program: QuantumProgram) -> job.Job[Results]:
    """Run a compiled QuantumProgram and return the results."""
    self._backend = self._backend_type(program.compiled_sequence, config=self._emulation_config)
    results = self._backend.run()
    assert isinstance(results, Results)
    return job._LocalJob(results)

validate_emulation_config(emulation_config: EmulationConfig | None) -> EmulationConfig

Returns a valid config for emulator backends, if needed.

Parameters:

  • emulation_config
    (EmulationConfig | None) –

    optional base configuration class for all emulators backends. If no config is provided to an emulator backend, the backend default will used.

Source code in qoolqit/execution/backends.py
def validate_emulation_config(
    self, emulation_config: EmulationConfig | None
) -> EmulationConfig:
    """Returns a valid config for emulator backends, if needed.

    Args:
        emulation_config: optional base configuration class for all emulators backends.
            If no config is provided to an emulator backend, the backend default will used.
    """
    if emulation_config is None:
        emulation_config = self.default_emulation_config()
    else:
        has_bitstrings = any(
            isinstance(obs, BitStrings) for obs in emulation_config.observables
        )
        if not has_bitstrings:
            updated_obs = (*emulation_config.observables, BitStrings(num_shots=self._num_shots))
            emulation_config = emulation_config.with_changes(observables=updated_obs)

    if self._num_shots is not None:
        emulation_config = emulation_config.with_changes(default_num_shots=self._num_shots)

    return emulation_config

QPU(*, connection: RemoteConnection, num_shots: int | None = None)

Execute QoolQit QuantumPrograms on Pasqal quantum processing units.

This class provides the primary interface for running quantum programs on actual QPU hardware. It requires authenticated credentials through a connection object to submit and execute programs on remote quantum processors.

Parameters:

  • connection

    (RemoteConnection) –

    Authenticated connection to the remote QPU backend.

  • num_shots

    (int | None, default: None ) –

    Number of bitstring samples to collect from the final quantum state.

Examples:

Using Pasqal Cloud:

from pulser_pasqal import PasqalCloud
from qoolqit.execution import QPU

connection = PasqalCloud(
    username="your_username",
    password="your_password",
    project_id="your_project_id"
)
backend = QPU(connection=connection)
remote_results = backend.submit(program)

Using Atos MyQML:

from pulser_myqlm import PulserQLMConnection
from qoolqit.execution import QPU

connection = PulserQLMConnection()
backend = QPU(connection=connection)
results = backend.run(program)

Note

Contact your quantum computing provider for credentials and connection setup: - Pasqal Cloud Documentation - Atos MyQML Framework

Methods:

  • run

    Run a compiled QuantumProgram and return a job handler.

  • validate_connection

    Validate the required connection to instantiate a RemoteBackend.

Source code in qoolqit/execution/backends.py
def __init__(
    self,
    *,
    connection: RemoteConnection,
    num_shots: int | None = None,
) -> None:
    """Instantiates a QPU backend."""
    self._backend_type = QPUBackend
    self._connection = self.validate_connection(connection)
    if num_shots is None:
        raise ValueError(
            """Number of shots must be provided to use the QPU backend.
            Please specify `num_shots` when creating the QPU instance.
            For example: QPU(connection=..., num_shots=100)""",
        )
    self._config = BackendConfig(default_num_shots=num_shots)

run(program: QuantumProgram) -> job.Job[Results]

Run a compiled QuantumProgram and return a job handler.

The returned handler Job can be used to retrieve results with job.results()

Parameters:

Source code in qoolqit/execution/backends.py
def run(self, program: QuantumProgram) -> job.Job[Results]:
    """Run a compiled QuantumProgram and return a job handler.

    The returned handler `Job` can be used to retrieve results with `job.results()`

    Args:
        program (QuantumProgram): the compiled quantum program to run.
    """
    self._backend = self._backend_type(
        program.compiled_sequence, connection=self._connection, config=self._config
    )
    remote_results = self._backend.run(wait=False)
    # If in open-batch mode, the job should be the last one in the batch ?
    return job._RemoteJob._from_remote_results(remote_results, -1)

validate_connection(connection: RemoteConnection) -> RemoteConnection staticmethod

Validate the required connection to instantiate a RemoteBackend.

Remote emulators and QPUs require a pulser.backend.remote.RemoteConnection or derived to send jobs. Validation also happens inside the backend. Early validation just makes the error easier to understand.

Source code in qoolqit/execution/backends.py
@staticmethod
def validate_connection(connection: RemoteConnection) -> RemoteConnection:
    """Validate the required connection to instantiate a RemoteBackend.

    Remote emulators and QPUs require a `pulser.backend.remote.RemoteConnection` or derived
    to send jobs. Validation also happens inside the backend. Early validation just makes the
    error easier to understand.
    """
    if not isinstance(connection, RemoteConnection):
        raise TypeError(f"""Error in `PulserRemoteBackend`:
            `connection` must be of type {RemoteConnection}.""")
    return connection

RemoteEmulator(*, backend_type: type[RemoteEmulatorBackend] = EmuFreeBackendV2, connection: RemoteConnection, emulation_config: EmulationConfig | None = None, num_shots: int | None = None)

Run QoolQit QuantumPrograms on a Pasqal remote emulator backends.

This class serves as a primary interface between tools written using QoolQit (including solvers) and remote emulator backends. The behavior is similar to LocalEmulator, but here, requires credentials through a connection to submit/run a program. To get your credentials and to create a connection object, please refer to the Pasqal Cloud interface documentation.

Parameters:

  • backend_type

    (type, default: EmuFreeBackendV2 ) –

    backend type. Must be a subtype of pulser_pasqal.backends.RemoteEmulatorBackend.

  • connection

    (RemoteConnection) –

    connection to execute the program on remote backends.

  • emulation_config

    (EmulationConfig, default: None ) –

    optional configuration object emulators.

  • num_shots

    (int, default: None ) –

    number of bitstring samples to collect from the final quantum state.

Examples:

from pulser_pasqal import PasqalCloud
from qoolqit.execution import RemoteEmulator, BackendType
connection = PasqalCloud(username=..., password=..., project_id=...)
backend = RemoteEmulator(backend_type=BackendType.EmuFreeBackendV2, connection=connection)
then
remote_results = backend.submit(program)
or
results = backend.run(program)

Methods:

Source code in qoolqit/execution/backends.py
def __init__(
    self,
    *,
    backend_type: type[RemoteEmulatorBackend] = EmuFreeBackendV2,
    connection: RemoteConnection,
    emulation_config: EmulationConfig | None = None,
    num_shots: int | None = None,
) -> None:
    """Instantiates a RemoteEmulator."""
    super().__init__(num_shots=num_shots)
    if not issubclass(backend_type, RemoteEmulatorBackend):
        raise TypeError(
            "Error in `RemoteEmulator`: `backend_type` must be a RemoteEmulatorBackend type."
        )
    self._backend_type = backend_type
    self._connection = self.validate_connection(connection)
    self._emulation_config = self.validate_emulation_config(emulation_config)

default_emulation_config() -> EmulationConfig

Return a unique emulation config for all emulators.

Defaults to a configuration that asks for the final bitstring, sampled num_shots times.

Source code in qoolqit/execution/backends.py
def default_emulation_config(self) -> EmulationConfig:
    """Return a unique emulation config for all emulators.

    Defaults to a configuration that asks for the final bitstring, sampled `num_shots` times.
    """
    return EmulationConfig(observables=(BitStrings(num_shots=self._num_shots),))

run(program: QuantumProgram) -> job.Job[Results]

Run a compiled QuantumProgram and return a job handler.

The returned handler Job can be used to retrieve results with job.results()

Parameters:

Source code in qoolqit/execution/backends.py
def run(self, program: QuantumProgram) -> job.Job[Results]:
    """Run a compiled QuantumProgram and return a job handler.

    The returned handler `Job` can be used to retrieve results with `job.results()`

    Args:
        program (QuantumProgram): the compiled quantum program to run.
    """
    # Instantiate backend
    self._backend = self._backend_type(
        program.compiled_sequence,
        connection=self._connection,
        config=self._emulation_config,
    )
    remote_results = self._backend.run(wait=False)
    # If in open-batch mode, the job should be the last one in the batch ?
    return job._RemoteJob._from_remote_results(remote_results, -1)

validate_connection(connection: RemoteConnection) -> RemoteConnection staticmethod

Validate the required connection to instantiate a RemoteBackend.

Remote emulators and QPUs require a pulser.backend.remote.RemoteConnection or derived to send jobs. Validation also happens inside the backend. Early validation just makes the error easier to understand.

Source code in qoolqit/execution/backends.py
@staticmethod
def validate_connection(connection: RemoteConnection) -> RemoteConnection:
    """Validate the required connection to instantiate a RemoteBackend.

    Remote emulators and QPUs require a `pulser.backend.remote.RemoteConnection` or derived
    to send jobs. Validation also happens inside the backend. Early validation just makes the
    error easier to understand.
    """
    if not isinstance(connection, RemoteConnection):
        raise TypeError(f"""Error in `PulserRemoteBackend`:
            `connection` must be of type {RemoteConnection}.""")
    return connection

validate_emulation_config(emulation_config: EmulationConfig | None) -> EmulationConfig

Returns a valid config for emulator backends, if needed.

Parameters:

  • emulation_config
    (EmulationConfig | None) –

    optional base configuration class for all emulators backends. If no config is provided to an emulator backend, the backend default will used.

Source code in qoolqit/execution/backends.py
def validate_emulation_config(
    self, emulation_config: EmulationConfig | None
) -> EmulationConfig:
    """Returns a valid config for emulator backends, if needed.

    Args:
        emulation_config: optional base configuration class for all emulators backends.
            If no config is provided to an emulator backend, the backend default will used.
    """
    if emulation_config is None:
        emulation_config = self.default_emulation_config()
    else:
        has_bitstrings = any(
            isinstance(obs, BitStrings) for obs in emulation_config.observables
        )
        if not has_bitstrings:
            updated_obs = (*emulation_config.observables, BitStrings(num_shots=self._num_shots))
            emulation_config = emulation_config.with_changes(observables=updated_obs)

    if self._num_shots is not None:
        emulation_config = emulation_config.with_changes(default_num_shots=self._num_shots)

    return emulation_config

SequenceCompiler(register: Register, drive: Drive, device: Device, profile: CompilerProfile, device_max_duration_ratio: float | None = None)

Compiles a QoolQit Register and Drive to a Device.

Parameters:

  • register

    (Register) –

    the QoolQit Register.

  • drive

    (Drive) –

    the QoolQit Drive.

  • device

    (Device) –

    the QoolQit Device.

  • profile

    (CompilerProfile) –

    the CompilerProfile to use.

  • device_max_duration_ratio

    (float | None, default: None ) –

    optionally set the program duration to a fraction of the device's maximum allowed duration.

Source code in qoolqit/execution/sequence_compiler.py
def __init__(
    self,
    register: Register,
    drive: Drive,
    device: Device,
    profile: CompilerProfile,
    device_max_duration_ratio: float | None = None,
) -> None:
    """Initializes the compiler.

    Args:
        register: the QoolQit Register.
        drive: the QoolQit Drive.
        device: the QoolQit Device.
        profile: the CompilerProfile to use.
        device_max_duration_ratio: optionally set the program duration to a fraction
            of the device's maximum allowed duration.
    """

    self._register = register
    self._drive = drive
    self._device = device
    self._target_device = device._device
    self._profile = profile
    self._device_max_duration_ratio = device_max_duration_ratio
    self._compilation_function: Callable = basic_compilation

get_batch_id(job: Job[Results]) -> str

Return the batch ID associated with a remote job.

Temporary utility for cases where batch_id must be persisted and later passed to :func:retrieve_remote_job. Will be deprecated once RemoteConnection supports direct job lookup by job ID alone.

Parameters:

  • job

    (Job[Results]) –

    Any :class:Job instance.

Returns:

  • str ( str ) –

    The batch ID if job is a :class:_RemoteJob,

  • str

    otherwise an empty string.

Source code in qoolqit/execution/job.py
def get_batch_id(job: Job[Results]) -> str:
    """Return the batch ID associated with a remote job.

    Temporary utility for cases where *batch_id* must be persisted
    and later passed to :func:`retrieve_remote_job`. Will be
    deprecated once ``RemoteConnection`` supports direct job lookup
    by job ID alone.

    Args:
        job (Job[Results]): Any :class:`Job` instance.

    Returns:
        str: The batch ID if *job* is a :class:`_RemoteJob`,
        otherwise an empty string.
    """
    if isinstance(job, _RemoteJob):
        return job._batch_id
    return ""

retrieve_remote_job(connection: remote.RemoteConnection, job_id: str, *, batch_id: str = '') -> Job[Results]

Retrieve a previously submitted remote job by its identifiers.

Use this to reconnect to a job in a new session, or to monitor a job submitted outside the current context.

Note

The batch_id argument is required by some RemoteConnection implementations (e.g. PasqalCloudConnection) to query job progress. Use :func:get_batch_id to recover the batch ID from an existing :class:Job if needed.

This dependency on batch_id is temporary and will be removed once RemoteConnection supports direct lookup by job ID alone.

Parameters:

  • connection

    (RemoteConnection) –

    The remote connection through which to query the job.

  • job_id

    (str) –

    The UUID of the job to retrieve.

  • batch_id

    (str, default: '' ) –

    The batch identifier the job belongs to. Defaults to an empty string.

Returns:

  • Job[Results]

    Job[Results]: A :class:_RemoteJob connected to the

  • Job[Results]

    specified job.

Source code in qoolqit/execution/job.py
def retrieve_remote_job(
    connection: remote.RemoteConnection,
    job_id: str,
    *,
    batch_id: str = "",
) -> Job[Results]:
    """Retrieve a previously submitted remote job by its identifiers.

    Use this to reconnect to a job in a new session, or to monitor a
    job submitted outside the current context.

    Note:
        The *batch_id* argument is required by some
        ``RemoteConnection`` implementations (e.g.
        ``PasqalCloudConnection``) to query job progress. Use
        :func:`get_batch_id` to recover the batch ID from an existing
        :class:`Job` if needed.

        This dependency on *batch_id* is temporary and will be removed
        once ``RemoteConnection`` supports direct lookup by job ID
        alone.

    Args:
        connection (remote.RemoteConnection): The remote connection
            through which to query the job.
        job_id (str): The UUID of the job to retrieve.
        batch_id (str): The batch identifier the job belongs to.
            Defaults to an empty string.

    Returns:
        Job[Results]: A :class:`_RemoteJob` connected to the
        specified job.
    """
    return _RemoteJob(connection, job_id, batch_id=batch_id)