Metadata-Version: 2.5
Name: xquad
Version: 0.5.0
Summary: Umbrella meta-package for the XQuad toolchain -- xqffi, xqcp, xqsa under a unified namespace, and the xquad command.
License: AGPL-3.0-or-later
Requires-Python: >=3.13
Requires-Dist: click>=8.2
Requires-Dist: xqcp==0.5.0
Requires-Dist: xqffi==0.5.0
Requires-Dist: xqsa==0.5.0
Provides-Extra: cuda
Requires-Dist: xqsa[cuda]==0.5.0; extra == 'cuda'
Provides-Extra: dwave
Requires-Dist: xqsa[dwave]==0.5.0; extra == 'dwave'
Provides-Extra: metal
Requires-Dist: xqsa[metal]==0.5.0; extra == 'metal'
Provides-Extra: quip
Requires-Dist: xqsa[quip]==0.5.0; extra == 'quip'
Description-Content-Type: text/markdown

# xquad -- Primary user-facing package for the XQuad toolchain

`xquad` is the Python distribution most users should install. It provides the interactive `Program` / `Session` / `RunResult` API, a `VM` wrapper over the Rust interpreter, and re-exports the lower-level peer packages (`xqffi`, `xqcp`, `xqsa`) under a single namespace.

## Install

```sh
pip install xquad
```

Pulls `xqffi`, `xqcp`, and `xqsa` as runtime dependencies.
Peer installs stay valid (`pip install xqffi xqcp xqsa`) if you only
need a subset.

## Interactive usage

Load a program once, run it with different calldata, inspect outputs by slot:

```python
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.

## Full pipeline

Compile a problem via the DSL, execute, sample:

```python
from xquad import cp, sa
from xquad.vm import VM

problem = cp.Problem("MyProblem")
# ... define inputs, model, objective, decoder ...
programs = problem.compile()

vm = VM()
vm.set_output_slots(1)
vm.run(programs.encoder)
model = vm.outputs()[0]

sample = sa.SolverCPU().solve(model).sample
```

Re-exports of peer packages are identity, not copies:

```python
import xquad, xqcp
assert xquad.cp.Problem is xqcp.Problem   # always True
```

So `isinstance` works whether the caller imported directly from the peer or via the umbrella.

## Subnamespaces

| `xquad.*` | Origin | Contents |
|-----------|--------|----------|
| `xquad.program` | first-party | Interactive API -- `Program`, `Session`, `RunResult` |
| `xquad.vm` | first-party | `VM` wrapper over the Rust interpreter: assembles source, keeps calldata and limits across runs |
| `xquad.types` | re-exports `xqffi.vm` | `Domain`, `XqmxModel`, `XqmxSample`, `triu`, `XqvmError` and its faults, VM limits |
| `xquad.asm` | is `xqffi.asm` | `parse_xqasm`, `assemble_source`, `disassemble` |
| `xquad.verifier` | is `xqffi.verifier` | `verify`, `verify_source` |
| `xquad.cp` | is `xqcp` | DSL -- `Problem`, `Types`, expression builders |
| `xquad.sa` | is `xqsa` | Solvers -- `SolverCPU`, `Solver` |

The raw FFI surface stays available as `xqffi.vm.Vm`.

## Also see

- [`xqffi`](https://gitlab.com/quip.network/xquad/-/tree/main/xqffi) -- PyO3 FFI bindings (low-level / conformance).
- [`xqcp`](https://gitlab.com/quip.network/xquad/-/tree/main/xqcp) -- constraint-programming DSL.
- [`xqsa`](https://gitlab.com/quip.network/xquad/-/tree/main/xqsa) -- solver adapters.
- [Running Programs](https://gitlab.com/quip.network/xquad/-/blob/main/docs/book/src/running/README.md) -- end-to-end tour including the Program/Session, `xqffi.vm`, and `xquad.vm` surfaces.

## License

AGPL-3.0-or-later.
