Early public release. The instruction set, binary format, and public API may still change before v1.0. Production use is not recommended yet.
XQuad is a hardware-agnostic toolchain for expressing and running quadratic optimization problems (QUBO / Ising / discrete) across quantum annealers and classical solvers. It ships as three Rust crates plus five Python distributions built around a single virtual-machine specification.
Think of it as LLVM for quadratic models — a common intermediate representation that lets you write a problem once and retarget it to any supported backend.
- Spec-first. Every behaviour is nailed down in
spec/xqvm/SPEC.mdand cross-implementation parity is mechanically enforced: every committed conformance vector runs on both the Rust production VM (xqvm) and the Python reference VM (xqvm_py) in CI; disagreement fails the build. - Embeddable. The Rust core supports
no_std + alloc, so the same VM runs inside WASM runtimes, Substrate pallets, and native binaries. - Interactive. The Python umbrella (
xquad) is REPL and Jupyter-friendly: load a program once, run it with different calldata, inspect outputs by slot. Low-level FFI lives inxqffi; user-facingProgram/Session/RunResultlive inxquad.program.
cargo install xqcli # gives you the `xquad` binarypip install xquad # umbrella — full pipeline
# or pick individual pieces:
pip install xqffi xqcp xqsa # FFI bindings + DSL + solversThree Rust crates on crates.io:
| Crate | Binary | Description |
|---|---|---|
xqvm |
– | X-Quadratic Virtual Machine interpreter, bytecode codec, opcode table (no_std + alloc) |
xqasm |
– | .xqasm text-format assembler |
xqcli |
xquad |
Unified CLI — xquad run / asm / dsm |
Five Python distributions on PyPI:
| Package | Description |
|---|---|
xqffi |
PyO3 FFI bindings for xqvm + xqasm (xqffi.vm, xqffi.asm) |
xqvm_py |
Pure-Python reference VM (conformance oracle) |
xqcp |
Constraint-programming DSL that compiles to .xqasm |
xqsa |
Solver adapters (dwave-samplers; pluggable solver interface) |
xquad |
Umbrella meta-package with interactive Program / Session / RunResult API |
The one Rust package without a crates.io artefact is the xqffi pyo3
crate itself — it ships as the xqffi PyPI wheel rather than a reusable
Rust library.
; add.xqasm — push two integers and add them
PUSH 10
PUSH 32
ADD
HALTxquad asm add.xqasm -o add.xqb && xquad run add.xqbThe recommended user-facing surface is xquad.program.Program +
Session + RunResult. Load once, run many times with different
calldata, inspect outputs by slot:
from xquad.program import Program
program = Program.from_source("""
PUSH 0
INPUT r0
PUSH 1
INPUT r1
LOAD r0
LOAD r1
ADD
STOW r2
PUSH 0
OUTPUT r2
HALT
""")
session = program.session(output_slots=1)
session.set_calldata([40, 2])
result = session.run()
assert dict(result.outputs) == {0: 42}Program.load(bytes) takes wire-format bytecode; Session.run()
returns a RunResult with dict-keyed outputs (unset slots present as
None), residual stack, and step count. See
docs/python-api-walkthrough.md for
the full tour.
For conformance harnesses and one-shot execution, the raw
xqffi.vm.Vm is still available directly:
from xqffi.asm import assemble_source
from xqffi.vm import Vm
bytecode = assemble_source(src)
v = Vm()
v.set_calldata([40, 2])
v.set_output_slots(1)
v.run(bytecode)
assert v.outputs() == [42]The xquad.vm.VM class offers a middle tier — a unified wrapper with
backend dispatch (VMBackend.RUST / VMBackend.PYTHON) that accepts
.xqasm source and normalises types across the two interpreters.
examples/tsp/ shows a full Travelling Salesman Problem
driven from the xqcp DSL through the VM and xqsa solver, runnable on
either the Python reference VM or the Rust VM:
uv run --no-sync python examples/tsp/runner.py --seed 42
uv run --no-sync python examples/maxcut/runner.py --seed 42 --interpreter rust
# Run every example on both interpreters, diff against golden.json:
make example-smokeXQuad is a stack-based interpreter with a 256-slot register file. Registers
hold typed values — integers, integer vectors, QUBO/Ising models
(XqmxModel), and candidate solutions (XqmxSample). A dedicated loop stack
drives RANGE/ITER iteration.
The opcode table is declared once in xqvm/src/bytecode/types/table.rs via
the opcodes! x-macro; conformance/opcodes.yaml is the machine-readable
mirror that all three representations (YAML, Rust macro, xqvm_py.opcodes)
are checked against at build time and in CI
(scripts/check-opcode-parity.py).
The binary format is a bare instruction stream — no header, no constant pool — just an opcode byte followed by its operands in big-endian byte order.
See docs/bytecode-semantics.md for
instruction-by-instruction semantics and
spec/xqvm/SPEC.md for the normative spec.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # stable Rust
make deps # dev toolsmake xquadThis syncs the Python workspace (xqvm_py, xqcp, xqsa, xqffi,
xquad) into .venv/, builds the xqffi pyo3 extension via maturin,
writes a workspace .pth so scripts anywhere in the repo can
import xqcp / xqsa / xqvm_py / xqffi / xquad naturally, and
installs the xquad CLI binary under ~/.cargo/bin/.
Open a REPL with everything ready:
make replmake all # fmt + lint + test (what CI runs)
make conformance # cross-impl parity suite (Rust + Python)See CONTRIBUTING.md for the development workflow, commit conventions, and DCO sign-off requirements. Agent guidelines for AI coding assistants are in AGENTS.md; cutting a release is documented in RELEASING.md.
Licensed under the GNU Affero General Public License v3.0 or later.