Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .github/workflows/selene-plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, macos-15-intel, windows-2022]
plugin:
- name: pecos-selene-general-noise
package: pecos_selene_general_noise
- name: pecos-selene-stabilizer
package: pecos_selene_stabilizer
- name: pecos-selene-statevec
Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"python/pecos-rslib-exp",
"python/pecos-rslib-cuda",
"python/pecos-rslib-llvm",
"python/selene-plugins/pecos-selene-general-noise",
"python/selene-plugins/pecos-selene-mast",
"python/selene-plugins/pecos-selene-stab-mps",
"python/selene-plugins/pecos-selene-stab-vec",
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"python/pecos-rslib-cuda",
"python/pecos-rslib-llvm",
"python/quantum-pecos",
"python/selene-plugins/pecos-selene-general-noise",
"python/selene-plugins/pecos-selene-mast",
"python/selene-plugins/pecos-selene-stab-mps",
"python/selene-plugins/pecos-selene-stab-vec",
Expand Down Expand Up @@ -102,6 +103,7 @@ reinstall-package = [
"pecos-rslib-cuda",
"pecos-rslib-exp",
"pecos-rslib-llvm",
"pecos-selene-general-noise",
]

[tool.black]
Expand Down
25 changes: 25 additions & 0 deletions python/selene-plugins/pecos-selene-general-noise/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "pecos-selene-general-noise"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
keywords.workspace = true
categories.workspace = true
description = "PECOS general noise model plugin for the Selene quantum emulator"

[lib]
name = "pecos_selene_general_noise"
path = "src/lib.rs"
crate-type = ["cdylib"]

[dependencies]
anyhow = { workspace = true }
pecos-core = { workspace = true }
pecos-engines = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
selene-core = { git = "https://github.com/Quantinuum/selene.git", rev = "01300ee5d4825e2dfc6500941d0540c3ff06988a" }

[lints]
workspace = true
58 changes: 58 additions & 0 deletions python/selene-plugins/pecos-selene-general-noise/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# PECOS General Noise Selene Plugin

This package exposes PECOS's general noise model as a device-neutral Selene
error-model plugin. It contains no calibrated hardware preset: every error
channel is disabled until the user configures it. Consequently,
`GeneralNoiseParameters()` is guaranteed to produce a noiseless model.

```python
from pecos_selene_general_noise import GeneralNoiseParameters, GeneralNoisePlugin

parameters = (
GeneralNoiseParameters()
.with_p_prep(1e-3)
.with_p_meas_0(2e-3)
.with_p_meas_1(3e-3)
.with_average_p1(1e-4)
.with_average_p2(1e-3)
.with_p_idle_linear(2e-3, {"Z": 1.0})
)
noise = GeneralNoisePlugin(parameters=parameters, random_seed=7)
```

For a first experiment, `GeneralNoiseParameters.uniform(1e-3)` applies a
common process-infidelity/error probability to preparation, measurement,
one-qubit, and two-qubit operations.

The fluent method names intentionally follow PECOS's Rust
`GeneralNoiseModelBuilder`. Parameter objects are immutable: every `with_*`
call returns a new validated configuration, making presets safe to reuse.
`with_seed` is intentionally not a parameter method because Selene owns and
supplies the per-shot error-model seed; set `random_seed` on
`GeneralNoisePlugin` instead. PECOS's historical `auto()` demonstration preset
is also omitted so that this package remains explicitly device-neutral.

## Capabilities

- process infidelity or average infidelity for gate errors
- custom Pauli and spontaneous-emission distributions
- leakage, seepage, and continuous leakage-to-depolarization scaling
- asymmetric readout errors
- linear stochastic, sine-squared stochastic, and coherent idle noise
- angle-dependent two-qubit noise and post-two-qubit idle sites
- all-to-all and topology-defined local crosstalk
- per-family and global scaling, plus arbitrary PECOS noiseless gate names

Idle rates use seconds because the adapter converts Selene's nanosecond schedule
to the units expected by PECOS. Local crosstalk is described with neutral qubit
groups rather than a hard-coded device layout.

## Development

From the PECOS repository root:

```bash
uv run --package pecos-selene-general-noise pytest \
python/selene-plugins/pecos-selene-general-noise/tests
cargo test -p pecos-selene-general-noise
```
59 changes: 59 additions & 0 deletions python/selene-plugins/pecos-selene-general-noise/hatch_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Build and bundle the native Selene error-model plugin."""

from __future__ import annotations

import platform
import shutil
import subprocess
import sys
from pathlib import Path
from typing import Any

from hatchling.builders.hooks.plugin.interface import BuildHookInterface
from packaging.tags import sys_tags


class PecosSeleneGeneralNoiseBuildHook(BuildHookInterface):
"""Compile the Rust cdylib and add it to the platform wheel."""

def _set_wheel_tag(self, build_data: dict[str, Any]) -> None:
build_data["pure_python"] = False
tag = next(tag for tag in sys_tags() if "manylinux" not in tag.platform and "musllinux" not in tag.platform)
target_platform = tag.platform
if sys.platform == "darwin":
from hatchling.builders.macos import process_macos_plat_tag

target_platform = process_macos_plat_tag(target_platform, compat=False)
build_data["tag"] = f"py3-none-{target_platform}"

def initialize(self, version: str, build_data: dict[str, Any]) -> None:
"""Build the native library unless an existing artifact is available."""
root = Path(self.root)
dist_dir = root / "python" / "pecos_selene_general_noise" / "_dist"
lib_dir = dist_dir / "lib"

system = platform.system()
if system == "Linux":
prefix, suffix = "lib", ".so"
elif system == "Darwin":
prefix, suffix = "lib", ".dylib"
elif system == "Windows":
prefix, suffix = "", ".dll"
else:
message = f"Unsupported platform: {system}"
raise RuntimeError(message)

workspace_root = root.parent.parent.parent
subprocess.run(
["cargo", "build", "--release", "--package", "pecos-selene-general-noise"],
cwd=workspace_root,
check=True,
)
filename = f"{prefix}pecos_selene_general_noise{suffix}"
source = workspace_root / "target" / "release" / filename
lib_dir.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, lib_dir / filename)
build_data["artifacts"] += [
artifact.relative_to(root).as_posix() for artifact in dist_dir.rglob("*") if artifact.is_file()
]
self._set_wheel_tag(build_data)
35 changes: 35 additions & 0 deletions python/selene-plugins/pecos-selene-general-noise/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[project]
name = "pecos-selene-general-noise"
version = "0.10.0.dev0"
requires-python = ">=3.10"
description = "PECOS general noise model plugin for the Selene quantum emulator"
readme = "README.md"
license = "Apache-2.0"
dependencies = ["selene-core>=0.2"]

[project.optional-dependencies]
test = [
"pytest>=9.0",
"selene-sim>=0.2,<0.3",
"guppylang>=0.14,<1.0",
]

[project.urls]
homepage = "https://pecos.io"
repository = "https://github.com/PECOS-packages/PECOS"

[build-system]
requires = ["hatchling", "packaging"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["python/pecos_selene_general_noise"]

[tool.hatch.build.hooks.custom]
path = "hatch_build.py"

[tool.uv]
cache-keys = [
{ file = "src/**/*.rs" },
{ file = "Cargo.toml" },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""PECOS general-noise plugin for Selene."""

from pecos_selene_general_noise.plugin import (
GateNoise,
GeneralNoiseParameters,
GeneralNoisePlugin,
IdleNoise,
MeasurementNoise,
NoiseScaling,
PreparationNoise,
TwoQubitGateNoise,
)

__all__ = [
"GateNoise",
"GeneralNoiseParameters",
"GeneralNoisePlugin",
"IdleNoise",
"MeasurementNoise",
"NoiseScaling",
"PreparationNoise",
"TwoQubitGateNoise",
]
Loading
Loading