# HXSB — the HexStellar binary problem format

For **large** problems (tens of thousands of variables, millions of coupling terms), encoding the problem as JSON is the
bottleneck: a few million `[i, j, w]` triples become hundreds of megabytes of text and spend real time being parsed. The
**HXSB** format skips that — the problem travels as raw little-endian integers, exactly as the engine reads them. A
million-edge problem that spends a minute becoming JSON in memory becomes a compact binary body read in a blink.

Use HXSB when your payload is large. For everyday problems, plain JSON (`hexstellar solve <cmd>`) is simpler and just as fast.

## Endpoint

```
POST /api/v1/compute/binary
Content-Type: application/octet-stream
Authorization: Bearer <API_KEY>
<the raw HXSB bytes as the request body>
```

Same auth, billing, receipt, and backpressure as the JSON path — only the ingest changes. The response is the usual JSON
envelope with an added `"ingest": "binary"`. Body limit: **128 MB**. Variables: **n ≤ 100 000**. Billing is identical to
the same problem in JSON (density is billed, so a dense binary payload costs the same as the dense JSON one).

## Byte layout (all little-endian)

| offset | bytes | field | value |
|---|---|---|---|
| 0 | 4 | magic | ASCII `HXSB` |
| 4 | 1 | version | `1` |
| 5 | 1 | command code | `1` = optimize (QUBO/Ising), `2` = maxcut |
| 6 | 2 | reserved | `0` |
| 8 | 4 | `n` | number of variables (u32) |
| 12 | 4 | `n_lin` | number of linear terms (u32) |
| 16 | 4 | `n_quad` | number of quadratic terms / edges (u32) |
| 20 | 12 × n_lin | linear block | each: `u32 index` + `i64 weight` |
| … | 16 × n_quad | quadratic block | each: `u32 i` + `u32 j` + `i64 weight` |

Total length is exactly `20 + 12·n_lin + 16·n_quad` bytes — the server validates this and rejects any mismatch.

- **command code = 1 (optimize):** minimize Σ hᵢxᵢ + Σ wᵢⱼxᵢxⱼ. The linear block holds the `hᵢ`; the quadratic block holds `[i, j, wᵢⱼ]`.
- **command code = 2 (maxcut):** `n_lin = 0`; the quadratic block holds the graph edges `[i, j, w]`.

All weights are signed 64-bit integers (`i64`). Indices are unsigned 32-bit (`u32`), `0 ≤ index < n`.

## The easy way: let the CLI do it

You do not have to build HXSB yourself. The CLI encodes your ordinary JSON into HXSB **and** gzip-compresses it for you:

```bash
echo '<PROBLEM_JSON>' | hexstellar solve optimize --binary     # optimize (code 1) or maxcut (code 2), integer weights
```

Build it by hand only if you are writing your own client. The reference encoder:

## Build it (Python, dependency-free — copy this)

```python
import struct

def to_hxsb_optimize(n, linear=None, quadratic=None):
    linear = linear or {}
    quadratic = quadratic or []
    out = bytearray(b"HXSB") + bytes([1, 1, 0, 0])          # magic | v1 | command=1 | reserved
    out += struct.pack("<III", n, len(linear), len(quadratic))
    for idx, h in linear.items():
        out += struct.pack("<Iq", int(idx), int(h))         # u32 index, i64 weight
    for i, j, w in quadratic:
        out += struct.pack("<IIq", int(i), int(j), int(w))  # u32 i, u32 j, i64 weight
    return bytes(out)

def to_hxsb_maxcut(n, edges):
    out = bytearray(b"HXSB") + bytes([1, 2, 0, 0])          # magic | v1 | command=2 | reserved
    out += struct.pack("<III", n, 0, len(edges))
    for i, j, w in edges:
        out += struct.pack("<IIq", int(i), int(j), int(w))
    return bytes(out)
```

## Build it (any language)

1. Write the 8-byte header: the 4 ASCII bytes `H X S B`, then bytes `1`, `command code`, `0`, `0`.
2. Write three little-endian `u32`: `n`, `n_lin`, `n_quad`.
3. For each linear term, write a little-endian `u32` index then a little-endian `i64` weight.
4. For each quadratic term / edge, write two little-endian `u32` (`i`, `j`) then a little-endian `i64` weight.

## Compression (Content-Encoding)

A large HXSB body compresses well. Send it gzip-compressed with the header `Content-Encoding: gzip` and the server
decompresses it before solving (note: a web server's `gzip on`-style directive compresses RESPONSES, not request bodies — the
CLIENT sets `Content-Encoding`). The `hexstellar --binary` CLI does this automatically. `zstd` is under evaluation for even
faster decompression.

## Send it (curl)

```bash
curl -sS https://api.hexstellar.com/api/v1/compute/binary \
  -H "Authorization: Bearer $HEXSTELLAR_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @problem.hxsb
```

## Response

The same envelope as the JSON path, plus `"ingest": "binary"`:

```json
{ "answer": [0, 1, 1, 0, ...], "energy": -12345, "certainty": "heuristic (hypothesis — verify)",
  "receipt": "…", "compute_units": 42, "ingest": "binary" }
```

Read the `certainty` label the same way as everywhere else: **certified** = proven, **heuristic** = a strong hypothesis
to verify. You can recompute the objective from the returned `answer` to check it yourself.

---

© 2025-2026 Brayon Pieske — HexStellar. All rights reserved.


## Encode it yourself — no CLI, standard library only

The layout above is the whole contract. This encoder produces a valid HXSB body for `optimize`
(command byte 1; use 2 for `maxcut` with edges in the quadratic block), gzip-compresses it, and the
curl line ships it — nothing beyond Python's standard library:

```python
import struct, gzip

def hxsb(command_byte, n, linear, quadratic):
    """linear: {index: int_weight} · quadratic: [(i, j, int_weight)] — integer weights only."""
    out = [b"HXSB", struct.pack("<BBH", 1, command_byte, 0), struct.pack("<III", n, len(linear), len(quadratic))]
    out += [struct.pack("<Iq", i, h) for i, h in sorted(linear.items())]
    out += [struct.pack("<IIq", i, j, w) for i, j, w in quadratic]
    return gzip.compress(b"".join(out), 6)

open("problem.hxsb.gz", "wb").write(hxsb(2, 4, {}, [(0, 1, 1), (1, 2, 1), (2, 3, 1), (3, 0, 1)]))
```

```bash
TOK=$(curl -s https://api.hexstellar.com/api/v1/sandbox | python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])')
curl -s -X POST 'https://api.hexstellar.com/api/v1/compute/binary?effort=medium' \
  -H "Authorization: Bearer $TOK" -H 'Content-Type: application/octet-stream' \
  -H 'Content-Encoding: gzip' --data-binary @problem.hxsb.gz
```

The response is the SAME envelope as the JSON lane (`"ingest": "binary"` added) — a heavy solve still
answers 202 with a long-poll `poll` URL. The wire format carries problem terms only — there are no text
fields, so the JSON lane's `tag`/`description` requirements do not apply here.
