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;
221pub mod time_compat;
222
223// Optional feature-gated modules
224#[cfg(feature = "monitoring")]
225pub mod monitoring;
226
227#[cfg(feature = "canonical")]
228pub mod canonical;
229
230#[cfg(feature = "wasm")]
231pub mod wasm;
232
233// Re-exports for convenient access
234pub use algorithm::approximate::{
235    ApproxMinCut, ApproxMinCutConfig, ApproxMinCutResult, ApproxMinCutStats,
236};
237pub use algorithm::{AlgorithmStats, DynamicMinCut, MinCutBuilder, MinCutConfig, MinCutResult};
238pub use certificate::{
239    AuditData, AuditEntry, AuditEntryType, AuditLogger, CertLocalKCutQuery, CertificateError,
240    CutCertificate, LocalKCutResponse, LocalKCutResultSummary, UpdateTrigger, UpdateType,
241};
242pub use cluster::hierarchy::{
243    Expander, HierarchyCluster, HierarchyConfig, HierarchyStats, MirrorCut, Precluster,
244    ThreeLevelHierarchy,
245};
246pub use cluster::{Cluster, ClusterHierarchy};
247pub use compact::{
248    BitSet256, CompactAdjacency, CompactCoreState, CompactEdge, CompactEdgeId, CompactVertexId,
249    CompactWitness, CoreResult, MAX_EDGES_PER_CORE, MAX_VERTICES_PER_CORE,
250};
251pub use connectivity::polylog::{PolylogConnectivity, PolylogStats};
252pub use connectivity::DynamicConnectivity;
253pub use error::{MinCutError, Result};
254pub use euler::EulerTourTree;
255pub use expander::{Conductance, ExpanderComponent, ExpanderDecomposition};
256pub use fragment::{Fragment, FragmentResult, FragmentingAlgorithm};
257pub use fragmentation::{
258    Fragment as FragmentationFragment, Fragmentation, FragmentationConfig, TrimResult,
259};
260pub use graph::{DynamicGraph, Edge, EdgeId, GraphStats, VertexId, Weight};
261pub use instance::{
262    BoundedInstance, InstanceResult, ProperCutInstance, StubInstance, WitnessHandle,
263};
264pub use integration::{CommunityDetector, GraphPartitioner, RuVectorGraphAnalyzer};
265pub use linkcut::LinkCutTree;
266pub use localkcut::{
267    ColorMask, DeterministicFamilyGenerator, DeterministicLocalKCut, EdgeColor, ForestPacking,
268    LocalCutResult, LocalKCut, LocalKCutOracle, LocalKCutQuery,
269    LocalKCutResult as PaperLocalKCutResult,
270};
271pub use parallel::{
272    compute_core_range, CoreDistributor, CoreExecutor, CoreMessage, CoreStrategy, ResultAggregator,
273    SharedCoordinator, WorkItem, NUM_CORES, RANGES_PER_CORE, RANGE_FACTOR, TOTAL_RANGES,
274};
275pub use sparsify::{SparseGraph, SparsifyConfig};
276pub use subpolynomial::{
277    HierarchyLevel, HierarchyStatistics, LevelExpander, MinCutQueryResult, RecourseStats,
278    SubpolyConfig, SubpolynomialMinCut,
279};
280pub use tree::{DecompositionNode, HierarchicalDecomposition, LevelInfo};
281pub use witness::{EdgeWitness, LazyWitnessTree, WitnessTree};
282pub use wrapper::MinCutWrapper;
283
284// Optimization re-exports (SOTA j-Tree + BMSSP performance improvements)
285pub use optimization::{
286    BatchConfig,
287    BenchmarkResult,
288    // Benchmarking
289    BenchmarkSuite,
290    CacheConfig,
291    CacheStats,
292    // DSpar: 5.9x speedup via degree-based presparse
293    DegreePresparse,
294    DistanceArray,
295    LazyLevel,
296    // Pool: 50-75% memory reduction
297    LevelPool,
298    OptimizationBenchmark,
299    ParallelConfig,
300    // Parallel: Rayon-based work-stealing
301    ParallelLevelUpdater,
302    // Cache: 10x for repeated distance queries
303    PathDistanceCache,
304    PoolConfig,
305    PoolStats,
306    PrefetchHint,
307    PresparseConfig,
308    PresparseResult,
309    PresparseStats,
310    // SIMD: 2-4x for distance operations
311    SimdDistanceOps,
312    TypedArrayTransfer,
313    // WASM Batch: 10x FFI overhead reduction
314    WasmBatchOps,
315    WorkStealingScheduler,
316};
317
318// J-Tree re-exports (feature-gated)
319#[cfg(feature = "jtree")]
320pub use jtree::{
321    ApproximateCut, BmsspJTreeLevel, ContractedGraph, CutResult as JTreeCutResult,
322    DynamicCutSparsifier, EscalationPolicy, EscalationTrigger, JTreeConfig, JTreeError,
323    JTreeHierarchy, JTreeLevel, JTreeStatistics, LevelConfig, LevelStatistics, PathCutResult,
324    QueryResult as CoordinatorQueryResult, RecourseTracker, SparsifierConfig, SparsifierStatistics,
325    Tier, TierMetrics, TwoTierCoordinator, VertexSplitResult,
326};
327
328// Re-export ForestPacking with explicit disambiguation (also defined in localkcut)
329#[cfg(feature = "jtree")]
330pub use jtree::ForestPacking as JTreeForestPacking;
331
332// SNN Integration re-exports
333pub use snn::{
334    AttractorConfig,
335    // Layer 1: Attractors
336    AttractorDynamics,
337    CPGConfig,
338    CausalConfig,
339    // Layer 3: Causal Discovery
340    CausalDiscoverySNN,
341    CausalGraph,
342    CausalRelation,
343    // Unified Engine
344    CognitiveMinCutEngine,
345    EnergyLandscape,
346    EngineConfig,
347    EngineMetrics,
348    GrowthRules,
349    // Core SNN types
350    LIFNeuron,
351    LayerConfig,
352    MetaAction,
353    // Layer 2: Strange Loop
354    MetaCognitiveMinCut,
355    MetaLevel,
356    MorphConfig,
357    // Layer 5: Morphogenetic
358    MorphogeneticSNN,
359    NetworkConfig,
360    // Layer 6: Neural Optimizer
361    NeuralGraphOptimizer,
362    NeuronConfig,
363    NeuronState,
364    OptimizationResult,
365    OptimizerConfig,
366    OscillatorNeuron,
367    PhaseTopology,
368    PolicySNN,
369    SNNMinCutConfig,
370    STDPConfig,
371    SimTime,
372    // Utilities
373    Spike,
374    SpikeTrain,
375    SpikingNetwork,
376    StrangeLoopConfig,
377    Synapse,
378    SynapseMatrix,
379    // Layer 4: Time Crystal
380    TimeCrystalCPG,
381    TuringPattern,
382    ValueNetwork,
383};
384
385#[cfg(feature = "agentic")]
386pub use integration::AgenticAnalyzer;
387
388#[cfg(feature = "canonical")]
389pub use canonical::{
390    CactusCycle, CactusEdge, CactusGraph, CactusVertex, CanonicalCutResult, CanonicalMinCut,
391    CanonicalMinCutImpl, FixedWeight, WitnessReceipt,
392};
393
394#[cfg(feature = "canonical")]
395pub use canonical::source_anchored::{
396    canonical_mincut, make_receipt, receipts_agree, CanonicalMinCutResult as SourceAnchoredResult,
397    SourceAnchoredConfig, SourceAnchoredCut, SourceAnchoredMinCut, SourceAnchoredReceipt,
398};
399
400#[cfg(feature = "canonical")]
401pub use canonical::tree_packing::{
402    canonical_mincut_fast, GomoryHuEdge, GomoryHuTree, TreeMinCutResult,
403};
404
405#[cfg(feature = "canonical")]
406pub use canonical::dynamic::{
407    DynamicMinCut as DynamicCanonicalMinCut, DynamicMinCutConfig as DynamicCanonicalConfig,
408    EdgeMutation,
409};
410
411#[cfg(feature = "monitoring")]
412pub use monitoring::{
413    EventType, MinCutEvent, MinCutMonitor, MonitorBuilder, MonitorConfig, MonitorMetrics, Threshold,
414};
415
416/// Crate version
417pub const VERSION: &str = env!("CARGO_PKG_VERSION");
418
419/// Crate name
420pub const NAME: &str = env!("CARGO_PKG_NAME");
421
422/// Prelude module for convenient imports
423///
424/// Import this module to get all the commonly used types and traits:
425///
426/// ```rust
427/// use ruvector_mincut::prelude::*;
428///
429/// let mincut = MinCutBuilder::new()
430///     .exact()
431///     .build()
432///     .unwrap();
433/// ```
434pub mod prelude {
435    //! Prelude module with commonly used types
436
437    pub use crate::{
438        compute_core_range,
439        AlgorithmStats,
440        ApproxMinCut,
441        ApproxMinCutConfig,
442        AttractorConfig,
443        AttractorDynamics,
444        AuditLogger,
445        BitSet256,
446        BoundedInstance,
447        CPGConfig,
448        CertificateError,
449        Cluster,
450        ClusterHierarchy,
451        // SNN Integration types
452        CognitiveMinCutEngine,
453        ColorMask,
454        CommunityDetector,
455        CompactAdjacency,
456        CompactCoreState,
457        CompactEdge,
458        CompactEdgeId,
459        CompactVertexId,
460        CompactWitness,
461        Conductance,
462        CoreDistributor,
463        CoreExecutor,
464        CoreResult,
465        CoreStrategy,
466        CutCertificate,
467        DeterministicFamilyGenerator,
468        DeterministicLocalKCut,
469        DynamicConnectivity,
470        DynamicGraph,
471        DynamicMinCut,
472        Edge,
473        EdgeColor,
474        EdgeId,
475        EngineConfig,
476        EngineMetrics,
477        ExpanderComponent,
478        ExpanderDecomposition,
479        ForestPacking,
480        Fragment,
481        FragmentResult,
482        FragmentingAlgorithm,
483        GraphPartitioner,
484        InstanceResult,
485        LocalCutResult,
486        LocalKCut,
487        LocalKCutOracle,
488        LocalKCutQuery,
489        MinCutBuilder,
490        MinCutConfig,
491        MinCutError,
492        MinCutResult,
493        MinCutWrapper,
494        NeuralGraphOptimizer,
495        OptimizerConfig,
496        PaperLocalKCutResult,
497        PolylogConnectivity,
498        PolylogStats,
499        ProperCutInstance,
500        RecourseStats,
501        Result,
502        ResultAggregator,
503        RuVectorGraphAnalyzer,
504        SharedCoordinator,
505        SimTime,
506        Spike,
507        StubInstance,
508        SubpolyConfig,
509        // Subpolynomial min-cut
510        SubpolynomialMinCut,
511        TimeCrystalCPG,
512        VertexId,
513        Weight,
514        WitnessHandle,
515        MAX_EDGES_PER_CORE,
516        MAX_VERTICES_PER_CORE,
517        NUM_CORES,
518        RANGES_PER_CORE,
519    };
520
521    #[cfg(feature = "agentic")]
522    pub use crate::AgenticAnalyzer;
523
524    #[cfg(feature = "monitoring")]
525    pub use crate::{EventType, MinCutEvent, MinCutMonitor, MonitorBuilder};
526
527    #[cfg(feature = "canonical")]
528    pub use crate::{
529        CactusCycle, CactusEdge, CactusGraph, CactusVertex, CanonicalCutResult, CanonicalMinCut,
530        CanonicalMinCutImpl, DynamicCanonicalConfig, DynamicCanonicalMinCut, EdgeMutation,
531        FixedWeight, GomoryHuTree, SourceAnchoredConfig, SourceAnchoredCut,
532        SourceAnchoredMinCut, SourceAnchoredReceipt, TreeMinCutResult, WitnessReceipt,
533    };
534
535    #[cfg(feature = "jtree")]
536    pub use crate::{
537        ApproximateCut, BmsspJTreeLevel, ContractedGraph, CoordinatorQueryResult,
538        DynamicCutSparsifier, EscalationPolicy, EscalationTrigger, JTreeConfig, JTreeCutResult,
539        JTreeError, JTreeForestPacking, JTreeHierarchy, JTreeLevel, JTreeStatistics, LevelConfig,
540        LevelStatistics, PathCutResult, RecourseTracker, SparsifierConfig, SparsifierStatistics,
541        Tier, TierMetrics, TwoTierCoordinator, VertexSplitResult,
542    };
543}
544
545#[cfg(test)]
546mod tests {
547    use super::*;
548
549    #[test]
550    fn test_version_constant() {
551        assert!(!VERSION.is_empty());
552        assert!(!NAME.is_empty());
553        assert_eq!(NAME, "ruvector-mincut");
554    }
555
556    #[test]
557    fn test_basic_workflow() {
558        // Test the main API works correctly
559        let mut mincut = MinCutBuilder::new()
560            .exact()
561            .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)])
562            .build()
563            .unwrap();
564
565        // Verify initial state
566        assert_eq!(mincut.num_vertices(), 3);
567        assert_eq!(mincut.num_edges(), 3);
568        assert_eq!(mincut.min_cut_value(), 2.0);
569
570        // Test insert
571        let new_cut = mincut.insert_edge(1, 4, 2.0).unwrap();
572        assert!(new_cut.is_finite());
573        assert_eq!(mincut.num_edges(), 4);
574
575        // Test delete
576        let new_cut = mincut.delete_edge(1, 2).unwrap();
577        assert!(new_cut.is_finite());
578        assert_eq!(mincut.num_edges(), 3);
579    }
580
581    #[test]
582    fn test_prelude_imports() {
583        use crate::prelude::*;
584
585        // Ensure all prelude items are accessible
586        let mincut = MinCutBuilder::new().build().unwrap();
587
588        assert_eq!(mincut.min_cut_value(), f64::INFINITY);
589    }
590
591    #[test]
592    fn test_approximate_mode() {
593        let mincut = MinCutBuilder::new()
594            .approximate(0.1)
595            .with_edges(vec![(1, 2, 1.0)])
596            .build()
597            .unwrap();
598
599        let result = mincut.min_cut();
600        assert!(!result.is_exact);
601        assert_eq!(result.approximation_ratio, 1.1);
602    }
603
604    #[test]
605    fn test_exact_mode() {
606        let mincut = MinCutBuilder::new()
607            .exact()
608            .with_edges(vec![(1, 2, 1.0)])
609            .build()
610            .unwrap();
611
612        let result = mincut.min_cut();
613        assert!(result.is_exact);
614        assert_eq!(result.approximation_ratio, 1.0);
615    }
616
617    #[test]
618    fn test_min_cut_result() {
619        let mincut = MinCutBuilder::new()
620            .with_edges(vec![(1, 2, 1.0), (2, 3, 1.0), (3, 1, 1.0)])
621            .build()
622            .unwrap();
623
624        let result = mincut.min_cut();
625        assert_eq!(result.value, 2.0);
626        assert!(result.cut_edges.is_some());
627        assert!(result.partition.is_some());
628
629        if let Some((s, t)) = result.partition {
630            assert_eq!(s.len() + t.len(), 3);
631            assert!(!s.is_empty());
632            assert!(!t.is_empty());
633        }
634    }
635
636    #[test]
637    fn test_graph_stats() {
638        let mincut = MinCutBuilder::new()
639            .with_edges(vec![(1, 2, 2.0), (2, 3, 3.0), (3, 1, 1.0)])
640            .build()
641            .unwrap();
642
643        let graph = mincut.graph();
644        let stats = graph.read().stats();
645
646        assert_eq!(stats.num_vertices, 3);
647        assert_eq!(stats.num_edges, 3);
648        assert_eq!(stats.total_weight, 6.0);
649        assert_eq!(stats.min_degree, 2);
650        assert_eq!(stats.max_degree, 2);
651    }
652
653    #[test]
654    fn test_algorithm_stats() {
655        let mut mincut = MinCutBuilder::new()
656            .with_edges(vec![(1, 2, 1.0)])
657            .build()
658            .unwrap();
659
660        mincut.insert_edge(2, 3, 1.0).unwrap();
661        mincut.delete_edge(1, 2).unwrap();
662        let _ = mincut.min_cut_value();
663
664        let stats = mincut.stats();
665        assert_eq!(stats.insertions, 1);
666        assert_eq!(stats.deletions, 1);
667        assert_eq!(stats.queries, 1);
668        assert!(stats.avg_update_time_us > 0.0);
669    }
670
671    #[test]
672    fn test_dynamic_updates() {
673        let mut mincut = MinCutBuilder::new().build().unwrap();
674
675        // Start empty
676        assert_eq!(mincut.min_cut_value(), f64::INFINITY);
677
678        // Add edges dynamically
679        mincut.insert_edge(1, 2, 1.0).unwrap();
680        assert_eq!(mincut.min_cut_value(), 1.0);
681
682        mincut.insert_edge(2, 3, 1.0).unwrap();
683        assert_eq!(mincut.min_cut_value(), 1.0);
684
685        mincut.insert_edge(3, 1, 1.0).unwrap();
686        assert_eq!(mincut.min_cut_value(), 2.0);
687    }
688
689    #[test]
690    fn test_disconnected_graph() {
691        let mincut = MinCutBuilder::new()
692            .with_edges(vec![(1, 2, 1.0), (3, 4, 1.0)])
693            .build()
694            .unwrap();
695
696        assert!(!mincut.is_connected());
697        assert_eq!(mincut.min_cut_value(), 0.0);
698    }
699
700    #[test]
701    fn test_builder_pattern() {
702        let mincut = MinCutBuilder::new()
703            .exact()
704            .max_cut_size(500)
705            .parallel(true)
706            .with_edges(vec![(1, 2, 1.0)])
707            .build()
708            .unwrap();
709
710        assert!(!mincut.config().approximate);
711        assert_eq!(mincut.config().max_exact_cut_size, 500);
712        assert!(mincut.config().parallel);
713    }
714
715    #[test]
716    fn test_weighted_graph() {
717        let mincut = MinCutBuilder::new()
718            .with_edges(vec![(1, 2, 5.0), (2, 3, 3.0), (3, 1, 2.0)])
719            .build()
720            .unwrap();
721
722        assert_eq!(mincut.min_cut_value(), 5.0);
723    }
724
725    #[test]
726    fn test_error_handling() {
727        let mut mincut = MinCutBuilder::new()
728            .with_edges(vec![(1, 2, 1.0)])
729            .build()
730            .unwrap();
731
732        // Try to insert duplicate edge
733        let result = mincut.insert_edge(1, 2, 2.0);
734        assert!(result.is_err());
735        assert!(matches!(result, Err(MinCutError::EdgeExists(1, 2))));
736
737        // Try to delete non-existent edge
738        let result = mincut.delete_edge(3, 4);
739        assert!(result.is_err());
740        assert!(matches!(result, Err(MinCutError::EdgeNotFound(3, 4))));
741    }
742
743    #[test]
744    fn test_large_graph() {
745        let mut edges = Vec::new();
746        for i in 0..99 {
747            edges.push((i, i + 1, 1.0));
748        }
749
750        let mincut = MinCutBuilder::new().with_edges(edges).build().unwrap();
751
752        assert_eq!(mincut.num_vertices(), 100);
753        assert_eq!(mincut.num_edges(), 99);
754        assert_eq!(mincut.min_cut_value(), 1.0);
755    }
756
757    #[cfg(feature = "monitoring")]
758    #[test]
759    fn test_monitoring_feature() {
760        use crate::monitoring::EventType;
761
762        // Ensure monitoring types are accessible when feature is enabled
763        let _ = EventType::CutIncreased;
764        let _ = EventType::CutDecreased;
765    }
766}