Solver adapters for XQMX models (dwave-samplers; pluggable solver interface).
Project description
xqsa -- Solver adapters for XQMX models
Pluggable solvers for quadratic optimisation models produced by the XQuad toolchain.
| Solver | Class | Transport | Install |
|---|---|---|---|
| DWave CPU simulated annealing | SolverDWaveCPU |
local | pip install xqsa |
| D-Wave Advantage QPU | SolverDWaveQPU |
D-Wave Leap cloud | pip install xqsa[dwave] |
| CUDA GPU simulated annealing | SolverCudaGPU |
local (NVIDIA GPU) | pip install xqsa[cuda] |
| Metal GPU SA / Gibbs | SolverMetalGPU |
local (Apple GPU, macOS) | pip install xqsa[metal] |
Install
# CPU simulated annealing only
pip install xqsa
# Add D-Wave QPU support
pip install xqsa[dwave]
# Add CUDA GPU support (requires NVIDIA GPU + CUDA driver)
pip install xqsa[cuda]
# Add Metal GPU support (requires macOS + Apple Silicon GPU)
pip install xqsa[metal]
Already have xqsa installed? Add an extra on top:
pip install "xqsa[cuda]" # adds CUDA support to an existing install
Driver prerequisites
| Extra | Hardware | Prerequisite | Verify |
|---|---|---|---|
[cuda] |
NVIDIA GPU | CUDA 12.x driver | nvidia-smi |
[metal] |
Apple Silicon | macOS 13+ (Ventura) | built-in on supported Macs |
[dwave] |
-- | D-Wave Leap account + DWAVE_API_TOKEN env var |
dwave ping |
After installing an extra, verify the solver class imports:
python -c "from xqsa import SolverCudaGPU; print('ok')"
python -c "from xqsa import SolverMetalGPU; print('ok')"
python -c "from xqsa import SolverDWaveQPU; print('ok')"
uv workspace caveat
uv sync installs only base dependencies, not optional extras. To test GPU/QPU solvers locally, install the extra explicitly:
uv pip install "xqsa[cuda]" # or [metal] / [dwave]
Note that a bare uv run pytest re-syncs the environment and drops both the extra and the maturin-built xqffi extension. Use uv run --no-sync pytest to preserve them, or re-run maturin develop + uv pip install "xqsa[...]" after each sync.
Quick start -- CPU simulated annealing
from xqsa import SolverDWaveCPU
from xqvm_py import XQMX, XQMXDomain
model = XQMX.binary_model(size=4)
model.set_linear(0, -1)
model.set_quadratic(0, 1, 2)
solver = SolverDWaveCPU()
result = solver.solve(model)
# result.sample: XQMX -- the best assignment found
# result.energy: int -- authoritative Hamiltonian energy
# result.timing: float -- wall-clock seconds spent solving
# result.metadata: dict -- seed, reads, solver-specific params
Quick start -- D-Wave Advantage QPU
Requires a D-Wave Leap account and
pip install xqsa[dwave].
import os
os.environ["DWAVE_API_TOKEN"] = "your-leap-token" # or pass token= directly
from xqsa import SolverDWaveQPU
from xqvm_py.xqmx import XQMX
model = XQMX.binary_model(size=4)
model.set_linear(0, -1)
model.set_quadratic(0, 1, 2)
solver = SolverDWaveQPU() # auto-selects best Advantage system
result = solver.solve(model)
print(result.metadata["solver"]) # e.g. "Advantage_system5.4"
print(result.metadata["qpu_timing"]) # QPU timing breakdown from Leap
Credential resolution order: token= constructor argument ->
DWAVE_API_TOKEN env var -> ValueError.
For a specific solver: SolverDWaveQPU(solver="Advantage_system5.4").
For custom annealing: solver.solve(model, annealing_time=100, chain_strength=2.0).
Quick start -- CUDA GPU simulated annealing
Requires an NVIDIA GPU with CUDA support and pip install xqsa[cuda].
from xqsa import SolverCudaGPU
from xqvm_py.xqmx import XQMX
model = XQMX.binary_model(size=4)
model.set_linear(0, -1)
model.set_quadratic(0, 1, 2)
solver = SolverCudaGPU() # uses all defaults
result = solver.solve(model)
print(result.energy, result.timing)
# Custom parameters
solver = SolverCudaGPU(num_reads=200, num_sweeps=2000, seed=42)
result = solver.solve(model, beta_range=(0.1, 5.0))
Algorithm selection via the strategy parameter (currently only "sa"
is supported; "gibbs" and "metropolis" are planned).
Quick start -- Metal GPU (Apple Silicon)
Requires macOS with an Apple Metal GPU and pip install xqsa[metal].
from xqsa import SolverMetalGPU
from xqvm_py.xqmx import XQMX
model = XQMX.binary_model(size=4)
model.set_linear(0, -1)
model.set_quadratic(0, 1, 2)
# Simulated annealing (default), or strategy="gibbs" for block Gibbs sampling.
solver = SolverMetalGPU(strategy="sa", num_reads=200, num_sweeps=2000, seed=42)
result = solver.solve(model)
print(result.energy, result.timing)
The strategy parameter selects "sa" (simulated annealing) or "gibbs"
(block Gibbs sampling over a greedy graph colouring). beta_schedule_type
selects "geometric" (default) or "linear". Coefficients are computed in
float32 on the GPU; result.energy is recomputed authoritatively in
integer arithmetic.
Selecting a solver by name
build_solver constructs any backend from a short, CLI-friendly name, so
tools and scripts can stay backend-agnostic:
from xqsa import SOLVERS, build_solver
print(sorted(SOLVERS)) # ['cuda-gpu', 'dwave-cpu', 'dwave-qpu', 'metal-gpu']
solver = build_solver("dwave-cpu", seed=42)
result = solver.solve(model)
seed is forwarded to the classical SA backends (dwave-cpu, cuda-gpu,
metal-gpu) and ignored for dwave-qpu, which is physical hardware. Every
example runner exposes this as a --solver flag:
uv run python examples/maxcut/runner.py --solver cuda-gpu
Solver protocol
Any class conforming to xqsa.Solver can drop in:
class Solver(ABC):
@abstractmethod
def solve(self, model: XQMX, **kwargs: Any) -> SolverResult: ...
SolverResult is a frozen dataclass of (sample: XQMX, energy: int, timing: float, metadata: dict). Solvers return the best solution found for the model.
Specification
Authoritative specification: ../spec/xqsa/SPEC.md. The spec is the source of truth; any divergence in this reference implementation is a bug.
Also see
xqvm_py-- pure-Python reference VM.xqffi-- pyo3 FFI bindings to the Rust runtime.xqcp-- constraint-programming DSL that compiles to models this package can sample.xquad-- umbrella meta-package.docs/python-api-walkthrough.md-- end-to-end tour.
License
AGPL-3.0-or-later.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xqsa-0.3.1.tar.gz.
File metadata
- Download URL: xqsa-0.3.1.tar.gz
- Upload date:
- Size: 96.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c27789dfd98ee01fb44c5d6ef2589e2d1038424d41c99541ea7f38c56df6e859
|
|
| MD5 |
9067f8f014eac62ad725a2fda5d4a050
|
|
| BLAKE2b-256 |
aecd6f166b03c3c570a22234a6a722a2fb55bcba4818bc2007c16a8b9eeffbb9
|
File details
Details for the file xqsa-0.3.1-py3-none-any.whl.
File metadata
- Download URL: xqsa-0.3.1-py3-none-any.whl
- Upload date:
- Size: 68.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8c67b7d6d53c3b58558b00081219b74cf7edc51835e44c6e8772ff6a0f53211
|
|
| MD5 |
df882d8f95a62533bf0ae8e7ac15dc2c
|
|
| BLAKE2b-256 |
13e95840616b2dbb306f097f626e04b833e3c8678138fc1da44453cd91c5331b
|