Files
wifi-densepose/crates/ruvector-mincut/docs/guide/04-integration-guide.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

53 KiB

Integration Guide

This guide covers all methods for integrating ruvector-mincut into your applications across different platforms and languages.

Table of Contents


Rust Crate Integration

Basic Setup

Add ruvector-mincut to your Cargo.toml:

[dependencies]
ruvector-mincut = "0.1.0"
ruvector-graph = "0.1.0"  # For graph database features

# Optional: Enable specific features
[dependencies.ruvector-mincut]
version = "0.1.0"
features = ["parallel", "advanced", "visualization"]

Feature Flags

The crate supports several feature combinations:

[features]
default = []

# Core features
parallel = ["rayon"]           # Parallel execution with rayon
advanced = ["petgraph"]        # Advanced algorithms (Nagamochi-Ibaraki, etc.)
visualization = ["plotters"]   # Graph visualization support

# Performance features
simd = []                      # SIMD optimizations
native = []                    # Native CPU optimizations

# Serialization
serde = ["dep:serde"]
bincode = ["dep:bincode"]

# All features
full = ["parallel", "advanced", "visualization", "simd", "serde"]

Workspace Setup

For multi-crate workspaces:

# workspace/Cargo.toml
[workspace]
members = [
    "app",
    "algorithms",
]

[workspace.dependencies]
ruvector-mincut = { version = "0.1.0", features = ["parallel", "advanced"] }

# app/Cargo.toml
[dependencies]
ruvector-mincut = { workspace = true }

# algorithms/Cargo.toml
[dependencies]
ruvector-mincut = { workspace = true, features = ["visualization"] }

Basic Usage Example

use ruvector_mincut::{MinCutWrapper, MinCutAlgorithm};
use ruvector_mincut::graph::GraphBuilder;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Build a graph
    let mut builder = GraphBuilder::new();
    builder.add_edge(0, 1, 1.0);
    builder.add_edge(1, 2, 1.0);
    builder.add_edge(2, 3, 1.0);
    builder.add_edge(3, 0, 1.0);
    builder.add_edge(0, 2, 0.5);

    let graph = builder.build()?;

    // Create wrapper and find minimum cut
    let mut wrapper = MinCutWrapper::new(graph);
    let result = wrapper.compute_min_cut(MinCutAlgorithm::StoerWagner)?;

    println!("Minimum cut value: {}", result.cut_value);
    println!("Partition 1: {:?}", result.partition1);
    println!("Partition 2: {:?}", result.partition2);

    Ok(())
}

Advanced Usage with Features

#[cfg(feature = "parallel")]
use rayon::prelude::*;

use ruvector_mincut::{
    MinCutWrapper,
    MinCutAlgorithm,
    algorithms::PaperAlgorithm,
};

fn parallel_analysis(graphs: Vec<Graph>) -> Vec<MinCutResult> {
    #[cfg(feature = "parallel")]
    {
        graphs.par_iter()
            .map(|g| {
                let mut wrapper = MinCutWrapper::new(g.clone());
                wrapper.compute_min_cut(MinCutAlgorithm::FlowBased).unwrap()
            })
            .collect()
    }

    #[cfg(not(feature = "parallel"))]
    {
        graphs.iter()
            .map(|g| {
                let mut wrapper = MinCutWrapper::new(g.clone());
                wrapper.compute_min_cut(MinCutAlgorithm::FlowBased).unwrap()
            })
            .collect()
    }
}

#[cfg(feature = "advanced")]
fn use_paper_algorithms(graph: &Graph) -> Result<f64, MinCutError> {
    use ruvector_mincut::PaperAlgorithm;

    let mut wrapper = MinCutWrapper::new(graph.clone());

    // Use state-of-the-art algorithm from SODA 2025
    let result = wrapper.compute_paper_algorithm(
        PaperAlgorithm::RandomizedMinCutVerification
    )?;

    Ok(result.cut_value)
}

WebAssembly (WASM)

Building for WASM Target

Prerequisites

# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# Add wasm32 target
rustup target add wasm32-unknown-unknown

Build Commands

# Development build
wasm-pack build --target web --dev crates/ruvector-mincut-wasm

# Production build with optimizations
wasm-pack build --target web --release crates/ruvector-mincut-wasm

# Build for Node.js
wasm-pack build --target nodejs crates/ruvector-mincut-wasm

# Build for bundlers (webpack, rollup)
wasm-pack build --target bundler crates/ruvector-mincut-wasm

Optimization Tips

# Cargo.toml for WASM builds
[profile.release]
opt-level = "z"           # Optimize for size
lto = true               # Link-time optimization
codegen-units = 1        # Better optimization
panic = "abort"          # Smaller binary
strip = true             # Strip symbols

[profile.release.package."*"]
opt-level = "z"

Browser Integration

HTML Setup

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>RuVector MinCut Demo</title>
</head>
<body>
    <h1>Minimum Cut Calculator</h1>

    <div>
        <label>Number of nodes:</label>
        <input type="number" id="nodeCount" value="10" min="2" max="1000">
    </div>

    <div>
        <label>Edge density:</label>
        <input type="range" id="density" min="0.1" max="1.0" step="0.1" value="0.3">
        <span id="densityValue">0.3</span>
    </div>

    <button id="computeBtn">Compute Min Cut</button>

    <div id="results"></div>
    <canvas id="graphCanvas" width="800" height="600"></canvas>

    <script type="module">
        import init, {
            MinCutWrapper,
            GraphBuilder,
            MinCutAlgorithm
        } from './pkg/ruvector_mincut_wasm.js';

        async function run() {
            // Initialize WASM module
            await init();

            document.getElementById('computeBtn').addEventListener('click', computeMinCut);
            document.getElementById('density').addEventListener('input', (e) => {
                document.getElementById('densityValue').textContent = e.target.value;
            });
        }

        async function computeMinCut() {
            const nodeCount = parseInt(document.getElementById('nodeCount').value);
            const density = parseFloat(document.getElementById('density').value);

            // Build random graph
            const builder = new GraphBuilder();

            for (let i = 0; i < nodeCount; i++) {
                for (let j = i + 1; j < nodeCount; j++) {
                    if (Math.random() < density) {
                        const weight = Math.random() * 10;
                        builder.add_edge(i, j, weight);
                    }
                }
            }

            const graph = builder.build();

            // Compute minimum cut
            const wrapper = new MinCutWrapper(graph);
            const startTime = performance.now();

            const result = wrapper.compute_min_cut(MinCutAlgorithm.StoerWagner);

            const elapsed = performance.now() - startTime;

            // Display results
            document.getElementById('results').innerHTML = `
                <h2>Results</h2>
                <p><strong>Minimum Cut Value:</strong> ${result.cut_value.toFixed(4)}</p>
                <p><strong>Partition 1 Size:</strong> ${result.partition1.length}</p>
                <p><strong>Partition 2 Size:</strong> ${result.partition2.length}</p>
                <p><strong>Computation Time:</strong> ${elapsed.toFixed(2)} ms</p>
                <p><strong>Edges in Cut:</strong> ${result.cut_edges.length}</p>
            `;

            // Visualize (optional - requires additional canvas code)
            visualizeGraph(graph, result);
        }

        function visualizeGraph(graph, result) {
            const canvas = document.getElementById('graphCanvas');
            const ctx = canvas.getContext('2d');

            // Clear canvas
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // Simple force-directed layout visualization
            // (Simplified version - production would use D3.js or similar)
            const nodes = result.partition1.concat(result.partition2);
            const positions = layoutNodes(nodes, canvas.width, canvas.height);

            // Draw edges
            ctx.strokeStyle = '#ccc';
            ctx.lineWidth = 1;
            // ... edge drawing code

            // Draw nodes
            result.partition1.forEach(nodeId => {
                drawNode(ctx, positions[nodeId], '#3498db');
            });

            result.partition2.forEach(nodeId => {
                drawNode(ctx, positions[nodeId], '#e74c3c');
            });
        }

        function drawNode(ctx, pos, color) {
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc(pos.x, pos.y, 8, 0, 2 * Math.PI);
            ctx.fill();
        }

        function layoutNodes(nodes, width, height) {
            // Simple circular layout
            const positions = {};
            const radius = Math.min(width, height) * 0.4;
            const centerX = width / 2;
            const centerY = height / 2;

            nodes.forEach((nodeId, i) => {
                const angle = (2 * Math.PI * i) / nodes.length;
                positions[nodeId] = {
                    x: centerX + radius * Math.cos(angle),
                    y: centerY + radius * Math.sin(angle)
                };
            });

            return positions;
        }

        run();
    </script>
</body>
</html>

TypeScript Integration

// mincut-worker.ts
import init, {
    MinCutWrapper,
    GraphBuilder,
    MinCutAlgorithm,
    type MinCutResult
} from 'ruvector-mincut-wasm';

interface GraphData {
    nodes: number;
    edges: Array<[number, number, number]>;
}

interface ComputeRequest {
    type: 'compute';
    graph: GraphData;
    algorithm: string;
}

let initialized = false;

self.onmessage = async (e: MessageEvent<ComputeRequest>) => {
    if (!initialized) {
        await init();
        initialized = true;
    }

    const { graph, algorithm } = e.data;

    try {
        // Build graph
        const builder = new GraphBuilder();
        graph.edges.forEach(([from, to, weight]) => {
            builder.add_edge(from, to, weight);
        });

        const g = builder.build();

        // Compute minimum cut
        const wrapper = new MinCutWrapper(g);
        const algo = MinCutAlgorithm[algorithm as keyof typeof MinCutAlgorithm];
        const result = wrapper.compute_min_cut(algo);

        self.postMessage({
            success: true,
            result: {
                cutValue: result.cut_value,
                partition1: Array.from(result.partition1),
                partition2: Array.from(result.partition2),
                cutEdges: Array.from(result.cut_edges)
            }
        });
    } catch (error) {
        self.postMessage({
            success: false,
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
};

Main Application

// app.ts
import type { MinCutResult } from './types';

class MinCutService {
    private worker: Worker;
    private requestId = 0;
    private pending = new Map<number, {
        resolve: (result: MinCutResult) => void;
        reject: (error: Error) => void;
    }>();

    constructor() {
        this.worker = new Worker(
            new URL('./mincut-worker.ts', import.meta.url),
            { type: 'module' }
        );

        this.worker.onmessage = (e) => {
            const { id, success, result, error } = e.data;
            const pending = this.pending.get(id);

            if (pending) {
                if (success) {
                    pending.resolve(result);
                } else {
                    pending.reject(new Error(error));
                }
                this.pending.delete(id);
            }
        };
    }

    async computeMinCut(
        graph: GraphData,
        algorithm: string = 'StoerWagner'
    ): Promise<MinCutResult> {
        return new Promise((resolve, reject) => {
            const id = this.requestId++;
            this.pending.set(id, { resolve, reject });

            this.worker.postMessage({
                type: 'compute',
                id,
                graph,
                algorithm
            });
        });
    }

    terminate() {
        this.worker.terminate();
    }
}

// Usage
const service = new MinCutService();

const graph = {
    nodes: 6,
    edges: [
        [0, 1, 2.0],
        [1, 2, 3.0],
        [2, 3, 1.0],
        [3, 4, 2.0],
        [4, 5, 1.0],
        [5, 0, 2.0],
        [0, 3, 0.5]
    ]
};

const result = await service.computeMinCut(graph);
console.log('Min cut value:', result.cutValue);

Node.js Integration

Installation

# Using npm
npm install ruvector-mincut-node

# Using yarn
yarn add ruvector-mincut-node

# Using pnpm
pnpm add ruvector-mincut-node

TypeScript Setup

// types/mincut.d.ts
declare module 'ruvector-mincut-node' {
    export interface Edge {
        from: number;
        to: number;
        weight: number;
    }

    export interface MinCutResult {
        cutValue: number;
        partition1: number[];
        partition2: number[];
        cutEdges: Array<[number, number]>;
    }

    export interface ConnectivityCurve {
        numClusters: number;
        cutValue: number;
    }

    export enum MinCutAlgorithm {
        StoerWagner = 'StoerWagner',
        FlowBased = 'FlowBased',
        KargerStein = 'KargerStein',
        NagamochiIbaraki = 'NagamochiIbaraki',
        Hierarchical = 'Hierarchical'
    }

    export class GraphBuilder {
        constructor();
        addEdge(from: number, to: number, weight: number): void;
        build(): Graph;
    }

    export class Graph {
        nodeCount(): number;
        edgeCount(): number;
    }

    export class MinCutWrapper {
        constructor(graph: Graph);
        computeMinCut(algorithm: MinCutAlgorithm): Promise<MinCutResult>;
        computeConnectivityCurve(maxClusters?: number): Promise<ConnectivityCurve[]>;
        computeLocalKCut(k: number, sourceNode: number): Promise<MinCutResult>;
    }

    export class PaperAlgorithm {
        static RandomizedMinCutVerification: string;
        static BoundedMinCutEnumeration: string;
        static ApproximateGlobalMinCut: string;
    }
}

Basic Usage

// src/mincut.ts
import {
    GraphBuilder,
    MinCutWrapper,
    MinCutAlgorithm,
    type MinCutResult
} from 'ruvector-mincut-node';

async function computeMinimumCut(
    edges: Array<[number, number, number]>
): Promise<MinCutResult> {
    // Build graph
    const builder = new GraphBuilder();

    for (const [from, to, weight] of edges) {
        builder.addEdge(from, to, weight);
    }

    const graph = builder.build();

    // Compute minimum cut
    const wrapper = new MinCutWrapper(graph);
    const result = await wrapper.computeMinCut(MinCutAlgorithm.StoerWagner);

    return result;
}

// Example usage
const edges: Array<[number, number, number]> = [
    [0, 1, 1.0],
    [1, 2, 1.0],
    [2, 3, 1.0],
    [3, 0, 1.0],
    [0, 2, 0.5]
];

computeMinimumCut(edges).then(result => {
    console.log('Minimum cut value:', result.cutValue);
    console.log('Partition 1:', result.partition1);
    console.log('Partition 2:', result.partition2);
});

Express.js Service

// src/server.ts
import express, { Request, Response } from 'express';
import {
    GraphBuilder,
    MinCutWrapper,
    MinCutAlgorithm
} from 'ruvector-mincut-node';

const app = express();
app.use(express.json());

interface MinCutRequest {
    edges: Array<[number, number, number]>;
    algorithm?: string;
}

app.post('/api/mincut', async (req: Request<{}, {}, MinCutRequest>, res: Response) => {
    try {
        const { edges, algorithm = 'StoerWagner' } = req.body;

        if (!edges || !Array.isArray(edges)) {
            return res.status(400).json({
                error: 'Invalid request: edges array required'
            });
        }

        // Validate edges
        for (const edge of edges) {
            if (!Array.isArray(edge) || edge.length !== 3) {
                return res.status(400).json({
                    error: 'Invalid edge format: expected [from, to, weight]'
                });
            }
        }

        // Build graph
        const builder = new GraphBuilder();
        edges.forEach(([from, to, weight]) => {
            builder.addEdge(from, to, weight);
        });

        const graph = builder.build();

        // Compute minimum cut
        const wrapper = new MinCutWrapper(graph);
        const algo = MinCutAlgorithm[algorithm as keyof typeof MinCutAlgorithm]
                     || MinCutAlgorithm.StoerWagner;

        const result = await wrapper.computeMinCut(algo);

        res.json({
            success: true,
            data: {
                cutValue: result.cutValue,
                partition1: result.partition1,
                partition2: result.partition2,
                cutEdges: result.cutEdges,
                algorithm: algorithm
            }
        });
    } catch (error) {
        console.error('Error computing min cut:', error);
        res.status(500).json({
            success: false,
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
});

app.post('/api/connectivity-curve', async (req: Request, res: Response) => {
    try {
        const { edges, maxClusters = 10 } = req.body;

        const builder = new GraphBuilder();
        edges.forEach(([from, to, weight]: [number, number, number]) => {
            builder.addEdge(from, to, weight);
        });

        const graph = builder.build();
        const wrapper = new MinCutWrapper(graph);

        const curve = await wrapper.computeConnectivityCurve(maxClusters);

        res.json({
            success: true,
            data: curve
        });
    } catch (error) {
        console.error('Error computing connectivity curve:', error);
        res.status(500).json({
            success: false,
            error: error instanceof Error ? error.message : 'Unknown error'
        });
    }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`MinCut service running on port ${PORT}`);
});

Async Patterns with Worker Threads

// src/worker-pool.ts
import { Worker } from 'worker_threads';
import { cpus } from 'os';

interface WorkerTask {
    id: number;
    edges: Array<[number, number, number]>;
    algorithm: string;
}

interface WorkerResult {
    id: number;
    result: any;
    error?: string;
}

export class MinCutWorkerPool {
    private workers: Worker[] = [];
    private queue: Array<{
        task: WorkerTask;
        resolve: (result: any) => void;
        reject: (error: Error) => void;
    }> = [];
    private activeWorkers = 0;
    private taskId = 0;

    constructor(private poolSize: number = cpus().length) {
        this.initializeWorkers();
    }

    private initializeWorkers() {
        for (let i = 0; i < this.poolSize; i++) {
            const worker = new Worker('./mincut-worker.js');

            worker.on('message', (result: WorkerResult) => {
                this.activeWorkers--;

                const pending = this.queue.shift();
                if (pending) {
                    if (result.error) {
                        pending.reject(new Error(result.error));
                    } else {
                        pending.resolve(result.result);
                    }
                }

                this.processQueue();
            });

            worker.on('error', (error) => {
                console.error('Worker error:', error);
                this.activeWorkers--;
                this.processQueue();
            });

            this.workers.push(worker);
        }
    }

    async computeMinCut(
        edges: Array<[number, number, number]>,
        algorithm: string = 'StoerWagner'
    ): Promise<any> {
        return new Promise((resolve, reject) => {
            const task: WorkerTask = {
                id: this.taskId++,
                edges,
                algorithm
            };

            this.queue.push({ task, resolve, reject });
            this.processQueue();
        });
    }

    private processQueue() {
        while (this.activeWorkers < this.poolSize && this.queue.length > 0) {
            const { task } = this.queue[0];
            const worker = this.workers[this.activeWorkers];

            this.activeWorkers++;
            worker.postMessage(task);
        }
    }

    terminate() {
        this.workers.forEach(worker => worker.terminate());
        this.workers = [];
    }
}

// Usage
const pool = new MinCutWorkerPool();

const tasks = [
    pool.computeMinCut([[0, 1, 1], [1, 2, 1]], 'StoerWagner'),
    pool.computeMinCut([[0, 1, 2], [1, 2, 3]], 'FlowBased'),
    pool.computeMinCut([[0, 1, 1], [1, 2, 1], [2, 0, 1]], 'KargerStein')
];

const results = await Promise.all(tasks);
console.log('All results:', results);

Python Integration

PyO3 Bindings Concept

# ruvector_mincut/__init__.py
"""
Python bindings for ruvector-mincut library.

This module provides Python access to high-performance minimum cut algorithms
implemented in Rust.
"""

from typing import List, Tuple, Optional, Dict, Any
from enum import Enum

class MinCutAlgorithm(Enum):
    """Available minimum cut algorithms."""
    STOER_WAGNER = "StoerWagner"
    FLOW_BASED = "FlowBased"
    KARGER_STEIN = "KargerStein"
    NAGAMOCHI_IBARAKI = "NagamochiIbaraki"
    HIERARCHICAL = "Hierarchical"


class MinCutResult:
    """Result of a minimum cut computation."""

    def __init__(
        self,
        cut_value: float,
        partition1: List[int],
        partition2: List[int],
        cut_edges: List[Tuple[int, int]]
    ):
        self.cut_value = cut_value
        self.partition1 = partition1
        self.partition2 = partition2
        self.cut_edges = cut_edges

    def __repr__(self) -> str:
        return (
            f"MinCutResult(cut_value={self.cut_value}, "
            f"partition1={self.partition1}, "
            f"partition2={self.partition2})"
        )

    def to_dict(self) -> Dict[str, Any]:
        """Convert result to dictionary."""
        return {
            'cut_value': self.cut_value,
            'partition1': self.partition1,
            'partition2': self.partition2,
            'cut_edges': self.cut_edges
        }


class GraphBuilder:
    """Builder for constructing graphs."""

    def __init__(self):
        """Initialize a new graph builder."""
        self._edges: List[Tuple[int, int, float]] = []

    def add_edge(self, from_node: int, to_node: int, weight: float = 1.0) -> 'GraphBuilder':
        """
        Add an edge to the graph.

        Args:
            from_node: Source node ID
            to_node: Target node ID
            weight: Edge weight (default: 1.0)

        Returns:
            Self for method chaining
        """
        self._edges.append((from_node, to_node, weight))
        return self

    def build(self) -> 'Graph':
        """
        Build the graph.

        Returns:
            Constructed Graph object
        """
        # This would call the Rust implementation
        from . import _native
        return Graph(_native.build_graph(self._edges))


class Graph:
    """Graph data structure."""

    def __init__(self, handle):
        """Initialize with native handle (internal use)."""
        self._handle = handle

    def node_count(self) -> int:
        """Get the number of nodes in the graph."""
        from . import _native
        return _native.graph_node_count(self._handle)

    def edge_count(self) -> int:
        """Get the number of edges in the graph."""
        from . import _native
        return _native.graph_edge_count(self._handle)


class MinCutWrapper:
    """Wrapper for minimum cut computations."""

    def __init__(self, graph: Graph):
        """
        Initialize wrapper with a graph.

        Args:
            graph: Graph to analyze
        """
        self.graph = graph
        from . import _native
        self._handle = _native.create_mincut_wrapper(graph._handle)

    def compute_min_cut(
        self,
        algorithm: MinCutAlgorithm = MinCutAlgorithm.STOER_WAGNER
    ) -> MinCutResult:
        """
        Compute the minimum cut.

        Args:
            algorithm: Algorithm to use

        Returns:
            MinCutResult containing the cut value and partitions

        Raises:
            ValueError: If computation fails
        """
        from . import _native

        result = _native.compute_min_cut(self._handle, algorithm.value)

        return MinCutResult(
            cut_value=result['cut_value'],
            partition1=result['partition1'],
            partition2=result['partition2'],
            cut_edges=result['cut_edges']
        )

    def compute_connectivity_curve(
        self,
        max_clusters: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        Compute connectivity curve showing cut values at different cluster counts.

        Args:
            max_clusters: Maximum number of clusters (default: node_count)

        Returns:
            List of dictionaries with 'num_clusters' and 'cut_value'
        """
        from . import _native
        return _native.compute_connectivity_curve(self._handle, max_clusters)

    def compute_local_k_cut(
        self,
        k: int,
        source_node: int
    ) -> MinCutResult:
        """
        Compute local k-cut around a source node.

        Args:
            k: Target cluster count
            source_node: Source node for local cut

        Returns:
            MinCutResult for the local cut
        """
        from . import _native

        result = _native.compute_local_k_cut(self._handle, k, source_node)

        return MinCutResult(
            cut_value=result['cut_value'],
            partition1=result['partition1'],
            partition2=result['partition2'],
            cut_edges=result['cut_edges']
        )


# Convenience functions
def compute_min_cut(
    edges: List[Tuple[int, int, float]],
    algorithm: MinCutAlgorithm = MinCutAlgorithm.STOER_WAGNER
) -> MinCutResult:
    """
    Convenience function to compute minimum cut from edge list.

    Args:
        edges: List of (from, to, weight) tuples
        algorithm: Algorithm to use

    Returns:
        MinCutResult

    Example:
        >>> edges = [(0, 1, 1.0), (1, 2, 1.0), (2, 0, 1.0)]
        >>> result = compute_min_cut(edges)
        >>> print(f"Cut value: {result.cut_value}")
    """
    builder = GraphBuilder()
    for from_node, to_node, weight in edges:
        builder.add_edge(from_node, to_node, weight)

    graph = builder.build()
    wrapper = MinCutWrapper(graph)
    return wrapper.compute_min_cut(algorithm)

Python Usage Example

# examples/python_example.py
from ruvector_mincut import (
    GraphBuilder,
    MinCutWrapper,
    MinCutAlgorithm,
    compute_min_cut
)
import matplotlib.pyplot as plt
import networkx as nx

def basic_example():
    """Basic usage example."""
    # Build a simple graph
    builder = GraphBuilder()
    builder.add_edge(0, 1, 1.0)
    builder.add_edge(1, 2, 1.0)
    builder.add_edge(2, 3, 1.0)
    builder.add_edge(3, 0, 1.0)
    builder.add_edge(0, 2, 0.5)

    graph = builder.build()

    # Compute minimum cut
    wrapper = MinCutWrapper(graph)
    result = wrapper.compute_min_cut(MinCutAlgorithm.STOER_WAGNER)

    print(f"Minimum cut value: {result.cut_value}")
    print(f"Partition 1: {result.partition1}")
    print(f"Partition 2: {result.partition2}")
    print(f"Cut edges: {result.cut_edges}")


def connectivity_analysis():
    """Analyze connectivity curve."""
    # Create a larger graph
    edges = []
    for i in range(10):
        edges.append((i, (i + 1) % 10, 1.0))
        if i % 2 == 0:
            edges.append((i, (i + 5) % 10, 0.5))

    builder = GraphBuilder()
    for from_node, to_node, weight in edges:
        builder.add_edge(from_node, to_node, weight)

    graph = builder.build()
    wrapper = MinCutWrapper(graph)

    # Get connectivity curve
    curve = wrapper.compute_connectivity_curve(max_clusters=5)

    # Plot
    clusters = [c['num_clusters'] for c in curve]
    cut_values = [c['cut_value'] for c in curve]

    plt.figure(figsize=(10, 6))
    plt.plot(clusters, cut_values, marker='o')
    plt.xlabel('Number of Clusters')
    plt.ylabel('Minimum Cut Value')
    plt.title('Connectivity Curve')
    plt.grid(True)
    plt.savefig('connectivity_curve.png')
    print("Saved connectivity curve to connectivity_curve.png")


def visualize_cut():
    """Visualize the minimum cut."""
    # Build graph
    edges = [
        (0, 1, 1.0), (1, 2, 1.0), (2, 3, 1.0),
        (3, 4, 1.0), (4, 5, 1.0), (5, 0, 1.0),
        (0, 3, 0.5), (1, 4, 0.5), (2, 5, 0.5)
    ]

    # Compute minimum cut
    result = compute_min_cut(edges)

    # Create NetworkX graph for visualization
    G = nx.Graph()
    for from_node, to_node, weight in edges:
        G.add_edge(from_node, to_node, weight=weight)

    # Color nodes by partition
    colors = []
    for node in G.nodes():
        if node in result.partition1:
            colors.append('lightblue')
        else:
            colors.append('lightcoral')

    # Highlight cut edges
    edge_colors = []
    for edge in G.edges():
        if edge in result.cut_edges or (edge[1], edge[0]) in result.cut_edges:
            edge_colors.append('red')
        else:
            edge_colors.append('gray')

    # Draw
    plt.figure(figsize=(10, 8))
    pos = nx.spring_layout(G)
    nx.draw(G, pos, node_color=colors, edge_color=edge_colors,
            node_size=500, with_labels=True, width=2)
    plt.title(f'Minimum Cut (value: {result.cut_value})')
    plt.savefig('mincut_visualization.png')
    print("Saved visualization to mincut_visualization.png")


if __name__ == '__main__':
    print("Running basic example...")
    basic_example()

    print("\nAnalyzing connectivity...")
    connectivity_analysis()

    print("\nVisualizing cut...")
    visualize_cut()

REST API Service

Actix-Web Service

// src/api/mod.rs
use actix_web::{web, App, HttpResponse, HttpServer, middleware};
use serde::{Deserialize, Serialize};
use ruvector_mincut::{MinCutWrapper, MinCutAlgorithm, MinCutError};
use ruvector_mincut::graph::GraphBuilder;

#[derive(Debug, Deserialize)]
struct Edge {
    from: usize,
    to: usize,
    weight: f64,
}

#[derive(Debug, Deserialize)]
struct MinCutRequest {
    edges: Vec<Edge>,
    algorithm: Option<String>,
}

#[derive(Debug, Serialize)]
struct MinCutResponse {
    cut_value: f64,
    partition1: Vec<usize>,
    partition2: Vec<usize>,
    cut_edges: Vec<(usize, usize)>,
    algorithm: String,
    computation_time_ms: f64,
}

#[derive(Debug, Serialize)]
struct ErrorResponse {
    error: String,
    details: Option<String>,
}

#[derive(Debug, Deserialize)]
struct ConnectivityRequest {
    edges: Vec<Edge>,
    max_clusters: Option<usize>,
}

#[derive(Debug, Serialize)]
struct ConnectivityPoint {
    num_clusters: usize,
    cut_value: f64,
}

#[derive(Debug, Serialize)]
struct ConnectivityResponse {
    curve: Vec<ConnectivityPoint>,
    computation_time_ms: f64,
}

// Health check endpoint
async fn health() -> HttpResponse {
    HttpResponse::Ok().json(serde_json::json!({
        "status": "healthy",
        "version": env!("CARGO_PKG_VERSION")
    }))
}

// Compute minimum cut endpoint
async fn compute_min_cut(req: web::Json<MinCutRequest>) -> HttpResponse {
    let start = std::time::Instant::now();

    // Build graph
    let mut builder = GraphBuilder::new();
    for edge in &req.edges {
        builder.add_edge(edge.from, edge.to, edge.weight);
    }

    let graph = match builder.build() {
        Ok(g) => g,
        Err(e) => {
            return HttpResponse::BadRequest().json(ErrorResponse {
                error: "Failed to build graph".to_string(),
                details: Some(e.to_string()),
            });
        }
    };

    // Parse algorithm
    let algorithm = match req.algorithm.as_deref() {
        Some("StoerWagner") | None => MinCutAlgorithm::StoerWagner,
        Some("FlowBased") => MinCutAlgorithm::FlowBased,
        Some("KargerStein") => MinCutAlgorithm::KargerStein,
        Some("NagamochiIbaraki") => MinCutAlgorithm::NagamochiIbaraki,
        Some("Hierarchical") => MinCutAlgorithm::Hierarchical,
        Some(algo) => {
            return HttpResponse::BadRequest().json(ErrorResponse {
                error: "Invalid algorithm".to_string(),
                details: Some(format!("Unknown algorithm: {}", algo)),
            });
        }
    };

    // Compute minimum cut
    let mut wrapper = MinCutWrapper::new(graph);
    let result = match wrapper.compute_min_cut(algorithm) {
        Ok(r) => r,
        Err(e) => {
            return HttpResponse::InternalServerError().json(ErrorResponse {
                error: "Computation failed".to_string(),
                details: Some(e.to_string()),
            });
        }
    };

    let elapsed = start.elapsed();

    HttpResponse::Ok().json(MinCutResponse {
        cut_value: result.cut_value,
        partition1: result.partition1,
        partition2: result.partition2,
        cut_edges: result.cut_edges,
        algorithm: format!("{:?}", algorithm),
        computation_time_ms: elapsed.as_secs_f64() * 1000.0,
    })
}

// Connectivity curve endpoint
async fn connectivity_curve(req: web::Json<ConnectivityRequest>) -> HttpResponse {
    let start = std::time::Instant::now();

    // Build graph
    let mut builder = GraphBuilder::new();
    for edge in &req.edges {
        builder.add_edge(edge.from, edge.to, edge.weight);
    }

    let graph = match builder.build() {
        Ok(g) => g,
        Err(e) => {
            return HttpResponse::BadRequest().json(ErrorResponse {
                error: "Failed to build graph".to_string(),
                details: Some(e.to_string()),
            });
        }
    };

    // Compute connectivity curve
    let mut wrapper = MinCutWrapper::new(graph);
    let curve = match wrapper.compute_connectivity_curve(req.max_clusters) {
        Ok(c) => c,
        Err(e) => {
            return HttpResponse::InternalServerError().json(ErrorResponse {
                error: "Computation failed".to_string(),
                details: Some(e.to_string()),
            });
        }
    };

    let elapsed = start.elapsed();

    let response_curve: Vec<ConnectivityPoint> = curve
        .into_iter()
        .map(|point| ConnectivityPoint {
            num_clusters: point.num_clusters,
            cut_value: point.cut_value,
        })
        .collect();

    HttpResponse::Ok().json(ConnectivityResponse {
        curve: response_curve,
        computation_time_ms: elapsed.as_secs_f64() * 1000.0,
    })
}

// List available algorithms
async fn list_algorithms() -> HttpResponse {
    HttpResponse::Ok().json(serde_json::json!({
        "algorithms": [
            {
                "name": "StoerWagner",
                "description": "Exact algorithm with O(V³) time complexity",
                "exact": true
            },
            {
                "name": "FlowBased",
                "description": "Maximum flow based algorithm",
                "exact": true
            },
            {
                "name": "KargerStein",
                "description": "Randomized algorithm with high probability guarantees",
                "exact": false
            },
            {
                "name": "NagamochiIbaraki",
                "description": "O(VE + V²log V) deterministic algorithm",
                "exact": true
            },
            {
                "name": "Hierarchical",
                "description": "Hierarchical clustering based approach",
                "exact": false
            }
        ]
    }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

    let port = std::env::var("PORT")
        .unwrap_or_else(|_| "8080".to_string())
        .parse::<u16>()
        .expect("Invalid PORT");

    log::info!("Starting MinCut API server on port {}", port);

    HttpServer::new(|| {
        App::new()
            .wrap(middleware::Logger::default())
            .wrap(middleware::Compress::default())
            .route("/health", web::get().to(health))
            .route("/api/mincut", web::post().to(compute_min_cut))
            .route("/api/connectivity", web::post().to(connectivity_curve))
            .route("/api/algorithms", web::get().to(list_algorithms))
    })
    .bind(("0.0.0.0", port))?
    .run()
    .await
}

API Client Example

// client/mincut-api-client.ts
export interface Edge {
    from: number;
    to: number;
    weight: number;
}

export interface MinCutResult {
    cutValue: number;
    partition1: number[];
    partition2: number[];
    cutEdges: Array<[number, number]>;
    algorithm: string;
    computationTimeMs: number;
}

export interface ConnectivityPoint {
    numClusters: number;
    cutValue: number;
}

export class MinCutAPIClient {
    constructor(private baseUrl: string = 'http://localhost:8080') {}

    async computeMinCut(
        edges: Edge[],
        algorithm?: string
    ): Promise<MinCutResult> {
        const response = await fetch(`${this.baseUrl}/api/mincut`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ edges, algorithm })
        });

        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || 'API request failed');
        }

        return response.json();
    }

    async computeConnectivityCurve(
        edges: Edge[],
        maxClusters?: number
    ): Promise<{ curve: ConnectivityPoint[]; computationTimeMs: number }> {
        const response = await fetch(`${this.baseUrl}/api/connectivity`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ edges, max_clusters: maxClusters })
        });

        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || 'API request failed');
        }

        return response.json();
    }

    async listAlgorithms(): Promise<any> {
        const response = await fetch(`${this.baseUrl}/api/algorithms`);
        return response.json();
    }
}

// Usage
const client = new MinCutAPIClient();

const edges = [
    { from: 0, to: 1, weight: 1.0 },
    { from: 1, to: 2, weight: 1.0 },
    { from: 2, to: 0, weight: 1.0 }
];

const result = await client.computeMinCut(edges, 'StoerWagner');
console.log(result);

GraphQL Integration

Schema Definition

# schema.graphql
type Query {
  """Get available algorithms"""
  algorithms: [Algorithm!]!

  """Check service health"""
  health: HealthStatus!
}

type Mutation {
  """Compute minimum cut for a graph"""
  computeMinCut(input: MinCutInput!): MinCutResult!

  """Compute connectivity curve"""
  computeConnectivityCurve(input: ConnectivityInput!): ConnectivityCurve!

  """Compute local k-cut around a source node"""
  computeLocalKCut(input: LocalKCutInput!): MinCutResult!
}

input EdgeInput {
  from: Int!
  to: Int!
  weight: Float!
}

input MinCutInput {
  edges: [EdgeInput!]!
  algorithm: AlgorithmType = STOER_WAGNER
}

input ConnectivityInput {
  edges: [EdgeInput!]!
  maxClusters: Int
}

input LocalKCutInput {
  edges: [EdgeInput!]!
  k: Int!
  sourceNode: Int!
}

enum AlgorithmType {
  STOER_WAGNER
  FLOW_BASED
  KARGER_STEIN
  NAGAMOCHI_IBARAKI
  HIERARCHICAL
}

type Algorithm {
  name: String!
  description: String!
  exact: Boolean!
  timeComplexity: String!
}

type MinCutResult {
  cutValue: Float!
  partition1: [Int!]!
  partition2: [Int!]!
  cutEdges: [[Int!]!]!
  algorithm: String!
  computationTimeMs: Float!
}

type ConnectivityPoint {
  numClusters: Int!
  cutValue: Float!
}

type ConnectivityCurve {
  curve: [ConnectivityPoint!]!
  computationTimeMs: Float!
}

type HealthStatus {
  status: String!
  version: String!
}

Resolver Implementation

// src/graphql/mod.rs
use async_graphql::{
    Context, Object, Schema, EmptySubscription, SimpleObject, Enum, InputObject
};
use ruvector_mincut::{MinCutWrapper, MinCutAlgorithm};
use ruvector_mincut::graph::GraphBuilder;

#[derive(InputObject)]
struct EdgeInput {
    from: usize,
    to: usize,
    weight: f64,
}

#[derive(InputObject)]
struct MinCutInput {
    edges: Vec<EdgeInput>,
    #[graphql(default)]
    algorithm: AlgorithmType,
}

#[derive(InputObject)]
struct ConnectivityInput {
    edges: Vec<EdgeInput>,
    max_clusters: Option<usize>,
}

#[derive(InputObject)]
struct LocalKCutInput {
    edges: Vec<EdgeInput>,
    k: usize,
    source_node: usize,
}

#[derive(Enum, Copy, Clone, Eq, PartialEq)]
enum AlgorithmType {
    StoerWagner,
    FlowBased,
    KargerStein,
    NagamochiIbaraki,
    Hierarchical,
}

impl From<AlgorithmType> for MinCutAlgorithm {
    fn from(algo: AlgorithmType) -> Self {
        match algo {
            AlgorithmType::StoerWagner => MinCutAlgorithm::StoerWagner,
            AlgorithmType::FlowBased => MinCutAlgorithm::FlowBased,
            AlgorithmType::KargerStein => MinCutAlgorithm::KargerStein,
            AlgorithmType::NagamochiIbaraki => MinCutAlgorithm::NagamochiIbaraki,
            AlgorithmType::Hierarchical => MinCutAlgorithm::Hierarchical,
        }
    }
}

#[derive(SimpleObject)]
struct Algorithm {
    name: String,
    description: String,
    exact: bool,
    time_complexity: String,
}

#[derive(SimpleObject)]
struct MinCutResultGQL {
    cut_value: f64,
    partition1: Vec<usize>,
    partition2: Vec<usize>,
    cut_edges: Vec<Vec<usize>>,
    algorithm: String,
    computation_time_ms: f64,
}

#[derive(SimpleObject)]
struct ConnectivityPointGQL {
    num_clusters: usize,
    cut_value: f64,
}

#[derive(SimpleObject)]
struct ConnectivityCurveGQL {
    curve: Vec<ConnectivityPointGQL>,
    computation_time_ms: f64,
}

#[derive(SimpleObject)]
struct HealthStatus {
    status: String,
    version: String,
}

pub struct QueryRoot;

#[Object]
impl QueryRoot {
    async fn algorithms(&self) -> Vec<Algorithm> {
        vec![
            Algorithm {
                name: "StoerWagner".to_string(),
                description: "Exact algorithm with O(V³) time complexity".to_string(),
                exact: true,
                time_complexity: "O(V³)".to_string(),
            },
            Algorithm {
                name: "FlowBased".to_string(),
                description: "Maximum flow based algorithm".to_string(),
                exact: true,
                time_complexity: "O(V²E)".to_string(),
            },
            Algorithm {
                name: "KargerStein".to_string(),
                description: "Randomized algorithm with high probability".to_string(),
                exact: false,
                time_complexity: "O(V²log³V)".to_string(),
            },
            Algorithm {
                name: "NagamochiIbaraki".to_string(),
                description: "Deterministic near-linear algorithm".to_string(),
                exact: true,
                time_complexity: "O(VE + V²log V)".to_string(),
            },
            Algorithm {
                name: "Hierarchical".to_string(),
                description: "Hierarchical clustering approach".to_string(),
                exact: false,
                time_complexity: "O(V²log V)".to_string(),
            },
        ]
    }

    async fn health(&self) -> HealthStatus {
        HealthStatus {
            status: "healthy".to_string(),
            version: env!("CARGO_PKG_VERSION").to_string(),
        }
    }
}

pub struct MutationRoot;

#[Object]
impl MutationRoot {
    async fn compute_min_cut(&self, input: MinCutInput) -> async_graphql::Result<MinCutResultGQL> {
        let start = std::time::Instant::now();

        // Build graph
        let mut builder = GraphBuilder::new();
        for edge in input.edges {
            builder.add_edge(edge.from, edge.to, edge.weight);
        }
        let graph = builder.build()?;

        // Compute minimum cut
        let mut wrapper = MinCutWrapper::new(graph);
        let result = wrapper.compute_min_cut(input.algorithm.into())?;

        let elapsed = start.elapsed();

        Ok(MinCutResultGQL {
            cut_value: result.cut_value,
            partition1: result.partition1,
            partition2: result.partition2,
            cut_edges: result.cut_edges.into_iter()
                .map(|(a, b)| vec![a, b])
                .collect(),
            algorithm: format!("{:?}", input.algorithm),
            computation_time_ms: elapsed.as_secs_f64() * 1000.0,
        })
    }

    async fn compute_connectivity_curve(
        &self,
        input: ConnectivityInput
    ) -> async_graphql::Result<ConnectivityCurveGQL> {
        let start = std::time::Instant::now();

        // Build graph
        let mut builder = GraphBuilder::new();
        for edge in input.edges {
            builder.add_edge(edge.from, edge.to, edge.weight);
        }
        let graph = builder.build()?;

        // Compute connectivity curve
        let mut wrapper = MinCutWrapper::new(graph);
        let curve = wrapper.compute_connectivity_curve(input.max_clusters)?;

        let elapsed = start.elapsed();

        Ok(ConnectivityCurveGQL {
            curve: curve.into_iter()
                .map(|p| ConnectivityPointGQL {
                    num_clusters: p.num_clusters,
                    cut_value: p.cut_value,
                })
                .collect(),
            computation_time_ms: elapsed.as_secs_f64() * 1000.0,
        })
    }

    async fn compute_local_k_cut(
        &self,
        input: LocalKCutInput
    ) -> async_graphql::Result<MinCutResultGQL> {
        let start = std::time::Instant::now();

        // Build graph
        let mut builder = GraphBuilder::new();
        for edge in input.edges {
            builder.add_edge(edge.from, edge.to, edge.weight);
        }
        let graph = builder.build()?;

        // Compute local k-cut
        let mut wrapper = MinCutWrapper::new(graph);
        let result = wrapper.compute_local_k_cut(input.k, input.source_node)?;

        let elapsed = start.elapsed();

        Ok(MinCutResultGQL {
            cut_value: result.cut_value,
            partition1: result.partition1,
            partition2: result.partition2,
            cut_edges: result.cut_edges.into_iter()
                .map(|(a, b)| vec![a, b])
                .collect(),
            algorithm: "LocalKCut".to_string(),
            computation_time_ms: elapsed.as_secs_f64() * 1000.0,
        })
    }
}

pub type MinCutSchema = Schema<QueryRoot, MutationRoot, EmptySubscription>;

pub fn create_schema() -> MinCutSchema {
    Schema::build(QueryRoot, MutationRoot, EmptySubscription).finish()
}

GraphQL Server

// src/graphql_server.rs
use actix_web::{web, App, HttpServer, guard, middleware};
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};

mod graphql;
use graphql::create_schema;

async fn graphql_playground() -> actix_web::HttpResponse {
    actix_web::HttpResponse::Ok()
        .content_type("text/html; charset=utf-8")
        .body(playground_source(
            GraphQLPlaygroundConfig::new("/graphql")
        ))
}

async fn graphql_handler(
    schema: web::Data<graphql::MinCutSchema>,
    req: GraphQLRequest,
) -> GraphQLResponse {
    schema.execute(req.into_inner()).await.into()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

    let schema = create_schema();

    log::info!("GraphQL Playground: http://localhost:8080/playground");

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(schema.clone()))
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/graphql")
                    .guard(guard::Post())
                    .to(graphql_handler)
            )
            .service(
                web::resource("/playground")
                    .guard(guard::Get())
                    .to(graphql_playground)
            )
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}

Architecture Patterns

WASM Browser Deployment

graph TB
    subgraph "Browser Environment"
        UI[Web UI<br/>React/Vue/Svelte]
        Worker[Web Worker<br/>WASM Runtime]
        Canvas[Canvas<br/>Visualization]
    end

    subgraph "WASM Module"
        WasmBind[wasm-bindgen<br/>JS Bindings]
        MinCut[MinCut Algorithms<br/>Rust Core]
        Graph[Graph Structures]
    end

    UI -->|Post Message| Worker
    Worker -->|Load & Initialize| WasmBind
    WasmBind -->|Call| MinCut
    MinCut -->|Use| Graph
    Worker -->|Results| UI
    UI -->|Render| Canvas

    style UI fill:#3498db
    style Worker fill:#2ecc71
    style WasmBind fill:#e74c3c
    style MinCut fill:#f39c12

Node.js Server Architecture

graph TB
    subgraph "Client Layer"
        Web[Web Clients]
        Mobile[Mobile Apps]
        CLI[CLI Tools]
    end

    subgraph "API Layer"
        REST[REST API<br/>Express/Fastify]
        GraphQL[GraphQL API<br/>Apollo Server]
        WS[WebSocket<br/>Real-time]
    end

    subgraph "Service Layer"
        Pool[Worker Pool<br/>Thread Pool]
        Cache[Redis Cache<br/>Results]
        Queue[Task Queue<br/>Bull/BullMQ]
    end

    subgraph "Core Layer"
        Native[Native Module<br/>ruvector-mincut-node]
        Rust[Rust Core<br/>MinCut Algorithms]
    end

    Web --> REST
    Mobile --> GraphQL
    CLI --> REST

    REST --> Pool
    GraphQL --> Pool
    WS --> Queue

    Pool --> Cache
    Pool --> Native
    Queue --> Native
    Native --> Rust

    style Web fill:#3498db
    style REST fill:#2ecc71
    style Pool fill:#e74c3c
    style Native fill:#f39c12

Microservice Integration

graph TB
    subgraph "API Gateway"
        Gateway[Kong/Traefik<br/>API Gateway]
    end

    subgraph "MinCut Service"
        API[MinCut API<br/>Actix-Web]
        Compute[Compute Workers<br/>Rayon Thread Pool]
        Cache[Local Cache<br/>LRU]
    end

    subgraph "Supporting Services"
        Graph[Graph Service<br/>ruvector-graph]
        Metrics[Metrics<br/>Prometheus]
        Trace[Tracing<br/>Jaeger]
    end

    subgraph "Storage Layer"
        DB[(Graph Database<br/>Neo4j/AgentDB)]
        Object[(Object Storage<br/>S3/MinIO)]
    end

    Gateway --> API
    API --> Compute
    API --> Cache
    API --> Graph
    API --> Metrics
    API --> Trace

    Graph --> DB
    Compute --> Object

    style Gateway fill:#3498db
    style API fill:#2ecc71
    style Compute fill:#e74c3c
    style Graph fill:#f39c12
    style DB fill:#9b59b6

Distributed Processing

graph TB
    subgraph "Load Balancer"
        LB[HAProxy/Nginx]
    end

    subgraph "Service Instances"
        S1[MinCut Service 1]
        S2[MinCut Service 2]
        S3[MinCut Service 3]
    end

    subgraph "Message Queue"
        Queue[RabbitMQ/Kafka<br/>Task Distribution]
    end

    subgraph "Worker Nodes"
        W1[Worker 1<br/>GPU Acceleration]
        W2[Worker 2<br/>CPU Intensive]
        W3[Worker 3<br/>Memory Optimized]
    end

    subgraph "Coordination"
        Coord[Coordinator<br/>Task Scheduling]
        Monitor[Monitor<br/>Health Checks]
    end

    LB --> S1
    LB --> S2
    LB --> S3

    S1 --> Queue
    S2 --> Queue
    S3 --> Queue

    Queue --> Coord
    Coord --> W1
    Coord --> W2
    Coord --> W3

    Monitor --> S1
    Monitor --> S2
    Monitor --> S3
    Monitor --> W1
    Monitor --> W2
    Monitor --> W3

    style LB fill:#3498db
    style Queue fill:#2ecc71
    style Coord fill:#e74c3c
    style W1 fill:#f39c12

Integration with ruvector-graph

For graph database features and persistent storage, integrate with ruvector-graph:

use ruvector_mincut::MinCutWrapper;
use ruvector_graph::{GraphDB, Query};

// Load graph from database
let db = GraphDB::connect("localhost:7687")?;
let graph = db.query("MATCH (n)-[r]-(m) RETURN n, r, m")?;

// Compute minimum cut
let mut wrapper = MinCutWrapper::new(graph);
let result = wrapper.compute_min_cut(MinCutAlgorithm::StoerWagner)?;

// Store results back to database
db.execute(
    "CREATE (r:MinCutResult {value: $value})",
    &[("value", result.cut_value)]
)?;

Best Practices

Performance Optimization

  1. Use Web Workers for WASM - Keep UI responsive
  2. Worker Pools for Node.js - Utilize all CPU cores
  3. Caching - Cache results for identical graphs
  4. Batch Processing - Process multiple graphs in parallel
  5. Algorithm Selection - Choose appropriate algorithm for graph size

Error Handling

try {
    const result = await computeMinCut(edges);
} catch (error) {
    if (error.message.includes('memory')) {
        // Graph too large, try different algorithm
    } else if (error.message.includes('timeout')) {
        // Computation timeout, use approximate algorithm
    } else {
        // Other errors
    }
}

Security Considerations

  1. Input Validation - Validate graph size limits
  2. Rate Limiting - Prevent abuse of compute resources
  3. Timeout Protection - Set computation timeouts
  4. Resource Limits - Limit memory usage per request

Next Steps