Skip to main content

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

License

AGPL-3.0-or-later.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xqsa-0.3.1.tar.gz (96.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xqsa-0.3.1-py3-none-any.whl (68.5 kB view details)

Uploaded Python 3

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

Hashes for xqsa-0.3.1.tar.gz
Algorithm Hash digest
SHA256 c27789dfd98ee01fb44c5d6ef2589e2d1038424d41c99541ea7f38c56df6e859
MD5 9067f8f014eac62ad725a2fda5d4a050
BLAKE2b-256 aecd6f166b03c3c570a22234a6a722a2fb55bcba4818bc2007c16a8b9eeffbb9

See more details on using hashes here.

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

Hashes for xqsa-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c8c67b7d6d53c3b58558b00081219b74cf7edc51835e44c6e8772ff6a0f53211
MD5 df882d8f95a62533bf0ae8e7ac15dc2c
BLAKE2b-256 13e95840616b2dbb306f097f626e04b833e3c8678138fc1da44453cd91c5331b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page