1#![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
123pub 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
146pub mod optimization;
150
151pub mod snn;
183
184pub mod subpolynomial;
189
190#[cfg(feature = "jtree")]
217pub mod jtree;
218
219mod core;
221pub mod time_compat;
222
223#[cfg(feature = "monitoring")]
225pub mod monitoring;
226
227#[cfg(feature = "canonical")]
228pub mod canonical;
229
230#[cfg(feature = "wasm")]
231pub mod wasm;
232
233pub 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
284pub use optimization::{
286 BatchConfig,
287 BenchmarkResult,
288 BenchmarkSuite,
290 CacheConfig,
291 CacheStats,
292 DegreePresparse,
294 DistanceArray,
295 LazyLevel,
296 LevelPool,
298 OptimizationBenchmark,
299 ParallelConfig,
300 ParallelLevelUpdater,
302 PathDistanceCache,
304 PoolConfig,
305 PoolStats,
306 PrefetchHint,
307 PresparseConfig,
308 PresparseResult,
309 PresparseStats,
310 SimdDistanceOps,
312 TypedArrayTransfer,
313 WasmBatchOps,
315 WorkStealingScheduler,
316};
317
318#[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#[cfg(feature = "jtree")]
330pub use jtree::ForestPacking as JTreeForestPacking;
331
332pub use snn::{
334 AttractorConfig,
335 AttractorDynamics,
337 CPGConfig,
338 CausalConfig,
339 CausalDiscoverySNN,
341 CausalGraph,
342 CausalRelation,
343 CognitiveMinCutEngine,
345 EnergyLandscape,
346 EngineConfig,
347 EngineMetrics,
348 GrowthRules,
349 LIFNeuron,
351 LayerConfig,
352 MetaAction,
353 MetaCognitiveMinCut,
355 MetaLevel,
356 MorphConfig,
357 MorphogeneticSNN,
359 NetworkConfig,
360 NeuralGraphOptimizer,
362 NeuronConfig,
363 NeuronState,
364 OptimizationResult,
365 OptimizerConfig,
366 OscillatorNeuron,
367 PhaseTopology,
368 PolicySNN,
369 SNNMinCutConfig,
370 STDPConfig,
371 SimTime,
372 Spike,
374 SpikeTrain,
375 SpikingNetwork,
376 StrangeLoopConfig,
377 Synapse,
378 SynapseMatrix,
379 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
416pub const VERSION: &str = env!("CARGO_PKG_VERSION");
418
419pub const NAME: &str = env!("CARGO_PKG_NAME");
421
422pub mod prelude {
435 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 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 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 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 assert_eq!(mincut.num_vertices(), 3);
567 assert_eq!(mincut.num_edges(), 3);
568 assert_eq!(mincut.min_cut_value(), 2.0);
569
570 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 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 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 assert_eq!(mincut.min_cut_value(), f64::INFINITY);
677
678 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 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 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 let _ = EventType::CutIncreased;
764 let _ = EventType::CutDecreased;
765 }
766}