Files
wifi-densepose/crates/ruvector-mincut/docs/bounded_testing_summary.md
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

6.2 KiB
Raw Blame History

Bounded-Range Dynamic Minimum Cut - Testing Summary

Overview

Created comprehensive integration tests and benchmarks for the bounded-range dynamic minimum cut system, implementing the wrapper algorithm from the December 2024 paper.

Files Created

Integration Tests

File: /home/user/ruvector/crates/ruvector-mincut/tests/bounded_integration.rs

16 comprehensive integration tests covering:

  1. Graph Topologies

    • Path graphs (P_n) - min cut = 1
    • Cycle graphs (C_n) - min cut = 2
    • Complete graphs (K_n) - min cut = n-1
    • Grid graphs - min cut = 2 (corner vertices)
    • Star graphs - min cut = 1
    • Bridge graphs (dumbbell) - min cut = 1
  2. Dynamic Operations

    • Edge insertions
    • Edge deletions
    • Incremental updates (path → cycle → path)
    • Buffered updates before query
  3. Correctness Properties

    • Disconnected graphs (min cut = 0)
    • Empty graphs
    • Single edges
    • Deterministic results
    • Multiple query consistency
  4. Stress Testing

    • 1000 random edge insertions
    • Large graphs (100 vertices)
    • Lazy instance instantiation

Benchmarks

File: /home/user/ruvector/crates/ruvector-mincut/benches/bounded_bench.rs

Comprehensive performance benchmarks:

  1. Basic Operations

    • benchmark_insert_edge - Insertion throughput at various graph sizes (100-5000 vertices)
    • benchmark_delete_edge - Deletion throughput
    • benchmark_query - Query latency
    • benchmark_query_after_updates - Query performance with buffered updates (10-500 updates)
  2. Graph Topologies

    • Path graphs
    • Cycle graphs
    • Grid graphs (22×22 = 484 vertices)
    • Complete graphs (30 vertices)
  3. Workload Patterns

    • benchmark_mixed_workload - Realistic mix: 70% queries, 20% inserts, 10% deletes
    • benchmark_lazy_instantiation - First query vs subsequent queries
  4. Performance Scaling

    • Measures throughput using Criterion's Throughput::Elements
    • Tests multiple graph sizes to verify subpolynomial scaling
    • Isolates setup from measurement using iter_batched

Key Bugs Fixed

1. Iterator Issue in LocalKCut

File: src/localkcut/paper_impl.rs

Fixed missing .into_iter() calls when mapping over graph.neighbors() results.

// Before (broken)
let neighbors = graph.neighbors(v).map(|(neighbor, _)| neighbor).collect();

// After (fixed)
let neighbors = graph.neighbors(v).into_iter().map(|(neighbor, _)| neighbor).collect();

2. Stub Instance Overflow

File: src/instance/stub.rs

Added check to prevent overflow when computing 1u64 << n for large graphs:

// Stub instance only works for small graphs (n < 20)
if n >= 20 {
    return None; // Triggers AboveRange
}

3. Wrapper Instance Initialization

File: src/instance/stub.rs, src/wrapper/mod.rs

Distinguished between two initialization modes:

  • new() - Copies initial graph state (for direct testing)
  • init() - Starts empty (for wrapper use, which applies edges via apply_inserts)

4. Wrapper AboveRange Handling

File: src/wrapper/mod.rs

Fixed logic to continue searching instances instead of stopping on first AboveRange:

// Before (broken)
InstanceResult::AboveRange => {
    break; // Would stop immediately!
}

// After (fixed)
InstanceResult::AboveRange => {
    continue; // Try next instance with larger range
}

5. New Instance State Initialization (Critical Fix!)

File: src/wrapper/mod.rs

Fixed bug where new instances created on subsequent queries didn't receive historical edges:

if is_new_instance {
    // New instance: apply ALL edges from the current graph state
    let all_edges: Vec<_> = self.graph.edges()
        .iter()
        .map(|e| (e.id, e.source, e.target))
        .collect();
    instance.apply_inserts(&all_edges);
} else {
    // Existing instance: apply only new updates since last query
    let inserts: Vec<_> = self.pending_inserts
        .iter()
        .filter(|u| u.time > last_time)
        .map(|u| (u.edge_id, u.u, u.v))
        .collect();
    instance.apply_inserts(&inserts);
}

Test Results

Integration Tests

test result: ok. 16 passed; 0 failed

All tests pass, covering:

  • Graph topologies (path, cycle, complete, grid, star, bridge)
  • Dynamic updates (insertions, deletions, incremental)
  • Edge cases (empty, disconnected, single edge)
  • Stress testing (1000 random edges, 100 vertices)
  • Correctness (determinism, consistency)

Benchmarks

Finished `bench` profile [optimized + debuginfo]
Executable: bounded_bench

Benchmarks compile successfully and ready to run with:

cargo bench --bench bounded_bench --package ruvector-mincut

Performance Characteristics

Based on test observations:

  1. Instance Creation: Lazy instantiation - instances only created when needed
  2. Query Time: O(log n) instances checked in worst case
  3. Update Time: Incremental - only new updates applied to existing instances
  4. Memory: Grows with graph size + O(log n) instances

Typical instance counts observed:

  • Path graph (10 vertices, min cut 1): 1 instance
  • Cycle graph (5 vertices, min cut 2): 4 instances
  • Grid graph (9 vertices, min cut 2): Similar pattern

Running Tests

# Run all integration tests
cargo test --test bounded_integration --package ruvector-mincut

# Run with output
cargo test --test bounded_integration --package ruvector-mincut -- --nocapture

# Run specific test
cargo test --test bounded_integration test_cycle_graph_integration --package ruvector-mincut

# Run benchmarks
cargo bench --bench bounded_bench --package ruvector-mincut

Future Improvements

  1. Replace StubInstance: Current brute-force O(2^n) implementation should be replaced with real LocalKCut algorithm for n > 20
  2. Deletions: Test coverage for deletion-heavy workloads
  3. Weighted Graphs: More extensive testing with non-unit edge weights
  4. Concurrency: Add tests for concurrent queries (wrapper uses Arc internally)
  5. Memory Bounds: Add tests verifying memory usage stays bounded

References

  • Paper: "Subpolynomial-time Dynamic Minimum Cut" (December 2024, arxiv:2512.13105)
  • Implementation follows wrapper algorithm from Section 3
  • Uses geometric range factor 1.2 with O(log n) instances