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

209 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
```rust
// 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:
```rust
// 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`:
```rust
// 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:
```rust
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:
```bash
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
```bash
# 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