weighted-gss 0.2.2

Persistent weighted graph-structured stacks
Documentation
# Python API

The Python package exposes the ordinary semantic API of the Rust implementation. Wheels use CPython's stable ABI and support Python 3.8 and later. Python wrapper instances are thread-affine; create and use a `WeightedGSS` on the same Python thread.

```python
from weighted_gss import WeightedGSS, __version__
```

## Values and weights

Stacks are supplied and returned bottom-to-top. Stack values must be immutable and hashable for as long as the GSS exists.

A weight is either `None`, for unweighted use, or an object implementing:

```python
def join(self, other): ...
```

`join` must be associative, commutative, and idempotent. Weights do not need to be hashable. Exceptions raised by `join` or stack-value equality are propagated normally to Python.

## Construction

```python
empty = WeightedGSS()
one = WeightedGSS.from_stack([0, 1, 2], weight)
weighted = WeightedGSS.from_stacks([
    ([0, 1, 2], weight_a),
    ([0, 1, 3], weight_b),
])
unweighted = WeightedGSS.from_unweighted([[0, 1, 2], [0, 1, 3]])
updated = weighted.with_stack([0, 4], another_weight)
```

All operations are persistent: the original value remains usable.

## Stack operations

- `push(value)` pushes onto every represented stack.
- `pop()` removes one value and discards empty alternatives.
- `popn(count)` removes `count` values and discards underflowing alternatives.
- `merge(other)` and `merge_all(values)` combine alternatives.

## Top frontier

- `tops()` returns the distinct non-empty top values.
- `top()` returns the unique top value, and raises `ValueError` when the frontier is empty or ambiguous, or when an empty-stack alternative is also present. This allows `None` itself to remain a valid stack symbol.
- `has_empty_stack()` reports an empty-stack alternative.
- `retain_top(value)` selects matching alternatives without popping.
- `retain_empty()` selects the empty stack.
- `pop_top(value)` selects and pops one top branch.
- `pop_branches()` returns `(top, remainder)` pairs for every non-empty top branch.

## Weights and inspection

- `joined_weight()` joins every represented path weight and raises `ValueError` when the GSS is empty.
- `empty_weight()` returns the joined weight of the empty stack and raises `ValueError` when no empty stack exists.

Both methods may legitimately return `None` for an unweighted GSS; absence is therefore reported by an exception rather than overloaded onto `None`.
- `is_empty()` and Boolean conversion test whether alternatives exist.
- `max_depth()` returns the maximum stack depth.
- `to_stacks(max_stacks=4096)` materialises canonical `(stack, weight)` pairs. It raises `OverflowError` rather than returning more than the requested number of distinct stacks.

The Python binding intentionally exposes only semantic stack operations. Raw graph structure and implementation-specific parser machinery are not part of the supported API.