D-Wave QPU
SolverDWave submits the model to a physical D-Wave Advantage
quantum annealer over the D-Wave Leap cloud API. This page is derived
from
xqsa/inprocess/dwave.py
and spec/xqsa/*; no D-Wave Leap account was available while writing
it, so nothing on this page was run.
Credentials
Requires the [dwave] extra:
pip install xqsa[dwave]
SolverDWave() resolves an API token from the token= constructor
argument first, then the DWAVE_API_TOKEN environment variable; with
neither set, construction raises ValueError. An optional endpoint=
or DWAVE_API_ENDPOINT overrides the default Leap API URL.
import os
os.environ["DWAVE_API_TOKEN"] = "your-leap-token"
from xqsa import SolverDWave
from xquad.types import XqmxModel
model = XqmxModel.binary(4)
model.set_linear(0, -1)
model.set_quad(0, 1, 2)
solver = SolverDWave() # auto-selects a Pegasus-topology Advantage system
result = solver.solve(model)
print(result.metadata["params"]["solver"]) # e.g. "Advantage_system5.4"
print(result.metadata["params"]["qpu_timing"]) # QPU timing breakdown from Leap
Pass solver="Advantage_system5.4" to target a specific system instead
of the default Pegasus-topology filter. SolverDWave also takes
mode, which is "qpu" and has no other value yet; hybrid modes are
not available.
What Embedding Means
A D-Wave Advantage chip is not fully connected: each physical qubit
couples only to a fixed, small set of neighbours defined by its
Pegasus topology. Your model’s coupling graph is almost never a
subgraph of that hardware graph directly. SolverDWave wraps the
sampler in dwave.system.EmbeddingComposite, which finds a
minor embedding: each logical variable maps to a chain of one or more
physical qubits, wired together so the chain acts as a single variable
by strongly coupling its members (chain_strength).
Problem size on real hardware is not simply “how many variables.”
A densely coupled model needs longer chains to embed, chains
compete for the chip’s limited qubits, and a model that does not embed
at all raises rather than silently degrading. EmbeddingComposite
handles the search automatically; there is no separate embedding step
to call in xqsa. Contrast this with Quip Network,
where SolverQuip requires an exact subgraph match onto a fixed
topology and refuses to do this chain-based embedding at all.
Parameters
| Parameter | Constructor default | Meaning |
|---|---|---|
token | None (env fallback) | Leap API token |
endpoint | None (env fallback) | Leap API endpoint override |
solver | None (Pegasus filter) | Specific Advantage system name |
num_reads | 100 | Annealing runs read back from the chip |
annealing_time | 20 | Microseconds per anneal |
chain_strength | None (not passed) | Coupling that holds each chain together |
auto_scale | None (not passed) | Whether Ocean rescales coefficients to the chip’s range |
Everything except token, endpoint, and solver is overridable per
call: solver.solve(model, annealing_time=100, chain_strength=2.0).
chain_strength and auto_scale are the only Ocean sampling
parameters xqsa forwards to the sampler, and only when set. Any other
keyword raises TypeError instead of reaching the sampler unchecked.
How a QPU Result Differs
The result shape is the same SolverResult every backend returns, but
two things are specific to this backend. result.energy is still
recomputed by xqsa in exact integer arithmetic from the returned
sample – the chip’s own reported energy is never trusted directly –
but the sample search itself ran on physical hardware subject to analog
noise and the embedding above, not an exact digital simulation. And
result.metadata["params"] carries QPU-specific detail that the local
backends do not report at all.
metadata has the same three keys as every backend except quip:
| Key | On this backend |
|---|---|
seed | Always None; there is no seed on physical hardware |
reads | num_reads for the call |
params | mode, solver, qpu_timing, annealing_time, raw_energy, plus chain_strength and auto_scale when forwarded |
params["solver"] names the physical Advantage system that ran the
job. params["qpu_timing"] is the timing breakdown Leap returns – a
dict when present, with keys that come from Leap and are not fixed by
xqsa, or None when the sampler response carries no timing info at
all. params["raw_energy"] is the chip’s own reported energy,
informational only.
result.timing covers the whole call, including converting the model
to a BQM and the sample back, not only the round trip to Leap. See
Solving Overview for the shape every
backend shares.