| Crates.io | wass |
| lib.rs | wass |
| version | 0.1.1 |
| created_at | 2026-01-18 16:32:30.146665+00 |
| updated_at | 2026-01-19 15:23:28.059188+00 |
| description | Optimal transport: Wasserstein distance, Sinkhorn algorithm, and Sinkhorn divergence |
| homepage | https://github.com/arclabs561/wass |
| repository | https://github.com/arclabs561/wass |
| max_upload_size | |
| id | 2052626 |
| size | 217,650 |
Optimal transport primitives for geometry-aware distribution comparison. Implements the Sinkhorn algorithm for entropy-regularized OT, including unbalanced transport for robust partial matching.
Invariants (must never change):
f32.sinkhorn_divergence_same_support is the canonical de-biased divergence; it guarantees non-negativity (modulo float noise) and symmetry.*_with_convergence methods return Err if the residual does not fall below tol within max_iter; they do not return a partial result silently.Support / Dependencies:
ndarray::Array1 (masses) and Array2 (costs).Exports:
sinkhorn: Standard dense OT.sinkhorn_divergence_same_support: MMD-like geometric divergence.wasserstein_1d: $O(n)$ exact solver for 1D.Dual-licensed under MIT or Apache-2.0.
use wass::{wasserstein_1d, sinkhorn, sinkhorn_divergence_same_support};
use ndarray::array;
// 1D Wasserstein (fast, closed-form)
let a = [0.0, 0.25, 0.5, 0.25];
let b = [0.25, 0.5, 0.25, 0.0];
let w1 = wasserstein_1d(&a, &b);
// General transport with Sinkhorn
let cost = array![[0.0, 1.0], [1.0, 0.0]];
let a = array![0.5, 0.5];
let b = array![0.5, 0.5];
let (plan, distance) = sinkhorn(&a, &b, &cost, 0.1, 100);
// Sinkhorn Divergence (debiased; requires same-support cost matrix)
let div = sinkhorn_divergence_same_support(&a, &b, &cost, 0.1, 1000, 1e-4).unwrap();
sparse module).Run these to see OT in action:
Robust Document Alignment: Shows how unbalanced OT aligns core topics while ignoring outliers (headers/footers/typos).
cargo run -p wass --example noisy_ocr_matching
Mass Mismatch: Shows how divergence scales with the unbalanced penalty parameter.
cargo run -p wass --example unbalanced_sinkhorn_mass_mismatch
Balanced Divergence:
cargo run -p wass --example sinkhorn_divergence_same_support
| Function | Use Case | Complexity |
|---|---|---|
wasserstein_1d |
1D distributions | O(n) |
sinkhorn |
General transport (dense) | O(n^2 x iter) |
sinkhorn_with_convergence |
With early stopping | O(n^2 x iter) |
sinkhorn_divergence_same_support |
Debiased divergence (same support) | O(n^2 x iter) |
sinkhorn_divergence_general |
Debiased divergence (different supports) | O(mn x iter) |
unbalanced_sinkhorn_divergence_general |
Robust comparison (different supports) | O(mn x iter) |
sparse::solve_semidual_l2 |
Sparse transport (L2) | O(n^2 x iter) |
sliced_wasserstein |
High-dim approx | O(n_proj x n log n) |
Note: sinkhorn_divergence is deprecated; it only computes a true divergence when the
cost is square. Use the explicit *_same_support / *_general variants instead.