Welcome to RuVector MinCut! This guide will help you understand minimum cuts and start using the library in your Rust projects.
Imagine you have a network of roads connecting different cities. The minimum cut answers this question:
"What's the smallest number of roads I need to close to completely separate the network into two parts?"
Think of it like finding the weakest links in a chain — the places where your network is most vulnerable to breaking apart.
| Scenario | What You Have | What Min-Cut Finds |
|---|---|---|
| Road Network | Cities connected by roads | Fewest roads to block to isolate a city |
| Social Network | People connected by friendships | Weakest link between two communities |
| Computer Network | Servers connected by cables | Most vulnerable connections if attacked |
| Water Pipes | Houses connected by pipes | Minimum pipes to shut off to stop water flow |
| Supply Chain | Factories connected by routes | Critical dependencies that could break the chain |
Here's what a minimum cut looks like in a simple graph:
graph LR
subgraph "Original Graph"
A((A)) ---|1| B((B))
B ---|1| C((C))
C ---|1| D((D))
A ---|1| D((D))
B ---|1| D((D))
end
subgraph "After Minimum Cut (value = 2)"
A1((A)) -.x.- B1((B))
B1((B)) ---|1| C1((C))
C1((C)) ---|1| D1((D))
A1((A)) -.x.- D1((D))
B1 ---|1| D1
end
style A1 fill:#ffcccc
style A fill:#ffcccc
style B fill:#ccccff
style C fill:#ccccff
style D fill:#ccccff
style B1 fill:#ccccff
style C1 fill:#ccccff
style D1 fill:#ccccff
Legend:
- Solid lines (—): Edges that remain
- Crossed lines (-.x.-): Edges in the minimum cut (removed)
- Red nodes: One side of the partition (set S)
- Blue nodes: Other side of the partition (set T)
The minimum cut value is 2 because we need to remove 2 edges to disconnect node A from the rest.
| Term | Simple Explanation | Example |
|---|---|---|
| Vertex (or Node) | A point in the network | A city, a person, a server |
| Edge | A connection between two vertices | A road, a friendship, a cable |
| Weight | The "strength" or "capacity" of an edge | Road width, friendship closeness |
| Cut | A set of edges that, when removed, splits the graph | Roads to close to isolate a city |
| Partition | The two groups created after a cut | Cities on each side of the divide |
| Cut Value | Sum of weights of edges in the cut | Total capacity of removed edges |
- Find Vulnerabilities: Identify critical infrastructure that could fail
- Optimize Networks: Understand where to strengthen connections
- Detect Communities: Find natural groupings in social networks
- Image Segmentation: Separate objects from backgrounds in photos
- Load Balancing: Divide work efficiently across systems
The easiest way to add RuVector MinCut to your project:
cargo add ruvector-mincutOr manually add to your Cargo.toml:
[dependencies]
ruvector-mincut = "0.2"RuVector MinCut has several optional features you can enable based on your needs:
[dependencies]
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 |
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 |
wasm |
❌ No | WebAssembly compatibility | For browser or edge deployment |
agentic |
❌ No | 256-core parallel execution | For agentic chip deployment |
# Default: exact + approximate algorithms
[dependencies]
ruvector-mincut = "0.2"
# With real-time monitoring
[dependencies]
ruvector-mincut = { version = "0.2", features = ["monitoring"] }
# Maximum performance
[dependencies]
ruvector-mincut = { version = "0.2", features = ["simd"] }
# Everything enabled
[dependencies]
ruvector-mincut = { version = "0.2", features = ["full"] }flowchart TD
Start[Which features do I need?] --> NeedAlerts{Need real-time<br/>alerts?}
NeedAlerts -->|Yes| AddMonitoring[Add 'monitoring']
NeedAlerts -->|No| CheckSpeed{Need maximum<br/>speed?}
AddMonitoring --> CheckSpeed
CheckSpeed -->|Yes| AddSIMD[Add 'simd']
CheckSpeed -->|No| CheckWasm{Deploying to<br/>browser/edge?}
AddSIMD --> CheckWasm
CheckWasm -->|Yes| AddWasm[Add 'wasm']
CheckWasm -->|No| Done[Use default features]
AddWasm --> Done
style Start fill:#e1f5ff
style Done fill:#c8e6c9
style AddMonitoring fill:#fff9c4
style AddSIMD fill:#fff9c4
style AddWasm fill:#fff9c4
Let's create a simple program that finds the minimum cut in a triangle graph.
Create a new file examples/my_first_mincut.rs:
use ruvector_mincut::{MinCutBuilder, DynamicMinCut};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🔷 Finding Minimum Cut in a Triangle\n");
// Step 1: Create a triangle graph
// 1 ------- 2
// \ /
// \ /
// \ /
// 3
//
// Each edge has weight 1.0
let mut mincut = MinCutBuilder::new()
.exact() // Use exact algorithm for guaranteed correct results
.with_edges(vec![
(1, 2, 1.0), // Edge from vertex 1 to vertex 2, weight 1.0
(2, 3, 1.0), // Edge from vertex 2 to vertex 3, weight 1.0
(3, 1, 1.0), // Edge from vertex 3 to vertex 1, weight 1.0
])
.build()?;
// Step 2: Query the minimum cut value
let cut_value = mincut.min_cut_value();
println!("Minimum cut value: {}", cut_value);
println!("→ We need to remove {} edge(s) to disconnect the graph\n", cut_value);
// Step 3: Get the partition (which vertices are on each side?)
let (side_s, side_t) = mincut.partition();
println!("Partition:");
println!(" Side S (red): {:?}", side_s);
println!(" Side T (blue): {:?}", side_t);
println!("→ These two groups are separated by the cut\n");
// Step 4: Get the actual edges in the cut
let cut_edges = mincut.cut_edges();
println!("Edges in the minimum cut:");
for (u, v, weight) in &cut_edges {
println!(" {} ←→ {} (weight: {})", u, v, weight);
}
println!("→ These edges must be removed to separate the graph\n");
// Step 5: Make the graph dynamic - add a new edge
println!("📍 Adding edge 3 → 4 (weight 2.0)...");
let new_cut = mincut.insert_edge(3, 4, 2.0)?;
println!("New minimum cut value: {}", new_cut);
println!("→ Adding a leaf node increased connectivity\n");
// Step 6: Delete an edge
println!("📍 Deleting edge 2 → 3...");
let final_cut = mincut.delete_edge(2, 3)?;
println!("Final minimum cut value: {}", final_cut);
println!("→ The graph is now a chain: 1-2, 3-4, 1-3\n");
println!("✅ Success! You've computed your first dynamic minimum cut.");
Ok(())
}cargo run --example my_first_mincutExpected Output:
🔷 Finding Minimum Cut in a Triangle
Minimum cut value: 2.0
→ We need to remove 2 edge(s) to disconnect the graph
Partition:
Side S (red): [1]
Side T (blue): [2, 3]
→ These two groups are separated by the cut
Edges in the minimum cut:
1 ←→ 2 (weight: 1.0)
1 ←→ 3 (weight: 1.0)
→ These edges must be removed to separate the graph
📍 Adding edge 3 → 4 (weight 2.0)...
New minimum cut value: 2.0
→ Adding a leaf node increased connectivity
📍 Deleting edge 2 → 3...
Final minimum cut value: 1.0
→ The graph is now a chain: 1-2, 3-4, 1-3
✅ Success! You've computed your first dynamic minimum cut.
Let's understand each part:
let mut mincut = MinCutBuilder::new()
.exact()
.with_edges(vec![
(1, 2, 1.0),
(2, 3, 1.0),
(3, 1, 1.0),
])
.build()?;MinCutBuilder::new(): Creates a new builder.exact(): Use exact algorithm (guaranteed correct).with_edges(vec![...]): Add edges as(source, target, weight)tuples.build()?: Construct the data structure
let cut_value = mincut.min_cut_value();This is O(1) — instant! The value is already computed.
let (side_s, side_t) = mincut.partition();Returns two vectors of vertex IDs showing which vertices are on each side of the cut.
mincut.insert_edge(3, 4, 2.0)?; // Add edge
mincut.delete_edge(2, 3)?; // Remove edgeThese operations update the minimum cut in O(n^{o(1)}) amortized time — much faster than recomputing from scratch!
let cut_value = mincut.min_cut_value(); // Example: 2.0Interpretation:
- This is the sum of weights of edges you need to remove
- For unweighted graphs (all edges weight 1.0), it's the count of edges
- Lower values = weaker connectivity, easier to disconnect
- Higher values = stronger connectivity, harder to disconnect
let (side_s, side_t) = mincut.partition();
// Example: ([1], [2, 3])Interpretation:
side_s: Vertex IDs on one side of the cut (arbitrarily chosen)side_t: Vertex IDs on the other side- All edges connecting S to T are in the minimum cut
- Vertices within S or T remain connected
let cut_edges = mincut.cut_edges();
// Example: [(1, 2, 1.0), (1, 3, 1.0)]Interpretation:
- These are the specific edges that form the minimum cut
- Format:
(source_vertex, target_vertex, weight) - Removing these edges disconnects the graph
- The sum of weights equals the cut value
let result = mincut.min_cut();
if result.is_exact {
println!("Guaranteed minimum: {}", result.value);
} else {
println!("Approximate: {} (±{}%)",
result.value,
(result.approximation_ratio - 1.0) * 100.0
);
}is_exact = true- Guaranteed to find the true minimum cut
- Slower for very large graphs
- Use when correctness is critical
is_exact = false- Returns a cut within
(1+ε)of the minimum - Much faster for large graphs
- Use when speed matters more than perfect accuracy
Example: With ε = 0.1:
- If true minimum = 10, approximate returns between 10 and 11
- Approximation ratio = 1.1 (10% tolerance)
// 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
Use this flowchart to decide which mode to use:
flowchart TD
Start{What's your<br/>graph size?} --> Small{Less than<br/>10,000 nodes?}
Small -->|Yes| UseExact[Use EXACT mode]
Small -->|No| Large{More than<br/>1 million nodes?}
Large -->|Yes| UseApprox[Use APPROXIMATE mode]
Large -->|No| CheckAccuracy{Need guaranteed<br/>correctness?}
CheckAccuracy -->|Yes| UseExact2[Use EXACT mode]
CheckAccuracy -->|No| CheckSpeed{Speed is<br/>critical?}
CheckSpeed -->|Yes| UseApprox2[Use APPROXIMATE mode]
CheckSpeed -->|No| UseExact3[Use EXACT mode<br/>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
| 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)}) |
Exact Mode (guaranteed correct):
let mut mincut = MinCutBuilder::new()
.exact()
.with_edges(edges)
.build()?;
assert!(mincut.min_cut().is_exact);Approximate Mode (10% tolerance):
let mut mincut = MinCutBuilder::new()
.approximate(0.1) // ε = 0.1
.with_edges(edges)
.build()?;
let result = mincut.min_cut();
assert!(!result.is_exact);
assert_eq!(result.approximation_ratio, 1.1);Congratulations! You now understand the basics of minimum cuts and how to use RuVector MinCut. Here's where to go next:
| Topic | Link | What You'll Learn |
|---|---|---|
| Advanced API | 02-advanced-api.md | Batch operations, custom graphs, thread safety |
| Real-Time Monitoring | 03-monitoring.md | Event notifications, thresholds, callbacks |
| Performance Tuning | 04-performance.md | Benchmarking, optimization, scaling |
| Use Cases | 05-use-cases.md | Network analysis, community detection, partitioning |
| Algorithm Details | ../ALGORITHMS.md | Mathematical foundations, proofs, complexity |
| Architecture | ../ARCHITECTURE.md | Internal design, data structures, implementation |
RuVector MinCut comes with several examples you can run:
# Basic minimum cut operations
cargo run --example basic
# Graph sparsification
cargo run --example sparsify_demo
# Local k-cut algorithm
cargo run --example localkcut_demo
# Real-time monitoring (requires 'monitoring' feature)
cargo run --example monitoring --features monitoring
# Performance benchmarking
cargo run --example benchmark --releaseuse ruvector_mincut::{MinCutBuilder, DynamicMinCut};
fn analyze_network(edges: Vec<(u32, u32, f64)>) -> Result<(), Box<dyn std::error::Error>> {
let mut mincut = MinCutBuilder::new()
.exact()
.with_edges(edges)
.build()?;
println!("Network vulnerability: {}", mincut.min_cut_value());
println!("Critical edges: {:?}", mincut.cut_edges());
Ok(())
}#[cfg(feature = "monitoring")]
use ruvector_mincut::{MonitorBuilder, EventType};
fn setup_monitoring() {
let monitor = MonitorBuilder::new()
.threshold_below(5.0, "critical")
.on_event_type(EventType::CutDecreased, "alert", |event| {
eprintln!("⚠️ WARNING: Cut decreased to {}", event.new_value);
})
.build();
// Attach to your mincut structure...
}fn batch_updates(mincut: &mut impl DynamicMinCut,
new_edges: &[(u32, u32, f64)]) -> Result<(), Box<dyn std::error::Error>> {
// Insert many edges at once
for (u, v, w) in new_edges {
mincut.insert_edge(*u, *v, *w)?;
}
// Query triggers lazy evaluation
let current_cut = mincut.min_cut_value();
println!("Updated minimum cut: {}", current_cut);
Ok(())
}- 📖 Documentation: docs.rs/ruvector-mincut
- 🐙 GitHub Issues: Report bugs or ask questions
- 💬 Discussions: Community forum
- 🌐 Website: ruv.io
The minimum cut problem connects to many fascinating areas of computer science:
- Network Flow: Max-flow/min-cut theorem
- Graph Theory: Connectivity, separators, spanning trees
- Optimization: Linear programming, approximation algorithms
- Distributed Systems: Partition tolerance, consensus
- Machine Learning: Graph neural networks, clustering
MinCutBuilder::new()
.exact() // or .approximate(0.1)
.with_edges(edges) // Initial edges
.with_capacity(10000) // Preallocate capacity
.build()? // Constructmincut.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)}))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.partition // (S, T) vertex setsHappy computing! 🚀
Pro Tip: Start simple with exact mode on small graphs, then switch to approximate mode as your graphs grow. The API is identical!