Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions quantinuum_schemas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
QuantinuumConfig,
QulacsConfig,
SelenePlusConfig,
HeliosConfig,
HeliosEmulatorConfig,
)
from quantinuum_schemas.models.emulator_config import (
ClassicalReplaySimulator,
CoinflipSimulator,
DepolarizingErrorModel,
HeliosCustomErrorModel,
HeliosRuntime,
MatrixProductStateSimulator,
NoErrorModel,
Expand All @@ -24,6 +27,10 @@
StabilizerSimulator,
StatevectorSimulator,
)
from quantinuum_schemas.models.quantinuum_systems_noise import (
HeliosErrorParams,
UserErrorParams,
)

__all__ = [
"AerConfig",
Expand All @@ -37,6 +44,8 @@
"SeleneConfig",
"SelenePlusConfig",
"SimpleRuntime",
"HeliosConfig",
"HeliosEmulatorConfig",
"HeliosRuntime",
"NoErrorModel",
"DepolarizingErrorModel",
Expand All @@ -46,4 +55,7 @@
"CoinflipSimulator",
"MatrixProductStateSimulator",
"ClassicalReplaySimulator",
"HeliosCustomErrorModel",
"HeliosErrorParams",
"UserErrorParams",
]
139 changes: 130 additions & 9 deletions quantinuum_schemas/models/backend_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
as our backend credential classes handle those.
"""

# pylint: disable=too-many-lines
# pylint: disable=too-many-lines,no-member
import abc
from typing import Any, Dict, Literal, Optional, Type, TypeVar, Union

Expand All @@ -18,6 +18,7 @@
ClassicalReplaySimulator,
CoinflipSimulator,
DepolarizingErrorModel,
HeliosCustomErrorModel,
HeliosRuntime,
MatrixProductStateSimulator,
NoErrorModel,
Expand All @@ -32,6 +33,8 @@

ST = TypeVar("ST", bound="BaseModel")

KNOWN_NEXUS_HELIOS_EMULATORS = ["Helios-1E-lite"]


class BaseBackendConfig(BaseModel, abc.ABC):
"""Base class for all the backend configs.
Expand Down Expand Up @@ -161,8 +164,8 @@ def check_local_remote_parameters_are_consistent( # pylint: disable=no-self-arg
return values


class QuantinuumCompilerOptions(BaseModel):
"""Class for Quantinuum Compiler Options.
class QuantinuumOptions(BaseModel):
"""Class for Quantinuum additional options.

Intentionally allows extra unknown flags to be defined.
"""
Expand All @@ -173,17 +176,25 @@ class QuantinuumCompilerOptions(BaseModel):
def check_field_values_are_supported_types( # pylint: disable=no-self-argument,
cls, values: Dict[str, Any]
) -> Dict[str, Any]:
"""Check that compiler option values are supported types."""
"""Check that option values are supported types."""
for key in values:
assert isinstance(values[key], (str, int, bool, float, list)), (
"Compiler options must be str, bool int, float or a list of floats"
"Options must be str, bool int, float or a list of floats"
)
if isinstance(values[key], list):
for x in values[key]:
assert isinstance(x, float), "Lists must only contain floats"
return values


# Alias via inheritance for backwards compatibility
class QuantinuumCompilerOptions(QuantinuumOptions):
"""Class for Quantinuum compiler options.

Intentionally allows extra unknown flags to be defined.
"""


class QuantinuumConfig(BaseBackendConfig):
"""Runs circuits on Quantinuum's quantum devices and simulators.

Expand Down Expand Up @@ -280,7 +291,7 @@ class BaseEmulatorConfig(BaseModel):
n_qubits: The maximum number of qubits to simulate.
"""

n_qubits: int = Field(ge=1)
n_qubits: int | None = None

@model_validator(mode="after")
def prevent_direct_instantiation(self) -> Self:
Expand Down Expand Up @@ -338,9 +349,118 @@ class SelenePlusConfig(BaseEmulatorConfig, BaseBackendConfig):
| ClassicalReplaySimulator
) = Field(default_factory=StatevectorSimulator)
runtime: SimpleRuntime | HeliosRuntime = Field(default_factory=HeliosRuntime)
error_model: NoErrorModel | DepolarizingErrorModel | QSystemErrorModel = Field(
default_factory=QSystemErrorModel
)
error_model: (
NoErrorModel
| DepolarizingErrorModel
| QSystemErrorModel
| HeliosCustomErrorModel
) = Field(default_factory=QSystemErrorModel)

@model_validator(mode="after")
def validate_runtime_and_error_model(self) -> Self:
"""Validate that the runtime and error model are compatible."""
if isinstance(self.error_model, (QSystemErrorModel, HeliosCustomErrorModel)):
if not isinstance(self.runtime, HeliosRuntime):
raise ValueError(
f"error_model of type: {self.error_model.__class__.__name__} "
"can only be used with runtime of type: HeliosRuntime"
)
if isinstance(self.error_model, HeliosCustomErrorModel):
if isinstance(self.simulator, StabilizerSimulator):
if self.error_model.error_params.coherent_dephasing is False:
raise ValueError(
"HeliosErrorModel with StabilizerSimulator must have "
"coherent_dephasing set to True"
)
else:
if self.error_model.error_params.coherent_dephasing is True:
raise ValueError(
"HeliosErrorModel with non-StabilizerSimulator must have "
"coherent_dephasing set to False"
)

return self


class HeliosEmulatorConfig(BaseEmulatorConfig):
"""Configuration for Helios emulator systems."""

n_qubits: int | None = None

simulator: (
StatevectorSimulator
| StabilizerSimulator
| MatrixProductStateSimulator
| CoinflipSimulator
| ClassicalReplaySimulator
) = Field(default_factory=StatevectorSimulator)
error_model: (
NoErrorModel
| DepolarizingErrorModel
| QSystemErrorModel
| HeliosCustomErrorModel
) = Field(default_factory=QSystemErrorModel)
runtime: HeliosRuntime = Field(default_factory=HeliosRuntime)


class HeliosConfig(BaseBackendConfig):
"""Configuration for Helios generation QPUs, emulators and checkers."""

type: Literal["HeliosConfig"] = "HeliosConfig"

system_name: str = "Helios-1"
emulator_config: HeliosEmulatorConfig | None = None

max_cost: int | None = None

attempt_batching: bool = False
max_batch_cost: int = 2000

options: QuantinuumOptions | None = None

@model_validator(mode="after")
def check_valid_config(self) -> Self:
"""Perform simple configuration validation."""

if self.max_cost is None:
if (
not self.system_name.endswith("SC")
and self.system_name not in KNOWN_NEXUS_HELIOS_EMULATORS
):
raise ValueError(f"max_cost must be set for {self.system_name}.")

if self.emulator_config is not None:
if self.attempt_batching:
raise ValueError("Batching not available for emulators.")
if self.system_name in KNOWN_NEXUS_HELIOS_EMULATORS:
if self.max_cost:
raise ValueError(
f"max_cost not currently supported for {self.system_name}"
)
if self.system_name not in KNOWN_NEXUS_HELIOS_EMULATORS:
if self.emulator_config.simulator.type == "ClassicalReplaySimulator":
raise ValueError(
f"ClassicalReplaySimulator is only available for "
f"emulators in: {KNOWN_NEXUS_HELIOS_EMULATORS}"
)
if self.emulator_config.error_model.type == "DepolarizingErrorModel":
raise ValueError(
f"DepolarizingErrorModel is only available for "
f"emulators in: {KNOWN_NEXUS_HELIOS_EMULATORS}"
)
if self.emulator_config.runtime.seed is not None:
raise ValueError(
f"runtime.seed will be ignored for {self.system_name}"
)
if self.emulator_config.simulator.seed is not None:
raise ValueError(
f"simulator.seed will be ignored for {self.system_name}"
)
if self.emulator_config.error_model.seed is not None:
raise ValueError(
f"error_model.seed will be ignored for {self.system_name}"
)
return self


BackendConfig = Annotated[
Expand All @@ -355,6 +475,7 @@ class SelenePlusConfig(BaseEmulatorConfig, BaseBackendConfig):
QulacsConfig,
SeleneConfig,
SelenePlusConfig,
HeliosConfig,
],
Field(discriminator="type"),
]
Expand Down
21 changes: 20 additions & 1 deletion quantinuum_schemas/models/emulator_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from pydantic import BaseModel, Field, model_validator
from typing_extensions import Self

from quantinuum_schemas.models.quantinuum_systems_noise import HeliosErrorParams


class SimpleRuntime(BaseModel):
"""A 'simple' runtime for the Selene emulator.
Expand Down Expand Up @@ -70,7 +72,8 @@ class DepolarizingErrorModel(BaseModel):


class QSystemErrorModel(BaseModel):
"""Model for simulating error for a specific QSystem via Selene.
"""Preconfigured Error Model for simulating error for a specific QSystem via Selene.
Will use a preconfiguration of the error model as specified by the name parameter.

Args:
seed: Random seed for the error model.
Expand All @@ -83,6 +86,20 @@ class QSystemErrorModel(BaseModel):
name: str = "alpha"


class HeliosCustomErrorModel(BaseModel):
"""Configurable Error Model for simulating error for the Helios system via Selene.

Args:
seed: Random seed for the error model.
error_params: Parameters for the Helios error model.
"""

type: Literal["HeliosCustomErrorModel"] = "HeliosCustomErrorModel"

seed: int | None = Field(default=None)
error_params: HeliosErrorParams = Field(default_factory=HeliosErrorParams)


class StatevectorSimulator(BaseModel):
"""Statevector simulator built on a QuEST backend.

Expand Down Expand Up @@ -149,6 +166,8 @@ def check_valid_config(self) -> Self:
raise ValueError("CPU backend does not support chi > 256.")
if self.chi and self.truncation_fidelity:
raise ValueError("Cannot set both chi and truncation_fidelity.")
if self.backend != "auto":
raise ValueError("Only backend='auto' is supported at this time.")
return self


Expand Down
Loading