diff --git a/crates/ruvector-mincut/Cargo.toml b/crates/ruvector-mincut/Cargo.toml index 0bcc0ba047..4739d4b35f 100644 --- a/crates/ruvector-mincut/Cargo.toml +++ b/crates/ruvector-mincut/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true authors.workspace = true repository.workspace = true readme = "README.md" -description = "World's first subpolynomial dynamic min-cut: self-healing networks, AI optimization, real-time graph analysis" +description = "Dynamic global minimum cut with an exact sparse Stoer-Wagner baseline and experimental graph algorithms" keywords = ["graph", "minimum-cut", "network-analysis", "self-healing", "dynamic-graph"] categories = ["algorithms", "data-structures", "science", "mathematics", "simulation"] homepage = "https://ruv.io" @@ -44,7 +44,7 @@ mockall = { workspace = true } default = ["exact", "approximate"] full = ["exact", "approximate", "integration", "monitoring", "simd", "agentic", "jtree", "tiered", "canonical"] exact = [] # Exact minimum cut algorithm -approximate = [] # (1+ε)-approximate algorithm +approximate = [] # Legacy compatibility flag; ApproxMinCut is currently always compiled integration = ["ruvector-graph"] # GraphDB integration monitoring = [] # Real-time monitoring with callbacks simd = ["ruvector-core/simd"] diff --git a/crates/ruvector-mincut/README.md b/crates/ruvector-mincut/README.md index 34a28d39b2..8f4a3aef7d 100644 --- a/crates/ruvector-mincut/README.md +++ b/crates/ruvector-mincut/README.md @@ -8,7 +8,7 @@ **Continuous structural integrity as a first-class signal for systems that must not drift.** -*Dynamic min-cut for self-healing infrastructure, AI agent coordination, and safety-critical systems.* +*Dynamic global minimum cuts and experimental graph algorithms.* --- @@ -16,7 +16,7 @@ Every complex system — your brain, the internet, a hospital network, an AI model — is a web of connections. Understanding where these connections are weakest unlocks the ability to **heal, protect, and optimize** at speeds never before possible. -**RuVector MinCut** is a production-oriented implementation of recent fully-dynamic min-cut research, including the December 2025 breakthrough ([arXiv:2512.13105](https://arxiv.org/abs/2512.13105)) by El-Hayek, Henzinger, and Li that achieves deterministic exact subpolynomial updates for cuts above polylogarithmic size. +`DynamicMinCut` maintains exact global cuts using a sparse Stoer-Wagner solver when its cached cut must be recomputed. That recomputation is polynomial. Other modules explore dynamic and sparsified approaches; this crate has not established the update bound of [arXiv:2512.13105](https://arxiv.org/abs/2512.13105), an `(1+ε)` guarantee for its experimental sparsifier, or suitability for safety-critical decisions. The performance numbers below are historical observations on specific test graphs, not general complexity bounds. --- @@ -31,7 +31,7 @@ The human brain contains 86 billion neurons with trillions of connections. Under - **Understand drug effects** by tracking how medications strengthen or weaken neural circuits - **Map disease spread** in biological networks to find intervention points -Traditional algorithms take hours to analyze a single brain scan. RuVector MinCut can track changes in milliseconds as new data streams in. +These are potential research applications. This crate has not been validated on clinical brain scans. ### Networking: Self-Healing Infrastructure @@ -55,7 +55,7 @@ Modern AI isn't just neural networks — it's networks of networks, agents, and ## The December 2025 Breakthrough -RuVector MinCut implements [arXiv:2512.13105](https://arxiv.org/abs/2512.13105) — deterministic exact fully-dynamic min-cut in subpolynomial time: +The result in [arXiv:2512.13105](https://arxiv.org/abs/2512.13105) motivates research in this crate. The following properties describe the paper, not guarantees of `DynamicMinCut`: | Property | What It Means | Why It Matters | |----------|---------------|----------------| @@ -85,18 +85,18 @@ RuVector MinCut implements [arXiv:2512.13105](https://arxiv.org/abs/2512.13105) ## ✨ What Makes This Different -This library delivers deterministic, exact, fully-dynamic min-cut based on recent theoretical advances. +`DynamicMinCut` accepts insertions and deletions and returns an exact cut for finite, nonnegative edge weights. It may run a full polynomial-time solver after an update. ### Core Properties | Property | What It Means | Measured Performance | |----------|---------------|---------------------| -| **Always Right** | Mathematically correct — no dice rolls | Essential for safety-critical systems | +| **Exact cut** | Sparse Stoer-Wagner recomputation | Subject to the supported graph and weight model | | **Perfectly Predictable** | Same input = same output | Essential for debugging and auditing | -| **Handles Any Change** | Insertions and deletions equally fast | Real networks grow AND shrink | -| **Scales Subpolynomially** | Update time grows slower than any polynomial | n^0.12 scaling across tested ranges (100–1600 vertices) | +| **Dynamic updates** | Insertions and deletions | Recomputations can be polynomial | +| **Cached queries** | Read the last cut value | Update cost depends on graph and cut changes | -### Production-Ready Extensions +### Additional Experimental Components | Feature | What It Does | Real-World Benefit | |---------|--------------|-------------------| @@ -138,7 +138,7 @@ Or add to `Cargo.toml`: ```toml [dependencies] -ruvector-mincut = "0.1" +ruvector-mincut = "2.3" ``` ### 30-Second Example @@ -160,7 +160,7 @@ fn main() -> Result<(), Box> { // Query minimum cut - O(1) after build println!("Min cut: {}", mincut.min_cut_value()); // Output: 2 - // Dynamic update - O(n^{o(1)}) amortized! + // Dynamic update; may recompute the exact cut. mincut.insert_edge(3, 4, 2.0)?; mincut.delete_edge(2, 3)?; @@ -212,7 +212,7 @@ Learn to build networks that think for themselves. These examples demonstrate se | Example | Description | Run Command | |---------|-------------|-------------| -| **Subpoly Benchmark** | Verify subpolynomial n^0.12 scaling | `cargo run -p ruvector-mincut --release --example subpoly_bench` | +| **Subpoly Benchmark** | Explore update scaling on the example's graph family | `cargo run -p ruvector-mincut --release --example subpoly_bench` | | **Temporal Attractors** | Networks that evolve toward stable states | `cargo run -p ruvector-mincut --release --example temporal_attractors` | | **Strange Loop** | Self-aware systems that monitor and repair themselves | `cargo run -p ruvector-mincut --release --example strange_loop` | | **Causal Discovery** | Trace cause-and-effect chains in failures | `cargo run -p ruvector-mincut --release --example causal_discovery` | @@ -230,8 +230,8 @@ See the full [Examples Guide](https://github.com/ruvnet/ruvector/tree/main/examp ### Core Features -- ⚡ **Subpolynomial Updates**: O(n^{o(1)}) amortized time per edge insertion/deletion -- 🎯 **Exact & Approximate Modes**: Choose between exact minimum cut or (1+ε)-approximation +- ⚡ **Dynamic Exact Cuts**: `DynamicMinCut` caches a cut and runs the polynomial exact solver when needed +- 🎯 **Separate Experimental Approximation**: `ApproxMinCut` explores sparsification; `MinCutBuilder::approximate()` does not switch solvers - 🔗 **Advanced Data Structures**: Link-Cut Trees and Euler Tour Trees for dynamic connectivity - 📊 **Graph Sparsification**: Benczúr-Karger and Nagamochi-Ibaraki algorithms - 🔔 **Real-Time Monitoring**: Event-driven notifications with configurable thresholds @@ -240,13 +240,13 @@ See the full [Examples Guide](https://github.com/ruvnet/ruvector/tree/main/examp ### December 2025 Breakthrough -This crate implements the **first deterministic exact fully-dynamic minimum cut algorithm** based on the December 2025 paper ([arxiv:2512.13105](https://arxiv.org/abs/2512.13105)): +The December 2025 paper ([arxiv:2512.13105](https://arxiv.org/abs/2512.13105)) motivates these research components. Their presence does not establish that the paper's full algorithm or update-time proof has been implemented: | Component | Status | Description | |-----------|--------|-------------| -| **SubpolynomialMinCut** | ✅ **NEW** | Verified n^0.12 scaling — true subpolynomial updates | +| **SubpolynomialMinCut** | Research | Hierarchy and recourse experiments; no proven subpolynomial update bound | | **MinCutWrapper** | ✅ Complete | O(log n) bounded-range instances with geometric factor 1.2 | -| **BoundedInstance** | ✅ Complete | Production implementation with strategic seed selection | +| **BoundedInstance** | Implemented | Bounded-range instance with strategic seed selection | | **DeterministicLocalKCut** | ✅ Complete | BFS-based local minimum cut oracle (no randomness) | | **CutCertificate** | ✅ Complete | Compact witness using RoaringBitmap | | **ClusterHierarchy** | ✅ Integrated | O(log n) levels of recursive decomposition | @@ -278,13 +278,13 @@ Optimized for deployment on agentic chips with 256 WASM cores × 8KB memory each | **CoreExecutor** | ✅ Complete | Per-core execution with SIMD boundary methods | | **AgenticAnalyzer** | ✅ Integrated | Graph distribution across cores | -### Paper Algorithm Implementation (arxiv:2512.13105) +### Research Components Inspired by arxiv:2512.13105 -Full implementation of the December 2025 breakthrough paper components: +These components are present, but no end-to-end implementation or complexity proof has been verified for the December 2025 paper: | Component | Status | Description | |-----------|--------|-------------| -| **SubpolynomialMinCut** | ✅ **NEW** | Integrated module with verified n^0.12 scaling | +| **SubpolynomialMinCut** | Research | Integrated module; asymptotic scaling unverified | | **DeterministicLocalKCut** | ✅ Complete | Color-coded DFS with 4-color family (Theorem 4.1) | | **GreedyForestPacking** | ✅ Complete | k edge-disjoint forests for witness guarantees | | **EdgeColoring** | ✅ Complete | (a,b)-coloring families for deterministic enumeration | @@ -293,12 +293,12 @@ Full implementation of the December 2025 breakthrough paper components: | **ThreeLevelHierarchy** | ✅ Complete | Expander → Precluster → Cluster decomposition | | **O(log^{1/4} n) Hierarchy** | ✅ Complete | Multi-level cluster hierarchy with φ-expansion | | **MirrorCut Tracking** | ✅ Complete | Cross-expander minimum cut maintenance | -| **Recourse Tracking** | ✅ Complete | Verifies subpolynomial update bounds | +| **Recourse Tracking** | Implemented | Records observed update recourse; does not prove an asymptotic bound | | **Incremental Updates** | ✅ Complete | Propagates changes without full rebuild | -### ✅ Verified Subpolynomial Performance +### Historical Scaling Observation -Benchmark results confirming **true subpolynomial complexity**: +One example run reported the following timings. The graph family, sample size, and finite range do not establish asymptotic complexity or a general update-time bound: ``` === Complexity Verification === @@ -310,7 +310,7 @@ Size Avg Update (μs) Scaling 800 870,120 n^0.50 1600 816,950 n^-0.09 -Overall scaling: n^0.12 (SUBPOLYNOMIAL ✓) +Fitted exponent on this run: n^0.12 (not a complexity guarantee) Avg recourse: ~4.0 (constant-like) ``` @@ -326,10 +326,10 @@ Beyond the core December 2025 paper, we implement cutting-edge algorithms from r | Component | Paper | Description | |-----------|-------|-------------| | **PolylogConnectivity** | [arXiv:2510.08297](https://arxiv.org/abs/2510.08297) | O(log³ n) expected worst-case dynamic connectivity | -| **ApproxMinCut** | [SODA 2025, arXiv:2412.15069](https://arxiv.org/abs/2412.15069) | (1+ε)-approximate min-cut for ALL cut sizes | +| **ApproxMinCut** | Inspired by [SODA 2025, arXiv:2412.15069](https://arxiv.org/abs/2412.15069) | Experimental sparsification; no verified (1+ε) guarantee | | **CacheOptBFS** | — | Cache-optimized traversal with prefetching hints | -#### SubpolynomialMinCut — True O(n^{o(1)}) Updates (NEW) +#### SubpolynomialMinCut — Research API ```rust use ruvector_mincut::{SubpolynomialMinCut, SubpolyConfig}; @@ -346,20 +346,20 @@ mincut.build(); // Query min cut - O(1) println!("Min cut: {}", mincut.min_cut_value()); -// Dynamic updates - O(n^{o(1)}) amortized +// Dynamic updates; the asymptotic bound is not established here. mincut.insert_edge(500, 750, 2.0).unwrap(); mincut.delete_edge(250, 251).unwrap(); -// Verify subpolynomial recourse +// Inspect observed recourse against a heuristic threshold. let stats = mincut.recourse_stats(); println!("Avg recourse: {:.2}", stats.amortized_recourse()); println!("Is subpolynomial: {}", stats.is_subpolynomial(1000)); ``` **Key Features:** -- **Verified n^0.12 scaling** — benchmark-confirmed subpolynomial updates +- **Measured example run** — an n^0.12 fitted exponent over five sizes, without a general complexity guarantee - **O(log^{1/4} n) hierarchy** — multi-level cluster decomposition -- **Recourse tracking** — verifies complexity bounds at runtime +- **Recourse tracking** — records observed changes; it does not verify a complexity proof - **Tree packing witness** — deterministic cut certification #### Polylogarithmic Worst-Case Connectivity (October 2025) @@ -379,7 +379,7 @@ assert!(conn.connected(0, 2)); // O(log n) worst-case query - Hierarchical level structure with edge sparsification - Automatic replacement edge finding on tree edge deletion -#### Approximate Min-Cut for All Sizes (SODA 2025) +#### Experimental Approximate Min-Cut ```rust use ruvector_mincut::ApproxMinCut; @@ -394,11 +394,9 @@ println!("Value: {}, Bounds: [{}, {}]", result.value, result.lower_bound, result.upper_bound); ``` -**Key Features:** -- (1+ε)-approximation for ANY cut size (not just small cuts) -- Spectral sparsification with effective resistance sampling -- O(n log n / ε²) sparsifier size -- Stoer-Wagner on sparsified graph for efficiency +This separate `ApproxMinCut` API uses heuristic edge sampling and Stoer-Wagner on +the sampled graph. The returned bounds are calculated from the requested ε; +they have not been validated as rigorous error bounds for all graph families. **Test Coverage**: 448+ tests passing (30+ specifically for paper algorithms) @@ -415,13 +413,13 @@ ruvector-mincut = "0.1" ```toml [dependencies] -ruvector-mincut = { version = "0.1", features = ["monitoring", "simd"] } +ruvector-mincut = { version = "2.3", features = ["monitoring", "simd"] } ``` Available features: - **`exact`** (default): Exact minimum cut algorithm -- **`approximate`** (default): (1+ε)-approximate algorithm with graph sparsification +- **`approximate`** (default): legacy compatibility flag; `ApproxMinCut` is currently compiled regardless, and this flag does not change `DynamicMinCut`'s solver - **`monitoring`**: Real-time event monitoring with callbacks - **`integration`**: GraphDB integration for ruvector-graph - **`simd`**: SIMD optimizations for vector operations @@ -462,15 +460,19 @@ let new_cut = mincut.delete_edge(2, 3)?; println!("After deletion: {}", new_cut); ``` -### Approximate Mode +### Legacy Approximate Builder Option -For large graphs, use the approximate algorithm: +For compatibility, `.approximate(ε)` still records the requested ε in the +configuration. `DynamicMinCut` continues to run the exact solver and reports +`is_exact: true` with `approximation_ratio: 1.0`. It does not offer a faster +approximate path. Use the separate `ApproxMinCut` research API to experiment +with sparsification. ```rust use ruvector_mincut::MinCutBuilder; let mincut = MinCutBuilder::new() - .approximate(0.1) // 10% approximation (1+ε) + .approximate(0.1) // legacy request; still computes an exact cut .with_edges(vec![ (1, 2, 1.0), (2, 3, 1.0), @@ -479,9 +481,9 @@ let mincut = MinCutBuilder::new() .build()?; let result = mincut.min_cut(); -assert!(!result.is_exact); -assert_eq!(result.approximation_ratio, 1.1); -println!("Approximate min cut: {}", result.value); +assert!(result.is_exact); +assert_eq!(result.approximation_ratio, 1.0); +println!("Exact min cut: {}", result.value); ``` ### Real-Time Monitoring @@ -514,110 +516,76 @@ mincut.insert_edge(2, 3, 1.0)?; | Operation | Time Complexity | Notes | |-----------|----------------|-------| -| **Build** | O(m log n) | Initial construction from m edges, n vertices | +| **Build** | Polynomial | Runs the exact solver on the initial graph | | **Query** | O(1) | Current minimum cut value | -| **Insert Edge** | O(n^{o(1)}) amortized | Subpolynomial update time | -| **Delete Edge** | O(n^{o(1)}) amortized | Includes replacement edge search | -| **Batch Insert** | O(k × n^{o(1)}) | k edges with lazy evaluation | +| **Insert Edge** | May be polynomial | Recomputes when the cached cut cannot be preserved | +| **Delete Edge** | May be polynomial | Recomputes when the cached cut cannot be preserved | +| **Batch Insert** | May be polynomial | Validates the batch, then runs at most one solve | | **Get Partition** | O(n) | Extract vertex partition | | **Get Cut Edges** | O(m) | Extract edges in the cut | ### Space Complexity - **Exact mode**: O(n log n + m) -- **Approximate mode**: O(n log n / ε²) after sparsification +- **Experimental `ApproxMinCut`**: sparsifier size and error are workload dependent; no general guarantee is established here - **Agentic mode**: 6.7KB per core (compile-time verified) ### Comparison with Alternatives | Library | Update Time | Deterministic | Exact | Dynamic | |---------|------------|---------------|-------|---------| -| **ruvector-mincut** | **O(n^{o(1)})** | ✅ Yes | ✅ Yes | ✅ Both | +| **DynamicMinCut** | Polynomial recomputation | ✅ Yes | ✅ Yes | ✅ Both | | petgraph (Karger) | O(n² log³ n) | ❌ No | ❌ Approx | ❌ Static | | Stoer-Wagner | O(nm + n² log n) | ✅ Yes | ✅ Yes | ❌ Static | | Push-Relabel | O(n²√m) | ✅ Yes | ✅ Yes | ❌ Static | -> **Bottom line**: RuVector MinCut is the only Rust library offering subpolynomial dynamic updates with deterministic exact results. +`DynamicMinCut` is an exact dynamic API with cached results. This repository +does not establish subpolynomial update time or a comparative performance lead. ### ⚠️ Limitations & Scope -Theoretical guarantees depend on graph model and cut size regime. Per the underlying paper ([arXiv:2512.13105](https://arxiv.org/abs/2512.13105)): +The underlying paper ([arXiv:2512.13105](https://arxiv.org/abs/2512.13105)) +proves bounds for its own algorithm. Those bounds do not apply to this crate's +current `DynamicMinCut` implementation: -- **Cut size regime**: Subpolynomial bounds apply to cuts of superpolylogarithmic size (λ > log^c n for some constant c) -- **Practical defaults**: Our implementation uses practical parameter choices; see `SubpolyConfig` for tuning -- **Benchmark scope**: Measured scaling (n^0.12) is empirical on test graphs; your mileage may vary on different topologies +- **Cut size regime**: The paper's subpolynomial result is scoped to superpolylogarithmic cuts; this crate does not inherit that theorem. +- **Practical defaults**: `SubpolyConfig` contains research parameters, not proven production tuning. +- **Benchmark scope**: The n^0.12 fit above uses a finite example run; it cannot establish asymptotic scaling. For formal complexity bounds and proofs, consult the original paper. ## Architecture -The crate implements a sophisticated multi-layered architecture: +`MinCutBuilder` constructs `DynamicMinCut` over a `DynamicGraph`. The solver +keeps a selected partition and cached cut value. Some updates can preserve +that cut; other updates call the sparse exact Stoer-Wagner implementation in +`src/algorithm/exact.rs`. `min_cut()` reports the solver actually used. -``` -┌─────────────────────────────────────────────────────────────┐ -│ DynamicMinCut (Public API) │ -├─────────────────────────────────────────────────────────────┤ -│ MinCutWrapper (December 2025 Paper Implementation) [✅] │ -│ ├── O(log n) BoundedInstance with strategic seeds │ -│ ├── Geometric ranges with factor 1.2 │ -│ ├── ClusterHierarchy integration │ -│ ├── FragmentingAlgorithm integration │ -│ └── DeterministicLocalKCut oracle │ -├─────────────────────────────────────────────────────────────┤ -│ HierarchicalDecomposition (O(log n) depth) [✅] │ -│ ├── DecompositionNode (Binary tree) │ -│ ├── ClusterHierarchy (recursive decomposition) │ -│ └── FragmentingAlgorithm (disconnected subgraphs) │ -├─────────────────────────────────────────────────────────────┤ -│ Dynamic Connectivity (Hybrid: ETT + Union-Find) [✅] │ -│ ├── EulerTourTree (Treap-based, O(log n)) │ -│ │ └── Bulk operations, lazy propagation │ -│ ├── Union-Find (path compression fallback) │ -│ └── LinkCutTree (Sleator-Tarjan) │ -├─────────────────────────────────────────────────────────────┤ -│ Graph Sparsification (Approximate mode) [✅] │ -│ ├── Benczúr-Karger (Randomized) │ -│ └── Nagamochi-Ibaraki (Deterministic) │ -├─────────────────────────────────────────────────────────────┤ -│ DynamicGraph (Thread-safe storage) [✅] │ -│ └── DashMap for concurrent operations │ -├─────────────────────────────────────────────────────────────┤ -│ Agentic Chip Layer (WASM, feature: agentic) [✅] │ -│ ├── CompactCoreState (6.7KB per core, compile-verified) │ -│ ├── SharedCoordinator (lock-free atomics) │ -│ ├── CoreExecutor with SIMD boundary methods │ -│ ├── AgenticAnalyzer (256-core distribution) │ -│ └── SIMD128 accelerated popcount/xor/boundary │ -└─────────────────────────────────────────────────────────────┘ -``` +Other public modules, including `SubpolynomialMinCut`, `MinCutWrapper`, +`ApproxMinCut`, and the hierarchy components, are separate research APIs. +They are not on `DynamicMinCut`'s solve path. Their presence does not imply +that the main API has the paper's update bound or a validated approximation +ratio. -See [ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed design documentation. +See [ARCHITECTURE.md](docs/ARCHITECTURE.md) for research design notes; check +current source before relying on a stated complexity or deployment property. ## Algorithms -### Exact Algorithm - -The exact algorithm maintains minimum cuts using: - -1. **Hierarchical Decomposition**: Balanced binary tree over vertices -2. **Link-Cut Trees**: Dynamic tree operations in O(log n) -3. **Euler Tour Trees**: Alternative connectivity structure -4. **Lazy Propagation**: Only recompute affected subtrees - -Guarantees the true minimum cut but may be slower for very large cuts. - -### Approximate Algorithm - -The approximate algorithm uses **graph sparsification**: +### Exact DynamicMinCut -1. **Edge Strength Computation**: Approximate max-flow for each edge -2. **Sampling**: Keep edges with probability ∝ 1/strength -3. **Weight Scaling**: Scale kept edges to preserve cuts -4. **Sparse Certificate**: O(n log n / ε²) edges preserve (1+ε)-approximate cuts +The main API uses sparse Stoer-Wagner to recompute an exact global cut when +its cached partition cannot be preserved. Full recomputation is polynomial. +Reading the cached cut value is O(1); `min_cut()` also clones the partition +and crossing edges. -Faster for large graphs, with tunable accuracy via ε. +### Experimental ApproxMinCut -See [ALGORITHMS.md](docs/ALGORITHMS.md) for complete mathematical details. +`ApproxMinCut` samples edges using heuristic resistance estimates, then +solves the sampled graph. Its `lower_bound` and `upper_bound` fields are +computed from the selected ε, but are not independently certified bounds on +the original graph. Treat this API as research code until error guarantees +are validated on representative graph families. ## API Reference @@ -633,9 +601,9 @@ See [ALGORITHMS.md](docs/ALGORITHMS.md) for complete mathematical details. ### Paper Implementation Types (December 2025) -- **`SubpolynomialMinCut`**: **NEW** — True O(n^{o(1)}) dynamic min-cut with verified n^0.12 scaling +- **`SubpolynomialMinCut`**: research API; no verified subpolynomial update bound - **`SubpolyConfig`**: Configuration for subpolynomial parameters (φ, λ_max, levels) -- **`RecourseStats`**: Tracks update recourse for complexity verification +- **`RecourseStats`**: Tracks observed update recourse - **`MinCutWrapper`**: O(log n) instance manager with geometric ranges - **`ProperCutInstance`**: Trait for bounded-range cut solvers - **`BoundedInstance`**: Production bounded-range implementation diff --git a/crates/ruvector-mincut/docs/ALGORITHMS.md b/crates/ruvector-mincut/docs/ALGORITHMS.md index 21799aae01..c7c462f59f 100644 --- a/crates/ruvector-mincut/docs/ALGORITHMS.md +++ b/crates/ruvector-mincut/docs/ALGORITHMS.md @@ -1,5 +1,9 @@ # Algorithm Documentation +> Research design document. Complexity targets below describe algorithms in +> the cited literature; they are not proven guarantees of this crate's +> `DynamicMinCut`, which currently uses sparse exact Stoer-Wagner recomputation. + This document provides detailed explanations of the algorithms implemented in `ruvector-mincut`, including mathematical foundations, pseudocode, complexity proofs, and implementation notes. ## Table of Contents diff --git a/crates/ruvector-mincut/docs/BENCHMARK_REPORT.md b/crates/ruvector-mincut/docs/BENCHMARK_REPORT.md index fc6ac8cf40..5384d57554 100644 --- a/crates/ruvector-mincut/docs/BENCHMARK_REPORT.md +++ b/crates/ruvector-mincut/docs/BENCHMARK_REPORT.md @@ -1,5 +1,10 @@ # RuVector MinCut - Performance Benchmark Report +> Historical measurements from December 2025. They have not been reproduced +> against the current release, are not general complexity bounds, and should +> not be used as release-qualified performance claims. Current `DynamicMinCut` +> may rerun a polynomial-time exact solver after updates. + **Date**: December 2025 **Version**: 0.2.0 **Environment**: Linux, Rust 1.70+, Release build @@ -14,8 +19,8 @@ This report documents the performance characteristics of the ruvector-mincut cra | Algorithm | Operation | Time (1000 vertices) | Complexity | |-----------|-----------|---------------------|------------| -| **DynamicMinCut** | Insert Edge | 56.6 µs | O(n^{o(1)}) amortized | -| **DynamicMinCut** | Delete Edge | 106.2 µs | O(n^{o(1)}) amortized | +| **DynamicMinCut** | Insert Edge | 56.6 µs | Not established; may recompute exactly | +| **DynamicMinCut** | Delete Edge | 106.2 µs | Not established; may recompute exactly | | **PolylogConnectivity** | Insert Edge | 1.66 ms | O(log³ n) expected worst-case | | **PolylogConnectivity** | Delete Edge | 519 ms | O(log³ n) expected worst-case | | **PolylogConnectivity** | Query | 16.1 µs | O(log n) worst-case | @@ -26,7 +31,7 @@ This report documents the performance characteristics of the ruvector-mincut cra ## Detailed Benchmark Results -### 1. Core DynamicMinCut (December 2025 Paper) +### 1. Core DynamicMinCut (Historical Measurement) **Insert Edge Performance** | Graph Size | Time | Throughput | @@ -42,7 +47,7 @@ This report documents the performance characteristics of the ruvector-mincut cra |------------|------|-------| | 100 vertices | 18.4 µs | Includes replacement search | | 500 vertices | 56.5 µs | Tree rebuild on tree edge delete | -| 1,000 vertices | 106 µs | O(n^{o(1)}) amortized | +| 1,000 vertices | 106 µs | No amortized bound established here | ### 2. PolylogConnectivity (arXiv:2510.08297) diff --git a/crates/ruvector-mincut/docs/PAPER_IMPLEMENTATION.md b/crates/ruvector-mincut/docs/PAPER_IMPLEMENTATION.md index a83ce97786..a3e711cd3f 100644 --- a/crates/ruvector-mincut/docs/PAPER_IMPLEMENTATION.md +++ b/crates/ruvector-mincut/docs/PAPER_IMPLEMENTATION.md @@ -1,8 +1,14 @@ # Paper Implementation Status +> Historical component inventory. The presence of these modules and small-graph +> tests does not establish a complete implementation or complexity proof for +> arXiv:2512.13105. `DynamicMinCut` currently uses sparse exact Stoer-Wagner +> recomputation. The coverage percentages below have not been reverified for +> this release. + ## Reference El Hayek, Henzinger, Li. "Deterministic and Exact Fully Dynamic Minimum Cut -of Superpolylogarithmic Size in Subpolynomial Time." arXiv:2512.13105, December 2024. +of Superpolylogarithmic Size in Subpolynomial Time." arXiv:2512.13105, December 2025. ## Implementation Status diff --git a/crates/ruvector-mincut/docs/guide/01-getting-started.md b/crates/ruvector-mincut/docs/guide/01-getting-started.md index 44e5819278..7a6b41a261 100644 --- a/crates/ruvector-mincut/docs/guide/01-getting-started.md +++ b/crates/ruvector-mincut/docs/guide/01-getting-started.md @@ -108,7 +108,7 @@ RuVector MinCut has several optional features you can enable based on your needs ```toml [dependencies] -ruvector-mincut = { version = "0.2", features = ["monitoring", "simd"] } +ruvector-mincut = { version = "2.3", features = ["monitoring", "simd"] } ``` #### Available Features @@ -116,7 +116,7 @@ ruvector-mincut = { version = "0.2", features = ["monitoring", "simd"] } | Feature | Default | What It Does | When to Use | |---------|---------|--------------|-------------| | **`exact`** | ✅ Yes | Exact minimum cut algorithm | When you need guaranteed correct results | -| **`approximate`** | ✅ Yes | Fast (1+ε)-approximate algorithm | When speed matters more than perfect accuracy | +| **`approximate`** | ✅ Yes | Legacy compatibility flag; does not switch `DynamicMinCut` solvers | Existing manifests only | | **`monitoring`** | ❌ No | Real-time event notifications | When you need alerts for cut changes | | **`integration`** | ❌ No | GraphDB integration with ruvector-graph | When working with vector databases | | **`simd`** | ❌ No | SIMD vector optimizations | For faster processing on modern CPUs | @@ -321,7 +321,7 @@ mincut.insert_edge(3, 4, 2.0)?; // Add edge mincut.delete_edge(2, 3)?; // Remove edge ``` -These operations update the minimum cut in **O(n^{o(1)})** amortized time — much faster than recomputing from scratch! +These operations update the cached cut. Some changes require a full polynomial-time exact recomputation. --- @@ -388,89 +388,27 @@ if result.is_exact { - Slower for very large graphs - Use when correctness is critical -#### Approximate Mode -- **`is_exact = false`** -- Returns a cut within `(1+ε)` of the minimum -- Much faster for large graphs -- Use when speed matters more than perfect accuracy +#### Legacy Approximate Option -**Example:** With `ε = 0.1`: -- If true minimum = 10, approximate returns between 10 and 11 -- Approximation ratio = 1.1 (10% tolerance) +`MinCutBuilder::approximate(ε)` remains for compatibility, but it does not +select a different solver. `DynamicMinCut` still computes an exact cut and +reports `is_exact = true` and `approximation_ratio = 1.0`. The separate +`ApproxMinCut` research API uses heuristic sparsification without a validated +all-graph `(1+ε)` guarantee. ### Performance Characteristics -```rust -// Query: O(1) - instant! -let value = mincut.min_cut_value(); - -// Insert edge: O(n^{o(1)}) - subpolynomial! -mincut.insert_edge(u, v, weight)?; - -// Delete edge: O(n^{o(1)}) - subpolynomial! -mincut.delete_edge(u, v)?; -``` - -**What is O(n^{o(1)})?** -- Slower than O(1) but faster than O(n), O(log n), etc. -- Example: O(n^{0.01}) or O(n^{1/log log n}) -- Much better than traditional O(m·n) algorithms -- Enables real-time updates even for large graphs +The cached cut value is O(1) to read. An update may preserve the current cut +or run the sparse Stoer-Wagner exact solver, whose full recomputation is +polynomial. Measure against your graph family before relying on update latency. --- -## 5. Choosing Between Exact and Approximate - -Use this flowchart to decide which mode to use: - -```mermaid -flowchart TD - Start{What's your
graph size?} --> Small{Less than
10,000 nodes?} - - Small -->|Yes| UseExact[Use EXACT mode] - Small -->|No| Large{More than
1 million nodes?} - - Large -->|Yes| UseApprox[Use APPROXIMATE mode] - Large -->|No| CheckAccuracy{Need guaranteed
correctness?} - - CheckAccuracy -->|Yes| UseExact2[Use EXACT mode] - CheckAccuracy -->|No| CheckSpeed{Speed is
critical?} - - CheckSpeed -->|Yes| UseApprox2[Use APPROXIMATE mode] - CheckSpeed -->|No| UseExact3[Use EXACT mode
as default] - - UseExact --> ExactCode["mincut = MinCutBuilder::new() - .exact() - .build()?"] - - UseExact2 --> ExactCode - UseExact3 --> ExactCode - - UseApprox --> ApproxCode["mincut = MinCutBuilder::new() - .approximate(0.1) - .build()?"] - - UseApprox2 --> ApproxCode - - style Start fill:#e1f5ff - style UseExact fill:#c8e6c9 - style UseExact2 fill:#c8e6c9 - style UseExact3 fill:#c8e6c9 - style UseApprox fill:#fff9c4 - style UseApprox2 fill:#fff9c4 - style ExactCode fill:#f0f0f0 - style ApproxCode fill:#f0f0f0 -``` - -### Quick Comparison +## 5. Choosing the Solver -| Aspect | Exact Mode | Approximate Mode | -|--------|-----------|------------------| -| **Accuracy** | 100% correct | (1+ε) of optimal | -| **Speed** | Moderate | Very fast | -| **Memory** | O(n log n + m) | O(n log n / ε²) | -| **Best For** | Small-medium graphs | Large graphs | -| **Update Time** | O(n^{o(1)}) | O(n^{o(1)}) | +Use `DynamicMinCut` when an exact global cut is required and its update cost is +acceptable. The legacy `.approximate(ε)` builder option offers no speedup. +Evaluate the separate `ApproxMinCut` API only as experimental research code. ### Code Examples @@ -484,16 +422,16 @@ let mut mincut = MinCutBuilder::new() assert!(mincut.min_cut().is_exact); ``` -**Approximate Mode** (10% tolerance): +**Legacy approximate request** (still exact): ```rust let mut mincut = MinCutBuilder::new() - .approximate(0.1) // ε = 0.1 + .approximate(0.1) // legacy request; does not change the solver .with_edges(edges) .build()?; let result = mincut.min_cut(); -assert!(!result.is_exact); -assert_eq!(result.approximation_ratio, 1.1); +assert!(result.is_exact); +assert_eq!(result.approximation_ratio, 1.0); ``` --- @@ -615,9 +553,8 @@ The minimum cut problem connects to many fascinating areas of computer science: ```rust MinCutBuilder::new() - .exact() // or .approximate(0.1) + .exact() // exact solver .with_edges(edges) // Initial edges - .with_capacity(10000) // Preallocate capacity .build()? // Construct ``` @@ -627,8 +564,8 @@ MinCutBuilder::new() mincut.min_cut_value() // Get cut value (O(1)) mincut.partition() // Get partition (O(n)) mincut.cut_edges() // Get cut edges (O(m)) -mincut.insert_edge(u, v, w)? // Add edge (O(n^{o(1)})) -mincut.delete_edge(u, v)? // Remove edge (O(n^{o(1)})) +mincut.insert_edge(u, v, w)? // Add edge (may recompute) +mincut.delete_edge(u, v)? // Remove edge (may recompute) ``` ### Result Inspection @@ -636,9 +573,9 @@ mincut.delete_edge(u, v)? // Remove edge (O(n^{o(1)})) ```rust let result = mincut.min_cut(); result.value // Cut value -result.is_exact // true if exact mode -result.approximation_ratio // 1.0 if exact, >1.0 if approximate -result.edges // Edges in the cut +result.is_exact // true for DynamicMinCut +result.approximation_ratio // 1.0 for DynamicMinCut +result.cut_edges // Edges in the cut result.partition // (S, T) vertex sets ``` diff --git a/crates/ruvector-mincut/docs/guide/02-core-concepts.md b/crates/ruvector-mincut/docs/guide/02-core-concepts.md index 29238fc95e..8c69481669 100644 --- a/crates/ruvector-mincut/docs/guide/02-core-concepts.md +++ b/crates/ruvector-mincut/docs/guide/02-core-concepts.md @@ -304,111 +304,34 @@ Dynamic algorithms have two complexity measures: - Guarantees for real-time systems - Example: O(log⁴ n) per edge insertion -**RuVector provides both**: -- **Standard algorithm**: Best amortized complexity O(n^{o(1)}) -- **PolylogConnectivity**: Deterministic worst-case O(log⁴ n) +These definitions describe algorithm analysis generally. This crate has not +proved a subpolynomial update bound for `DynamicMinCut`; it may rerun the +polynomial exact solver after a graph change. --- ## 4. Algorithm Choices -RuVector provides three cutting-edge algorithms from recent research papers (2024-2025). Here's when to use each: +### DynamicMinCut (Main API) -### 4.1 Exact Algorithm (Default) +`MinCutBuilder` constructs an exact `DynamicMinCut`. It caches the selected +partition and runs sparse Stoer-Wagner when a change requires recomputation. +The full solve is polynomial. `MinCutBuilder::approximate(ε)` is a legacy +compatibility option and does not select another algorithm; results remain +exact and report an approximation ratio of 1.0. -**Based on**: "A Õ(n^{o(1)})-Approximation Algorithm for Minimum Cut" (Chen et al., 2024) +### ApproxMinCut (Separate Research API) -**Complexity**: O(n^{o(1)}) amortized per operation +`ApproxMinCut` samples a graph using heuristic resistance estimates. Its +reported interval is calculated from ε, but it is not a certified `(1+ε)` +error guarantee for all graphs. Validate correctness and latency on your own +graph family before using it for decisions. -**When to use**: -- ✅ You need the exact minimum cut value -- ✅ Your graph changes frequently (dynamic updates) -- ✅ You want the best average-case performance -- ✅ General-purpose applications +### Other Research Components -**Trade-offs**: -- Slower worst-case than approximate algorithm -- Best for most applications - -```rust -use ruvector_mincut::{MinCutWrapper, MinCutAlgorithm}; - -let mut wrapper = MinCutWrapper::new( - num_vertices, - MinCutAlgorithm::Exact -); -``` - -### 4.2 Approximate Algorithm ((1+ε)-approximation) - -**Based on**: "Dynamic (1+ε)-Approximate Minimum Cut in Subpolynomial Time per Operation" (Cen et al., 2025) - -**Complexity**: Õ(1/ε²) amortized per operation (subpolynomial in n!) - -**When to use**: -- ✅ You can tolerate small approximation error -- ✅ You need extremely fast updates -- ✅ Your graph is very large (millions of vertices) -- ✅ You want cutting-edge performance - -**Trade-offs**: -- Result is within (1+ε) of optimal (e.g., ε=0.1 → 10% error bound) -- **Fastest algorithm** for large graphs - -```rust -let mut wrapper = MinCutWrapper::new_approx( - num_vertices, - 0.1 // ε = 10% approximation -); -``` - -**Example**: If true minimum cut is 100, approximate algorithm returns 100-110. - -### 4.3 PolylogConnectivity (Deterministic Worst-Case) - -**Based on**: "Incremental (1+ε)-Approximate Dynamic Connectivity with polylog Worst-Case Time per Update" (Cen et al., 2025) - -**Complexity**: O(log⁴ n / ε²) worst-case per operation - -**When to use**: -- ✅ You need **guaranteed** worst-case performance -- ✅ Real-time systems with strict latency requirements -- ✅ Safety-critical applications -- ✅ You need predictable performance (no spikes) - -**Trade-offs**: -- Slightly slower than amortized algorithms on average -- Provides deterministic guarantees - -```rust -let mut wrapper = MinCutWrapper::new_polylog_connectivity( - num_vertices, - 0.1 // ε = 10% approximation -); -``` - -### Performance Comparison - -```mermaid -graph TD - subgraph "Performance Characteristics" - A[Exact Algorithm] --> A1["Amortized: O(n^o1)"] - A --> A2[Exact results] - A --> A3[Best general-purpose] - - B[Approximate] --> B1["Amortized: Õ(1/ε²)"] - B --> B2[±ε error] - B --> B3[Fastest updates] - - C[PolylogConnectivity] --> C1["Worst-case: O(log⁴ n / ε²)"] - C --> C2[±ε error] - C --> C3[Predictable latency] - end - - style A fill:#e1f5ff - style B fill:#ffe1e1 - style C fill:#e1ffe1 -``` +`SubpolynomialMinCut`, `MinCutWrapper`, `PolylogConnectivity`, and hierarchy +components expose separate experiments. Their presence does not establish the +paper bounds for the main API or a release-qualified performance claim. --- @@ -567,89 +490,27 @@ graph TB ## 6. Which Algorithm Should I Use? -Use this decision flowchart to choose the right algorithm: - -```mermaid -graph TD - Start[Which algorithm?] --> Q1{Need exact result?} - - Q1 -->|Yes| Exact[Use Exact Algorithm] - Q1 -->|No, approximation OK| Q2{Need worst-case guarantees?} - - Q2 -->|Yes, real-time/safety-critical| Polylog[Use PolylogConnectivity] - Q2 -->|No, average case is fine| Q3{Graph size?} - - Q3 -->|Small < 10K vertices| Exact2[Use Exact Algorithm] - Q3 -->|Large > 10K vertices| Approx[Use Approximate Algorithm] - - Exact --> E1["MinCutAlgorithm::Exact
Best general-purpose"] - Exact2 --> E1 - Approx --> A1["new_approx(n, 0.1)
10% error, fastest"] - Polylog --> P1["new_polylog_connectivity(n, 0.1)
Predictable latency"] +For exact global cuts, start with `MinCutBuilder` and `DynamicMinCut`: - style Exact fill:#90EE90 - style Exact2 fill:#90EE90 - style Approx fill:#FFD700 - style Polylog fill:#87CEEB - style E1 fill:#90EE90 - style A1 fill:#FFD700 - style P1 fill:#87CEEB -``` - -### Quick Reference Table - -| Your Needs | Recommended Algorithm | Configuration | -|------------|----------------------|---------------| -| General-purpose, need exact results | **Exact** | `MinCutAlgorithm::Exact` | -| Large graph (>10K vertices), can tolerate 5-10% error | **Approximate** | `new_approx(n, 0.1)` | -| Real-time system, need guaranteed latency | **PolylogConnectivity** | `new_polylog_connectivity(n, 0.1)` | -| Interactive application with frequent updates | **Approximate** | `new_approx(n, 0.05)` | -| Scientific computing, need precision | **Exact** | `MinCutAlgorithm::Exact` | -| Image segmentation (can accept small errors) | **Approximate** | `new_approx(n, 0.1)` | -| Network monitoring (need alerts) | **PolylogConnectivity** | `new_polylog_connectivity(n, 0.05)` | - -### Performance Guidelines - -**Exact Algorithm**: ```rust -// Best for: Most applications -let mut mincut = MinCutWrapper::new(1000, MinCutAlgorithm::Exact); -``` +use ruvector_mincut::MinCutBuilder; -**Approximate Algorithm**: -```rust -// Best for: Large graphs, speed-critical -let mut mincut = MinCutWrapper::new_approx( - 100_000, // Large graph - 0.1 // 10% approximation is usually fine -); +let mincut = MinCutBuilder::new() + .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)]) + .build()?; +assert!(mincut.min_cut().is_exact); ``` -**PolylogConnectivity**: -```rust -// Best for: Real-time systems -let mut mincut = MinCutWrapper::new_polylog_connectivity( - 50_000, // Medium-large graph - 0.05 // Tight approximation for accuracy -); -``` +Measure updates and memory on the graph family you intend to use. A changed +cut can trigger a polynomial-time solve. `.approximate(ε)` does not reduce +this cost. Research modules should be independently evaluated before their +outputs are used in reliability, medical, or security decisions. --- ## Summary -You now understand: - -1. **Graph fundamentals**: Vertices, edges, weights, and directions -2. **Minimum cut**: Finding the weakest separation in a graph -3. **Dynamic algorithms**: Why incremental updates are revolutionary (200× faster!) -4. **Algorithm choices**: Exact, approximate, and worst-case deterministic options -5. **Data structures**: The sophisticated machinery powering fast dynamic updates -6. **Decision making**: How to choose the right algorithm for your application - -**Next Steps**: -- Read [API Reference](./03-api-reference.md) for detailed function documentation -- Explore [Examples](./04-examples.md) for practical use cases -- Check out [Performance Guide](./05-performance.md) for optimization tips - -**Key Takeaway**: RuVector gives you state-of-the-art dynamic minimum cut algorithms that are 100-200× faster than static approaches for graphs that change over time. Choose your algorithm based on whether you need exact results, maximum speed, or worst-case guarantees. +- `DynamicMinCut` maintains an exact cut and may recompute it after updates. +- `ApproxMinCut` is a separate, experimental sampled-graph API. +- Paper complexity bounds and historical benchmark observations are not + guarantees of the current main API. diff --git a/crates/ruvector-mincut/src/algorithm/approximate.rs b/crates/ruvector-mincut/src/algorithm/approximate.rs index 4de5219c51..1ba8fceb10 100644 --- a/crates/ruvector-mincut/src/algorithm/approximate.rs +++ b/crates/ruvector-mincut/src/algorithm/approximate.rs @@ -1,14 +1,14 @@ //! Approximate Min-Cut for All Cut Sizes //! -//! Implementation based on "Approximate Min-Cut in All Cut Sizes" -//! (SODA 2025, arXiv:2412.15069). +//! Experimental implementation inspired by "Approximate Min-Cut in All Cut Sizes" +//! (SODA 2025, arXiv:2412.15069). It does not implement that paper's proved +//! algorithm or provide a validated all-graph approximation guarantee. //! //! # Key Innovation //! -//! Uses spectral sparsification with edge sampling to achieve (1+ε)-approximate -//! minimum cuts for ANY cut size, not just small cuts. +//! Uses heuristic resistance estimates and edge sampling before a cut solve. //! -//! # Time Complexity +//! # Illustrative Targets (Not Proven Bounds) //! //! - Preprocessing: O(m log² n / ε²) //! - Query: O(n polylog n / ε²) @@ -101,9 +101,9 @@ impl SpectralSparsifier { } } -/// Approximate minimum cut for all cut sizes +/// Experimental sampled-graph minimum cut /// -/// Achieves (1+ε)-approximation for any cut size using spectral sparsification. +/// Experimental sampled-graph min-cut; no all-graph `(1+ε)` guarantee is established. /// /// # Example /// @@ -154,9 +154,9 @@ pub struct ApproxMinCutStats { pub struct ApproxMinCutResult { /// Approximate minimum cut value pub value: f64, - /// Lower bound (value / (1+ε)) + /// Heuristic lower endpoint (value / (1+ε)); not a certified lower bound. pub lower_bound: f64, - /// Upper bound (value * (1+ε)) + /// Heuristic upper endpoint (value * (1+ε)); not a certified upper bound. pub upper_bound: f64, /// Partition achieving the cut pub partition: Option<(Vec, Vec)>, diff --git a/crates/ruvector-mincut/src/algorithm/mod.rs b/crates/ruvector-mincut/src/algorithm/mod.rs index 700401a531..6f619f64e9 100644 --- a/crates/ruvector-mincut/src/algorithm/mod.rs +++ b/crates/ruvector-mincut/src/algorithm/mod.rs @@ -3,12 +3,13 @@ //! Provides the main algorithm with: //! - Exact global cuts with a matching cached partition //! - Support for edge insertions and deletions -//! - Both exact and approximate modes +//! - Exact global cuts; the legacy approximate option does not select a solver //! //! ## Modules //! //! - [`replacement`]: Replacement edge index for tree edge deletions -//! - [`approximate`]: (1+ε)-approximate min-cut for all cut sizes (SODA 2025) +//! - [`approximate`]: experimental sampled-graph min-cut, without a validated +//! all-graph `(1+ε)` guarantee pub mod approximate; mod exact; @@ -28,9 +29,9 @@ use std::sync::Arc; pub struct MinCutConfig { /// Maximum cut size supported for exact algorithm pub max_exact_cut_size: usize, - /// Epsilon for approximate algorithm (0 < ε ≤ 1) + /// Legacy requested tolerance (0 < ε ≤ 1); ignored by `DynamicMinCut`. pub epsilon: f64, - /// Whether to use approximate mode + /// Legacy request flag; `DynamicMinCut` still uses the exact solver. pub approximate: bool, /// Enable parallel computation pub parallel: bool, @@ -59,9 +60,9 @@ pub struct MinCutResult { pub cut_edges: Option>, /// Partition (if requested): (S, T) where S and T are vertex sets pub partition: Option<(Vec, Vec)>, - /// Whether this is an exact or approximate result + /// Whether the solver actually computed an exact cut. pub is_exact: bool, - /// Approximation ratio (1.0 for exact) + /// Guarantee of the solver actually used (1.0 for exact). pub approximation_ratio: f64, } @@ -308,12 +309,10 @@ impl DynamicMinCut { value, cut_edges: Some(edges), partition: Some((partition_s, partition_t)), - is_exact: !self.config.approximate, - approximation_ratio: if self.config.approximate { - 1.0 + self.config.epsilon - } else { - 1.0 - }, + // recompute_min_cut always runs the exact Stoer-Wagner kernel. + // The legacy approximate request must not relabel its result. + is_exact: true, + approximation_ratio: 1.0, } } @@ -434,7 +433,9 @@ impl MinCutBuilder { self } - /// Use approximate algorithm with given epsilon + /// Record a legacy approximate request. `DynamicMinCut` still computes an + /// exact cut; this option does not enable an approximate solver. Use the + /// separate `ApproxMinCut` type for experimental sparsification behavior. pub fn approximate(mut self, epsilon: f64) -> Self { assert!(epsilon > 0.0 && epsilon <= 1.0, "Epsilon must be in (0, 1]"); self.config.approximate = true; @@ -612,8 +613,36 @@ mod tests { let mincut = MinCutBuilder::new().approximate(0.1).build().unwrap(); let result = mincut.min_cut(); - assert!(!result.is_exact); - assert_eq!(result.approximation_ratio, 1.1); + assert!(result.is_exact); + assert_eq!(result.approximation_ratio, 1.0); + } + + #[test] + fn legacy_approximate_option_reports_the_exact_solver_after_updates() { + let edges = vec![(1, 2, 3.0), (2, 3, 2.0), (1, 3, 1.0)]; + let mut exact = MinCutBuilder::new() + .with_edges(edges.clone()) + .build() + .unwrap(); + let mut legacy = MinCutBuilder::new() + .approximate(0.5) + .with_edges(edges) + .build() + .unwrap(); + for (u, v, weight) in [(3, 4, 2.0), (1, 4, 1.0)] { + exact.insert_edge(u, v, weight).unwrap(); + legacy.insert_edge(u, v, weight).unwrap(); + let lhs = exact.min_cut(); + let rhs = legacy.min_cut(); + assert_eq!(rhs.value, lhs.value); + assert_eq!(rhs.partition, lhs.partition); + assert_eq!( + rhs.cut_edges.as_ref().map(Vec::len), + lhs.cut_edges.as_ref().map(Vec::len) + ); + assert!(rhs.is_exact); + assert_eq!(rhs.approximation_ratio, 1.0); + } } #[test] diff --git a/crates/ruvector-mincut/src/lib.rs b/crates/ruvector-mincut/src/lib.rs index 3553145c46..971f39f677 100644 --- a/crates/ruvector-mincut/src/lib.rs +++ b/crates/ruvector-mincut/src/lib.rs @@ -1,14 +1,14 @@ //! # RuVector MinCut //! -//! Subpolynomial-time dynamic minimum cut algorithm with real-time monitoring. +//! Dynamic global minimum cuts with an exact sparse Stoer-Wagner baseline. //! //! This crate provides efficient algorithms for maintaining minimum cuts in //! dynamic graphs with edge insertions and deletions. //! //! ## Features //! -//! - **Exact Algorithm**: O(n^{o(1)}) amortized update time for cuts up to 2^{O((log n)^{3/4})} -//! - **Approximate Algorithm**: (1+ε)-approximate cuts via graph sparsification +//! - **DynamicMinCut**: exact global cuts, recomputed when the cached cut changes +//! - **ApproxMinCut**: a separate experimental sparsification implementation //! - **Real-Time Monitoring**: Event-driven notifications with configurable thresholds //! - **Thread-Safe**: Concurrent reads with exclusive writes //! @@ -50,7 +50,7 @@ //! ## Feature Flags //! //! - `exact` - Exact minimum cut algorithm (enabled by default) -//! - `approximate` - (1+ε)-approximate algorithm (enabled by default) +//! - `approximate` - legacy compatibility flag; it does not switch the solver //! - `monitoring` - Real-time monitoring with callbacks (optional) //! - `integration` - GraphDB integration (optional) //! - `simd` - SIMD optimizations (optional) @@ -74,20 +74,20 @@ //! assert_eq!(mincut.min_cut_value(), 2.0); //! ``` //! -//! ### Approximate Algorithm +//! ### Legacy approximate builder option //! //! ```rust //! use ruvector_mincut::prelude::*; //! //! let mincut = MinCutBuilder::new() -//! .approximate(0.1) // 10% approximation +//! .approximate(0.1) // compatibility option; still runs the exact solver //! .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0)]) //! .build() //! .unwrap(); //! //! let result = mincut.min_cut(); -//! assert!(!result.is_exact); -//! assert_eq!(result.approximation_ratio, 1.1); +//! assert!(result.is_exact); +//! assert_eq!(result.approximation_ratio, 1.0); //! ``` //! //! ### Real-Time Monitoring @@ -180,10 +180,10 @@ pub mod optimization; /// ``` pub mod snn; -/// Subpolynomial-time dynamic minimum cut algorithm. +/// Research module for dynamic minimum cut. /// -/// This module implements the December 2024 breakthrough achieving n^{o(1)} update time. -/// Integrates multi-level hierarchy, deterministic LocalKCut, and fragmenting algorithm. +/// Research components inspired by dynamic min-cut work. The module's presence +/// does not establish a subpolynomial update bound for this implementation. pub mod subpolynomial; /// Dynamic Hierarchical j-Tree Decomposition for Approximate Cut Structure @@ -595,8 +595,8 @@ mod tests { .unwrap(); let result = mincut.min_cut(); - assert!(!result.is_exact); - assert_eq!(result.approximation_ratio, 1.1); + assert!(result.is_exact); + assert_eq!(result.approximation_ratio, 1.0); } #[test] diff --git a/crates/ruvector-mincut/src/subpolynomial/mod.rs b/crates/ruvector-mincut/src/subpolynomial/mod.rs index 5ca0f252e7..af4b8672d3 100644 --- a/crates/ruvector-mincut/src/subpolynomial/mod.rs +++ b/crates/ruvector-mincut/src/subpolynomial/mod.rs @@ -1,6 +1,6 @@ //! Subpolynomial Dynamic Minimum Cut Algorithm //! -//! Implementation of the December 2024 breakthrough achieving n^{o(1)} update time: +//! Research implementation inspired by the dynamic min-cut result in: //! "Deterministic and Exact Fully-dynamic Minimum Cut of Superpolylogarithmic Size //! in Subpolynomial Time" (arXiv:2512.13105) //! @@ -11,12 +11,10 @@ //! 3. **Fragmenting Algorithm**: Boundary-sparse cut detection //! 4. **Witness Trees**: Certificate-based cut verification //! -//! # Complexity Guarantees +//! # Paper Bounds (Not Established for This Implementation) //! -//! - **Update Time**: O(n^{o(1)}) = 2^{O(log^{1-c} n)} amortized -//! - **Query Time**: O(1) -//! - **Space**: O(m log n) -//! - **Cut Size**: Up to 2^{Θ(log^{3/4-c} n)} +//! The paper studies O(n^{o(1)}) amortized updates in a scoped cut-size +//! regime. This crate has not proved that bound for this implementation. //! //! # Example //! @@ -34,7 +32,7 @@ //! let cut_value = mincut.min_cut_value(); //! println!("Min cut: {}", cut_value); //! -//! // Updates are subpolynomial! +//! // The update complexity of this implementation is not established. //! mincut.insert_edge(3, 4, 1.0); //! println!("New min cut: {}", mincut.min_cut_value()); //! ``` @@ -138,7 +136,8 @@ pub struct RecourseStats { } impl RecourseStats { - /// Check if recourse is within subpolynomial bounds + /// Compare observed average recourse with a heuristic threshold. + /// This is not a proof of subpolynomial update time. pub fn is_subpolynomial(&self, n: usize) -> bool { if n < 2 || self.num_updates == 0 { return true;