weighted-gss
A persistent weighted graph-structured stack.
WeightedGss<S, W> represents a finite collection of stack alternatives. Each stack carries a weight. When stack operations make alternatives denote the same concrete stack, their weights are joined.
The graph representation is private. The Rust API contains semantic stack operations, bounded concrete-stack inspection, and a linear-prefix fast path without exposing graph nodes or canonical representation machinery.
Installation
The latest release is version 0.2.1.
[dependencies]
weighted-gss = "0.2.1"
Python 3.8 or later:
python -m pip install "weighted-gss==0.2.1"
Rust
Stacks are supplied and returned bottom-to-top.
use weighted_gss::{Weight, WeightedGss};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Possibilities(u32);
impl Weight for Possibilities {
fn join(&self, other: &Self) -> Self {
Self(self.0 | other.0)
}
}
let left = WeightedGss::from_stack([0_u32, 1, 2], Possibilities(0b001));
let right = WeightedGss::from_stack([0_u32, 1, 3], Possibilities(0b100));
let stacks = left.merge(&right);
assert_eq!(stacks.top(), None);
assert_eq!(
stacks.tops().collect::<std::collections::BTreeSet<_>>(),
[2, 3].into(),
);
let reduced = stacks.pop_top(&2).push(9);
assert_eq!(
reduced.to_stacks(8).unwrap(),
vec![(vec![0, 1, 9], Possibilities(0b001))],
);
A weight must implement ordinary equality. join must be associative, commutative, and idempotent.
The exported Rust names are:
Weight
WeightedGss
Gss
LinearPrefix
StackLimitExceeded
linear_prefix
for_each_stack_top_first
The core methods are:
- construction:
new,from_stack,from_stacks,from_stacks_with_weight; - alternatives:
merge; - stack operations:
push,pop,popn; - top selection:
top,tops,has_empty_stack,retain_top,retain_empty,pop_top; - weights:
weights,map_weights,filter_map_weights,joined_weight; - observations:
is_empty,max_depth,to_stacks.
to_stacks(max_stacks) returns canonical (stack, weight) pairs and fails with the opaque StackLimitExceeded error rather than returning more than the requested number of distinct stacks.
weights() iterates stored factored weight regions, not concrete stacks. One weight may cover many stacks, equal weights may appear more than once, and count/order are unspecified. map_weights and filter_map_weights transform those regions without materialising stacks; see Semantics and invariants for the representation-independence condition.
Bounded inspection and linear prefixes
for_each_stack_top_first(&gss, max_stacks, visit) visits canonical distinct stacks as borrowed top-first slices. It completes only when the complete result fits within max_stacks.
linear_prefix(&gss) returns a LinearPrefix when the current value has one homogeneous weight and a directly accessible linear top prefix. The hidden floor may still branch. The view supports indexed reads from the top, pushes, bounded pops, and conversion back into a WeightedGss while retaining the unchanged floor.
Neither operation exposes graph nodes, structural paths, or canonical stack-language IDs.
Validation and performance characteristics
Correctness is checked against an explicit stack-to-weight map through deterministic tests, shrinkable property-based operation sequences, and an oracle-backed cargo-fuzz target. The benchmark suite compares the compact representation with an explicit map, an explicit unweighted stack set, and a benchmark-only weight -> stack set ablation.
Representative Criterion medians from one clean Apple M1 Pro run are shown below. They describe these particular shapes and operations, not a machine-independent speed claim.
| Workload | WeightedGss |
Explicit map | What it shows |
|---|---|---|---|
| Persistent fork of a 512-stack value | 174 ns | 141 µs | Immutable structural sharing makes forks cheap |
| Merge across a 20,000-symbol common top prefix | 8.25 µs | 22.6 µs | Compact prefix reuse can avoid copying long stacks |
| Pop 1,024 alternatives that collapse to one stack | 113 µs | 42.6 µs | An explicit map remains faster for this join-heavy operation |
| Construct 1,024 already-explicit weighted stacks | 3.54 ms | 60.5 µs | Bulk construction is not the graph representation's strength |
The intended trade-off is therefore specific: WeightedGss pays construction and representation costs to support persistent evolution and structural sharing. It is not a universally faster replacement for an explicit stack map.
cargo test --all-targets
cargo bench
cargo +nightly fuzz run operation_sequences
See Correctness validation, Benchmarks, and the 2026-07-28 validation record.
Python
from dataclasses import dataclass
from weighted_gss import WeightedGSS
@dataclass(frozen=True)
class Possibilities:
bits: int
def join(self, other: "Possibilities") -> "Possibilities":
return Possibilities(self.bits | other.bits)
stacks = WeightedGSS.from_stacks([
([0, 1, 2], Possibilities(0b001)),
([0, 1, 3], Possibilities(0b100)),
])
assert stacks.tops() == {2, 3}
assert stacks.pop_top(2).to_stacks() == [
([0, 1], Possibilities(0b001)),
]
Python weights need not be hashable. Exceptions raised by join() are propagated normally. See the Python API.
Semantics
Weights and stack operations have an extensional meaning independent of the private graph representation. Rust 1.85 is the declared minimum version. See Semantics and invariants.
Licensed under either Apache-2.0 or MIT, at your option.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file weighted_gss-0.2.1.tar.gz.
File metadata
- Download URL: weighted_gss-0.2.1.tar.gz
- Upload date:
- Size: 50.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
672ba52e571ce5b79354c3990b81431f5715f9edaa9bb5bf1a51a36808e45421
|
|
| MD5 |
97b913f34eb4d136e504331d22639e89
|
|
| BLAKE2b-256 |
e2192fc76ae96c4f2e4c339cebfa2061747c357ec30cd7919727ade933c775a0
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 247.7 kB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
654cc24a91fff8a0f5c79f368cc1686ba9c3961c80bd6bb9d883aeb5c929582a
|
|
| MD5 |
73f210e0bcc6ce08e93c21b98b06eca1
|
|
| BLAKE2b-256 |
97a0880d5adf7d636d239eb4fd5a55fd43583207ab612571950bd2f40d5fe535
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 548.3 kB
- Tags: CPython 3.8+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b82b1965df5368b07de1284d16bf2c2da10e89c7e8fcdd98169415acd691785d
|
|
| MD5 |
0e72dc2375d0dbb27b4fbab65b1ac9e0
|
|
| BLAKE2b-256 |
84593ec7b172b16fe9f75e3232c2b336fde7e41b4a7f8f14f4ef6ae82b412ff3
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 501.6 kB
- Tags: CPython 3.8+, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
943899627d1d3737753dc5d26f4da4bbd030546de756c40ef79b70a55f269838
|
|
| MD5 |
4dfaa546edf23b398213d44381341fb0
|
|
| BLAKE2b-256 |
a697f1e8810e42737d6ab25da87b68b16d8dc579d0a8e316057b00a5e93a738e
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 340.4 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a29a5b1b4839879d244d81bb92108cb7fa8ddaca952fb2a3886653f23bc7a5e9
|
|
| MD5 |
be894a423796b91c7b4a882f08b9cf27
|
|
| BLAKE2b-256 |
5c0852105694d92bbe2172942e858cd22731c5850a1ea8a27cfe90bb47b8a26e
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 324.7 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a2e6f5d4bb3f0bb721a2e92702b51ed77e7fb084fcdc4858074a28b1f0213e9
|
|
| MD5 |
53330887a4e35970e606472116174a74
|
|
| BLAKE2b-256 |
27a246d6b3ed4de909342246c88a8f7454c1920734dc8ae256aeebbb2316171c
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 306.8 kB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7761f004c9a379f82fcd799574440cc4a91cd828fbbe40c2656ea6d00cb3306
|
|
| MD5 |
d923f318b40d77c1fd03f39d27050e1d
|
|
| BLAKE2b-256 |
dc6d123d1cd0c1795f84e832487e1079e826c394955b876ccc7de44f12701451
|
File details
Details for the file weighted_gss-0.2.1-cp38-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: weighted_gss-0.2.1-cp38-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 312.4 kB
- Tags: CPython 3.8+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cac12804175a93765a6bf4f8ecd5c230797cc24e5f91dc107743b343496708f
|
|
| MD5 |
e8af7a9b38a58cf1f1f4824f79a70859
|
|
| BLAKE2b-256 |
3f7b7af48b21dafa290a05e8f8ee18052182a011a57167a190e106dc6891c864
|