Skip to content

quicopt.wire

wire

quicopt.wire — a structured Program → versioned wire bytes.

A hand-rolled, stdlib-only encoder of Quicopt's wire schema (the deliberate "no protoc" choice: the schema is small and frozen). Crucially it is byte-identical to what the Quicopt service expects: the same canonical ordering of the order-free dict tables (so equal Programs encode to equal bytes), the same always-emit-the- oneof-case rule (so Const(0.0) survives), and the same always-emit scalars (VarDecl.start, ParamEntry.value even when 0.0 — which proto3's default-omission would drop). That exactness is the encoder's correctness property (see tests/test_wire_golden.py).

Wire format crib (proto3): a field is tag = (number<<3 | wiretype) then the payload; wiretype 0=varint, 1=fixed64 (doubles, little-endian), 2=length-delimited (strings, embedded messages, repeated). Embedded messages are length-delimited.

encode

encode(prog: Program) -> bytes

Serialize a Program to versioned (v1) wire bytes.

The top-level message in schema order: index sets (1), indexed sets (2), param tables (3), variable declarations (4), the objective expression (5), the sense string (6), constraints (7), and the fix pins (8). The order-free tables (indexed_sets, params, fix) are emitted in sorted-key order so equal Programs encode to equal bytes — the byte-identity property the golden test pins.

Parameters:

Name Type Description Default
prog Program

The :class:~quicopt.ir.Program to serialize.

required

Returns:

Name Type Description
bytes bytes

The wire message, deterministic and byte-identical to what the

bytes

Quicopt service decodes for the same model.

Source code in src/quicopt/wire.py
def encode(prog: Program) -> bytes:
    """Serialize a ``Program`` to versioned (v1) wire bytes.

    The top-level message in schema order: index sets (1), indexed sets (2),
    param tables (3), variable declarations (4), the objective expression (5), the
    sense string (6), constraints (7), and the ``fix`` pins (8). The order-free
    tables (``indexed_sets``, ``params``, ``fix``) are emitted in sorted-key order
    so equal Programs encode to equal bytes — the byte-identity property the golden
    test pins.

    Args:
        prog: The :class:`~quicopt.ir.Program` to serialize.

    Returns:
        bytes: The wire message, deterministic and byte-identical to what the
        Quicopt service decodes for the same model.
    """
    io = BytesIO()
    for s in prog.sets:
        _wmsg(io, 1, _msg(lambda b, s=s: _enc_index_set(b, s)))
    for name in sorted(prog.indexed_sets.keys()):
        _wmsg(io, 2, _msg(lambda b, name=name: _enc_indexed_set(b, name, prog.indexed_sets[name])))
    for name in sorted(prog.params.keys()):
        _wmsg(io, 3, _msg(lambda b, name=name: _enc_param_table(b, name, prog.params[name])))
    for vd in prog.vars:
        _wmsg(io, 4, _msg(lambda b, vd=vd: _enc_var_decl(b, vd)))
    _wmsg(io, 5, _expr_msg(prog.objective))
    _wstr(io, 6, prog.sense)
    for c in prog.constraints:
        _wmsg(io, 7, _msg(lambda b, c=c: _enc_constraint(b, c)))
    for key in sorted(prog.fix.keys(), key=lambda k: (k[0], _idxkey(k[1]))):
        var, idx = key
        def build(b, var=var, idx=idx, key=key):
            _wstr(b, 1, var)
            _wmsg(b, 2, _idx_msg(idx))
            _wdouble(b, 3, prog.fix[key])
        _wmsg(io, 8, _msg(build))
    return io.getvalue()

encode_params

encode_params(params: dict) -> bytes

Serialize just the Param tables as a standalone ParamData message.

This supports rebinding parameters over the wire without resending the model: graph the Program once, then emit one ParamData per instance. Tables are emitted in sorted-key order to stay byte-canonical.

Parameters:

Name Type Description Default
params dict

A mapping table name → (index tuple → double) of the parameter values to send.

required

Returns:

Name Type Description
bytes bytes

The encoded ParamData message.

Source code in src/quicopt/wire.py
def encode_params(params: dict) -> bytes:
    """Serialize just the ``Param`` tables as a standalone ``ParamData`` message.

    This supports rebinding parameters over the wire without resending the model:
    graph the ``Program`` once, then emit one ``ParamData`` per instance. Tables are
    emitted in sorted-key order to stay byte-canonical.

    Args:
        params: A mapping ``table name → (index tuple → double)`` of the parameter
            values to send.

    Returns:
        bytes: The encoded ``ParamData`` message.
    """
    io = BytesIO()
    for name in sorted(params.keys()):
        _wmsg(io, 1, _msg(lambda b, name=name: _enc_param_table(b, name, params[name])))
    return io.getvalue()