Skip to main content

ruvector_mincut/
lib.rs

1//! # RuVector MinCut
2//!
3//! Subpolynomial-time dynamic minimum cut algorithm with real-time monitoring.
4//!
5//! This crate provides efficient algorithms for maintaining minimum cuts in
6//! dynamic graphs with edge insertions and deletions.
7//!
8//! ## Features
9//!
10//! - **Exact Algorithm**: O(n^{o(1)}) amortized update time for cuts up to 2^{O((log n)^{3/4})}
11//! - **Approximate Algorithm**: (1+ε)-approximate cuts via graph sparsification
12//! - **Real-Time Monitoring**: Event-driven notifications with configurable thresholds
13//! - **Thread-Safe**: Concurrent reads with exclusive writes
14//!
15//! ## Quick Start
16//!
17//! ```rust,no_run
18//! use ruvector_mincut::{MinCutBuilder, DynamicMinCut};
19//!
20//! // Create a dynamic minimum cut structure
21//! let mut mincut = MinCutBuilder::new()
22//!     .exact()
23//!     .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)])
24//!     .build()
25//!     .expect("Failed to build");
26//!
27//! // Query the minimum cut
28//! println!("Min cut: {}", mincut.min_cut_value());
29//!
30//! // Insert a new edge
31//! mincut.insert_edge(3, 4, 1.0).expect("Insert failed");
32//!
33//! // Delete an existing edge
34//! let _ = mincut.delete_edge(2, 3);
35//! ```
36//!
37//! ## Architecture
38//!
39//! The crate is organized into several modules:
40//!
41//! - [`graph`]: Dynamic graph representation with efficient operations
42//! - [`algorithm`]: Core minimum cut algorithms (exact and approximate)
43//! - [`tree`]: Hierarchical decomposition for subpolynomial updates
44//! - [`linkcut`]: Link-cut trees for dynamic connectivity
45//! - [`euler`]: Euler tour trees for tree operations
46//! - [`sparsify`]: Graph sparsification for approximate cuts
47//! - [`expander`]: Expander decomposition for subpolynomial updates
48//! - `monitoring`: Real-time event monitoring (feature-gated)
49//!
50//! ## Feature Flags
51//!
52//! - `exact` - Exact minimum cut algorithm (enabled by default)
53//! - `approximate` - (1+ε)-approximate algorithm (enabled by default)
54//! - `monitoring` - Real-time monitoring with callbacks (optional)
55//! - `integration` - GraphDB integration (optional)
56//! - `simd` - SIMD optimizations (optional)
57//!
58//! ## Examples
59//!
60//! ### Basic Usage
61//!
62//! ```rust
63//! use ruvector_mincut::prelude::*;
64//!
65//! let mut mincut = MinCutBuilder::new()
66//!     .with_edges(vec![
67//!         (1, 2, 1.0),
68//!         (2, 3, 1.0),
69//!         (3, 1, 1.0),
70//!     ])
71//!     .build()
72//!     .unwrap();
73//!
74//! assert_eq!(mincut.min_cut_value(), 2.0);
75//! ```
76//!
77//! ### Approximate Algorithm
78//!
79//! ```rust
80//! use ruvector_mincut::prelude::*;
81//!
82//! let mincut = MinCutBuilder::new()
83//!     .approximate(0.1) // 10% approximation
84//!     .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0)])
85//!     .build()
86//!     .unwrap();
87//!
88//! let result = mincut.min_cut();
89//! assert!(!result.is_exact);
90//! assert_eq!(result.approximation_ratio, 1.1);
91//! ```
92//!
93//! ### Real-Time Monitoring
94//!
95//! ```rust,ignore
96//! #[cfg(feature = "monitoring")]
97//! use ruvector_mincut::{MinCutBuilder, MonitorBuilder, EventType};
98//!
99//! let mut mincut = MinCutBuilder::new()
100//!     .with_edges(vec![(1, 2, 1.0)])
101//!     .build()
102//!     .unwrap();
103//!
104//! let monitor = MonitorBuilder::new()
105//!     .threshold("low", 0.5, true)
106//!     .on_event(|event| {
107//!         println!("Cut changed: {:?}", event.event_type);
108//!     })
109//!     .build();
110//!
111//! // Monitor will fire callbacks on updates
112//! mincut.insert_edge(2, 3, 1.0).unwrap();
113//! ```
114
115#![deny(missing_docs)]
116#![cfg_attr(not(feature = "wasm"), deny(unsafe_code))]
117#![warn(clippy::all)]
118#![warn(clippy::pedantic)]
119#![allow(clippy::module_name_repetitions)]
120#![allow(clippy::missing_errors_doc)]
121#![allow(clippy::missing_panics_doc)]
122
123// Core modules
124pub mod algorithm;
125pub mod certificate;
126pub mod cluster;
127pub mod compact;
128pub mod connectivity;
129pub mod error;
130pub mod euler;
131pub mod expander;
132pub mod fragment;
133pub mod fragmentation;
134pub mod graph;
135pub mod instance;
136pub mod integration;
137pub mod linkcut;
138pub mod localkcut;
139pub mod parallel;
140pub mod pool;
141pub mod sparsify;
142pub mod tree;
143pub mod witness;
144pub mod wrapper;
145
146/// Performance optimizations for j-Tree + BMSSP implementation.
147///
148/// Provides SOTA optimizations achieving 10x combined speedup.
149pub mod optimization;
150
151/// Spiking Neural Network integration for deep MinCut optimization.
152///
153/// This module implements a six-layer integration architecture combining
154/// neuromorphic computing with subpolynomial graph algorithms:
155///
156/// 1. **Temporal Attractors**: Energy landscapes for graph optimization
157/// 2. **Strange Loop**: Self-modifying meta-cognitive protocols
158/// 3. **Causal Discovery**: Spike-timing based inference
159/// 4. **Time Crystal CPG**: Central pattern generators for coordination
160/// 5. **Morphogenetic Networks**: Bio-inspired self-organizing growth
161/// 6. **Neural Optimizer**: Reinforcement learning on graph structures
162///
163/// ## Quick Start
164///
165/// ```rust,no_run
166/// use ruvector_mincut::snn::{CognitiveMinCutEngine, EngineConfig, OperationMode};
167/// use ruvector_mincut::graph::DynamicGraph;
168///
169/// // Create a graph
170/// let graph = DynamicGraph::new();
171/// graph.insert_edge(0, 1, 1.0).unwrap();
172/// graph.insert_edge(1, 2, 1.0).unwrap();
173///
174/// // Create the cognitive engine
175/// let config = EngineConfig::default();
176/// let mut engine = CognitiveMinCutEngine::new(graph, config);
177///
178/// // Run optimization
179/// engine.set_mode(OperationMode::Optimize);
180/// let spikes = engine.run(100);
181/// ```
182pub mod snn;
183
184/// Subpolynomial-time dynamic minimum cut algorithm.
185///
186/// This module implements the December 2024 breakthrough achieving n^{o(1)} update time.
187/// Integrates multi-level hierarchy, deterministic LocalKCut, and fragmenting algorithm.
188pub mod subpolynomial;
189
190/// Dynamic Hierarchical j-Tree Decomposition for Approximate Cut Structure
191///
192/// This module implements the two-tier dynamic cut architecture from ADR-002:
193///
194/// - **Tier 1 (j-Tree)**: O(n^ε) amortized updates, poly-log approximation
195/// - **Tier 2 (Exact)**: SubpolynomialMinCut for exact verification
196///
197/// Key features:
198/// - BMSSP WASM integration for O(m·log^(2/3) n) path-cut duality queries
199/// - Vertex-split-tolerant cut sparsifier with O(log² n / ε²) recourse
200/// - Lazy hierarchical evaluation (demand-paging)
201///
202/// ## Example
203///
204/// ```rust,no_run
205/// use ruvector_mincut::jtree::{JTreeHierarchy, JTreeConfig};
206/// use ruvector_mincut::graph::DynamicGraph;
207/// use std::sync::Arc;
208///
209/// let graph = Arc::new(DynamicGraph::new());
210/// graph.insert_edge(1, 2, 1.0).unwrap();
211/// graph.insert_edge(2, 3, 1.0).unwrap();
212///
213/// let mut jtree = JTreeHierarchy::build(graph, JTreeConfig::default()).unwrap();
214/// let approx = jtree.approximate_min_cut().unwrap();
215/// ```
216#[cfg(feature = "jtree")]
217pub mod jtree;
218
219// Internal modules
220mod core;
221
222// Optional feature-gated modules
223#[cfg(feature = "monitoring")]
224pub mod monitoring;
225
226#[cfg(feature = "wasm")]
227pub mod wasm;
228
229// Re-exports for convenient access
230pub use algorithm::approximate::{
231    ApproxMinCut, ApproxMinCutConfig, ApproxMinCutResult, ApproxMinCutStats,
232};
233pub use algorithm::{AlgorithmStats, DynamicMinCut, MinCutBuilder, MinCutConfig, MinCutResult};
234pub use certificate::{
235    AuditData, AuditEntry, AuditEntryType, AuditLogger, CertLocalKCutQuery, CertificateError,
236    CutCertificate, LocalKCutResponse, LocalKCutResultSummary, UpdateTrigger, UpdateType,
237};
238pub use cluster::hierarchy::{
239    Expander, HierarchyCluster, HierarchyConfig, HierarchyStats, MirrorCut, Precluster,
240    ThreeLevelHierarchy,
241};
242pub use cluster::{Cluster, ClusterHierarchy};
243pub use compact::{
244    BitSet256, CompactAdjacency, CompactCoreState, CompactEdge, CompactEdgeId, CompactVertexId,
245    CompactWitness, CoreResult, MAX_EDGES_PER_CORE, MAX_VERTICES_PER_CORE,
246};
247pub use connectivity::polylog::{PolylogConnectivity, PolylogStats};
248pub use connectivity::DynamicConnectivity;
249pub use error::{MinCutError, Result};
250pub use euler::EulerTourTree;
251pub use expander::{Conductance, ExpanderComponent, ExpanderDecomposition};
252pub use fragment::{Fragment, FragmentResult, FragmentingAlgorithm};
253pub use fragmentation::{
254    Fragment as FragmentationFragment, Fragmentation, FragmentationConfig, TrimResult,
255};
256pub use graph::{DynamicGraph, Edge, EdgeId, GraphStats, VertexId, Weight};
257pub use instance::{
258    BoundedInstance, InstanceResult, ProperCutInstance, StubInstance, WitnessHandle,
259};
260pub use integration::{CommunityDetector, GraphPartitioner, RuVectorGraphAnalyzer};
261pub use linkcut::LinkCutTree;
262pub use localkcut::{
263    ColorMask, DeterministicFamilyGenerator, DeterministicLocalKCut, EdgeColor, ForestPacking,
264    LocalCutResult, LocalKCut, LocalKCutOracle, LocalKCutQuery,
265    LocalKCutResult as PaperLocalKCutResult,
266};
267pub use parallel::{
268    compute_core_range, CoreDistributor, CoreExecutor, CoreMessage, CoreStrategy, ResultAggregator,
269    SharedCoordinator, WorkItem, NUM_CORES, RANGES_PER_CORE, RANGE_FACTOR, TOTAL_RANGES,
270};
271pub use sparsify::{SparseGraph, SparsifyConfig};
272pub use subpolynomial::{
273    HierarchyLevel, HierarchyStatistics, LevelExpander, MinCutQueryResult, RecourseStats,
274    SubpolyConfig, SubpolynomialMinCut,
275};
276pub use tree::{DecompositionNode, HierarchicalDecomposition, LevelInfo};
277pub use witness::{EdgeWitness, LazyWitnessTree, WitnessTree};
278pub use wrapper::MinCutWrapper;
279
280// Optimization re-exports (SOTA j-Tree + BMSSP performance improvements)
281pub use optimization::{
282    BatchConfig,
283    BenchmarkResult,
284    // Benchmarking
285    BenchmarkSuite,
286    CacheConfig,
287    CacheStats,
288    // DSpar: 5.9x speedup via degree-based presparse
289    DegreePresparse,
290    DistanceArray,
291    LazyLevel,
292    // Pool: 50-75% memory reduction
293    LevelPool,
294    OptimizationBenchmark,
295    ParallelConfig,
296    // Parallel: Rayon-based work-stealing
297    ParallelLevelUpdater,
298    // Cache: 10x for repeated distance queries
299    PathDistanceCache,
300    PoolConfig,
301    PoolStats,
302    PrefetchHint,
303    PresparseConfig,
304    PresparseResult,
305    PresparseStats,
306    // SIMD: 2-4x for distance operations
307    SimdDistanceOps,
308    TypedArrayTransfer,
309    // WASM Batch: 10x FFI overhead reduction
310    WasmBatchOps,
311    WorkStealingScheduler,
312};
313
314// J-Tree re-exports (feature-gated)
315#[cfg(feature = "jtree")]
316pub use jtree::{
317    ApproximateCut, BmsspJTreeLevel, ContractedGraph, CutResult as JTreeCutResult,
318    DynamicCutSparsifier, EscalationPolicy, EscalationTrigger, JTreeConfig, JTreeError,
319    JTreeHierarchy, JTreeLevel, JTreeStatistics, LevelConfig, LevelStatistics, PathCutResult,
320    QueryResult as CoordinatorQueryResult, RecourseTracker, SparsifierConfig, SparsifierStatistics,
321    Tier, TierMetrics, TwoTierCoordinator, VertexSplitResult,
322};
323
324// Re-export ForestPacking with explicit disambiguation (also defined in localkcut)
325#[cfg(feature = "jtree")]
326pub use jtree::ForestPacking as JTreeForestPacking;
327
328// SNN Integration re-exports
329pub use snn::{
330    AttractorConfig,
331    // Layer 1: Attractors
332    AttractorDynamics,
333    CPGConfig,
334    CausalConfig,
335    // Layer 3: Causal Discovery
336    CausalDiscoverySNN,
337    CausalGraph,
338    CausalRelation,
339    // Unified Engine
340    CognitiveMinCutEngine,
341    EnergyLandscape,
342    EngineConfig,
343    EngineMetrics,
344    GrowthRules,
345    // Core SNN types
346    LIFNeuron,
347    LayerConfig,
348    MetaAction,
349    // Layer 2: Strange Loop
350    MetaCognitiveMinCut,
351    MetaLevel,
352    MorphConfig,
353    // Layer 5: Morphogenetic
354    MorphogeneticSNN,
355    NetworkConfig,
356    // Layer 6: Neural Optimizer
357    NeuralGraphOptimizer,
358    NeuronConfig,
359    NeuronState,
360    OptimizationResult,
361    OptimizerConfig,
362    OscillatorNeuron,
363    PhaseTopology,
364    PolicySNN,
365    SNNMinCutConfig,
366    STDPConfig,
367    SimTime,
368    // Utilities
369    Spike,
370    SpikeTrain,
371    SpikingNetwork,
372    StrangeLoopConfig,
373    Synapse,
374    SynapseMatrix,
375    // Layer 4: Time Crystal
376    TimeCrystalCPG,
377    TuringPattern,
378    ValueNetwork,
379};
380
381#[cfg(feature = "agentic")]
382pub use integration::AgenticAnalyzer;
383
384#[cfg(feature = "monitoring")]
385pub use monitoring::{
386    EventType, MinCutEvent, MinCutMonitor, MonitorBuilder, MonitorConfig, MonitorMetrics, Threshold,
387};
388
389/// Crate version
390pub const VERSION: &str = env!("CARGO_PKG_VERSION");
391
392/// Crate name
393pub const NAME: &str = env!("CARGO_PKG_NAME");
394
395/// Prelude module for convenient imports
396///
397/// Import this module to get all the commonly used types and traits:
398///
399/// ```rust
400/// use ruvector_mincut::prelude::*;
401///
402/// let mincut = MinCutBuilder::new()
403///     .exact()
404///     .build()
405///     .unwrap();
406/// ```
407pub mod prelude {
408    //! Prelude module with commonly used types
409
410    pub use crate::{
411        compute_core_range,
412        AlgorithmStats,
413        ApproxMinCut,
414        ApproxMinCutConfig,
415        AttractorConfig,
416        AttractorDynamics,
417        AuditLogger,
418        BitSet256,
419        BoundedInstance,
420        CPGConfig,
421        CertificateError,
422        Cluster,
423        ClusterHierarchy,
424        // SNN Integration types
425        CognitiveMinCutEngine,
426        ColorMask,
427        CommunityDetector,
428        CompactAdjacency,
429        CompactCoreState,
430        CompactEdge,
431        CompactEdgeId,
432        CompactVertexId,
433        CompactWitness,
434        Conductance,
435        CoreDistributor,
436        CoreExecutor,
437        CoreResult,
438        CoreStrategy,
439        CutCertificate,
440        DeterministicFamilyGenerator,
441        DeterministicLocalKCut,
442        DynamicConnectivity,
443        DynamicGraph,
444        DynamicMinCut,
445        Edge,
446        EdgeColor,
447        EdgeId,
448        EngineConfig,
449        EngineMetrics,
450        ExpanderComponent,
451        ExpanderDecomposition,
452        ForestPacking,
453        Fragment,
454        FragmentResult,
455        FragmentingAlgorithm,
456        GraphPartitioner,
457        InstanceResult,
458        LocalCutResult,
459        LocalKCut,
460        LocalKCutOracle,
461        LocalKCutQuery,
462        MinCutBuilder,
463        MinCutConfig,
464        MinCutError,
465        MinCutResult,
466        MinCutWrapper,
467        NeuralGraphOptimizer,
468        OptimizerConfig,
469        PaperLocalKCutResult,
470        PolylogConnectivity,
471        PolylogStats,
472        ProperCutInstance,
473        RecourseStats,
474        Result,
475        ResultAggregator,
476        RuVectorGraphAnalyzer,
477        SharedCoordinator,
478        SimTime,
479        Spike,
480        StubInstance,
481        SubpolyConfig,
482        // Subpolynomial min-cut
483        SubpolynomialMinCut,
484        TimeCrystalCPG,
485        VertexId,
486        Weight,
487        WitnessHandle,
488        MAX_EDGES_PER_CORE,
489        MAX_VERTICES_PER_CORE,
490        NUM_CORES,
491        RANGES_PER_CORE,
492    };
493
494    #[cfg(feature = "agentic")]
495    pub use crate::AgenticAnalyzer;
496
497    #[cfg(feature = "monitoring")]
498    pub use crate::{EventType, MinCutEvent, MinCutMonitor, MonitorBuilder};
499
500    #[cfg(feature = "jtree")]
501    pub use crate::{
502        ApproximateCut, BmsspJTreeLevel, ContractedGraph, CoordinatorQueryResult,
503        DynamicCutSparsifier, EscalationPolicy, EscalationTrigger, JTreeConfig, JTreeCutResult,
504        JTreeError, JTreeForestPacking, JTreeHierarchy, JTreeLevel, JTreeStatistics, LevelConfig,
505        LevelStatistics, PathCutResult, RecourseTracker, SparsifierConfig, SparsifierStatistics,
506        Tier, TierMetrics, TwoTierCoordinator, VertexSplitResult,
507    };
508}
509
510#[cfg(test)]
511mod tests {
512    use super::*;
513
514    #[test]
515    fn test_version_constant() {
516        assert!(!VERSION.is_empty());
517        assert!(!NAME.is_empty());
518        assert_eq!(NAME, "ruvector-mincut");
519    }
520
521    #[test]
522    fn test_basic_workflow() {
523        // Test the main API works correctly
524        let mut mincut = MinCutBuilder::new()
525            .exact()
526            .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)])
527            .build()
528            .unwrap();
529
530        // Verify initial state
531        assert_eq!(mincut.num_vertices(), 3);
532        assert_eq!(mincut.num_edges(), 3);
533        assert_eq!(mincut.min_cut_value(), 2.0);
534
535        // Test insert
536        let new_cut = mincut.insert_edge(1, 4, 2.0).unwrap();
537        assert!(new_cut.is_finite());
538        assert_eq!(mincut.num_edges(), 4);
539
540        // Test delete
541        let new_cut = mincut.delete_edge(1, 2).unwrap();
542        assert!(new_cut.is_finite());
543        assert_eq!(mincut.num_edges(), 3);
544    }
545
546    #[test]
547    fn test_prelude_imports() {
548        use crate::prelude::*;
549
550        // Ensure all prelude items are accessible
551        let mincut = MinCutBuilder::new().build().unwrap();
552
553        assert_eq!(mincut.min_cut_value(), f64::INFINITY);
554    }
555
556    #[test]
557    fn test_approximate_mode() {
558        let mincut = MinCutBuilder::new()
559            .approximate(0.1)
560            .with_edges(vec![(1, 2, 1.0)])
561            .build()
562            .unwrap();
563
564        let result = mincut.min_cut();
565        assert!(!result.is_exact);
566        assert_eq!(result.approximation_ratio, 1.1);
567    }
568
569    #[test]
570    fn test_exact_mode() {
571        let mincut = MinCutBuilder::new()
572            .exact()
573            .with_edges(vec![(1, 2, 1.0)])
574            .build()
575            .unwrap();
576
577        let result = mincut.min_cut();
578        assert!(result.is_exact);
579        assert_eq!(result.approximation_ratio, 1.0);
580    }
581
582    #[test]
583    fn test_min_cut_result() {
584        let mincut = MinCutBuilder::new()
585            .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)])
586            .build()
587            .unwrap();
588
589        let result = mincut.min_cut();
590        assert_eq!(result.value, 2.0);
591        assert!(result.cut_edges.is_some());
592        assert!(result.partition.is_some());
593
594        if let Some((s, t)) = result.partition {
595            assert_eq!(s.len() + t.len(), 3);
596            assert!(!s.is_empty());
597            assert!(!t.is_empty());
598        }
599    }
600
601    #[test]
602    fn test_graph_stats() {
603        let mincut = MinCutBuilder::new()
604            .with_edges(vec![(1, 2, 2.0), (2, 3, 3.0), (3, 1, 1.0)])
605            .build()
606            .unwrap();
607
608        let graph = mincut.graph();
609        let stats = graph.read().stats();
610
611        assert_eq!(stats.num_vertices, 3);
612        assert_eq!(stats.num_edges, 3);
613        assert_eq!(stats.total_weight, 6.0);
614        assert_eq!(stats.min_degree, 2);
615        assert_eq!(stats.max_degree, 2);
616    }
617
618    #[test]
619    fn test_algorithm_stats() {
620        let mut mincut = MinCutBuilder::new()
621            .with_edges(vec![(1, 2, 1.0)])
622            .build()
623            .unwrap();
624
625        mincut.insert_edge(2, 3, 1.0).unwrap();
626        mincut.delete_edge(1, 2).unwrap();
627        let _ = mincut.min_cut_value();
628
629        let stats = mincut.stats();
630        assert_eq!(stats.insertions, 1);
631        assert_eq!(stats.deletions, 1);
632        assert_eq!(stats.queries, 1);
633        assert!(stats.avg_update_time_us > 0.0);
634    }
635
636    #[test]
637    fn test_dynamic_updates() {
638        let mut mincut = MinCutBuilder::new().build().unwrap();
639
640        // Start empty
641        assert_eq!(mincut.min_cut_value(), f64::INFINITY);
642
643        // Add edges dynamically
644        mincut.insert_edge(1, 2, 1.0).unwrap();
645        assert_eq!(mincut.min_cut_value(), 1.0);
646
647        mincut.insert_edge(2, 3, 1.0).unwrap();
648        assert_eq!(mincut.min_cut_value(), 1.0);
649
650        mincut.insert_edge(3, 1, 1.0).unwrap();
651        assert_eq!(mincut.min_cut_value(), 2.0);
652    }
653
654    #[test]
655    fn test_disconnected_graph() {
656        let mincut = MinCutBuilder::new()
657            .with_edges(vec![(1, 2, 1.0), (3, 4, 1.0)])
658            .build()
659            .unwrap();
660
661        assert!(!mincut.is_connected());
662        assert_eq!(mincut.min_cut_value(), 0.0);
663    }
664
665    #[test]
666    fn test_builder_pattern() {
667        let mincut = MinCutBuilder::new()
668            .exact()
669            .max_cut_size(500)
670            .parallel(true)
671            .with_edges(vec![(1, 2, 1.0)])
672            .build()
673            .unwrap();
674
675        assert!(!mincut.config().approximate);
676        assert_eq!(mincut.config().max_exact_cut_size, 500);
677        assert!(mincut.config().parallel);
678    }
679
680    #[test]
681    fn test_weighted_graph() {
682        let mincut = MinCutBuilder::new()
683            .with_edges(vec![(1, 2, 5.0), (2, 3, 3.0), (3, 1, 2.0)])
684            .build()
685            .unwrap();
686
687        assert_eq!(mincut.min_cut_value(), 5.0);
688    }
689
690    #[test]
691    fn test_error_handling() {
692        let mut mincut = MinCutBuilder::new()
693            .with_edges(vec![(1, 2, 1.0)])
694            .build()
695            .unwrap();
696
697        // Try to insert duplicate edge
698        let result = mincut.insert_edge(1, 2, 2.0);
699        assert!(result.is_err());
700        assert!(matches!(result, Err(MinCutError::EdgeExists(1, 2))));
701
702        // Try to delete non-existent edge
703        let result = mincut.delete_edge(3, 4);
704        assert!(result.is_err());
705        assert!(matches!(result, Err(MinCutError::EdgeNotFound(3, 4))));
706    }
707
708    #[test]
709    fn test_large_graph() {
710        let mut edges = Vec::new();
711        for i in 0..99 {
712            edges.push((i, i + 1, 1.0));
713        }
714
715        let mincut = MinCutBuilder::new().with_edges(edges).build().unwrap();
716
717        assert_eq!(mincut.num_vertices(), 100);
718        assert_eq!(mincut.num_edges(), 99);
719        assert_eq!(mincut.min_cut_value(), 1.0);
720    }
721
722    #[cfg(feature = "monitoring")]
723    #[test]
724    fn test_monitoring_feature() {
725        use crate::monitoring::EventType;
726
727        // Ensure monitoring types are accessible when feature is enabled
728        let _ = EventType::CutIncreased;
729        let _ = EventType::CutDecreased;
730    }
731}