gomory_hu_tree/flow/
traits.rs

1/// A trait for basic graph structures used in flow algorithms.
2///
3/// Graphs implementing this trait provide essential information like vertex count.
4pub trait FlowGraph {
5    /// Returns the number of vertices in the graph.
6    fn vertex_count(&self) -> usize;
7    // Potential future methods:
8    // fn edge_count(&self) -> usize;
9    // fn get_capacity(&self, u: usize, v: usize) -> Option<f64>;
10}
11
12/// Represents a min-cut partition in a graph.
13///
14/// The partition divides the graph's vertices into two sets, typically the source-side
15/// (S) and the sink-side (T) of the cut.
16#[derive(Debug, Clone)]
17pub struct MinCut {
18    /// A boolean vector where `partition[i]` is true if vertex `i` is on the source-side
19    /// of the cut, and false otherwise (meaning it's on the sink-side).
20    /// The length of this vector should be equal to the number of vertices in the graph.
21    pub partition: Vec<bool>,
22}
23
24impl MinCut {
25    /// Creates a new `MinCut` from a given partition.
26    ///
27    /// # Arguments
28    /// * `partition`: A vector where `partition[i]` indicates if vertex `i` is on the
29    ///   source-side of the cut.
30    pub fn new(partition: Vec<bool>) -> Self {
31        Self { partition }
32    }
33
34    /// Checks if a vertex `v` is on the same side of the cut as a representative vertex `s_representative`.
35    ///
36    /// Typically, `s_representative` is the source node used in the max-flow computation that yielded this cut.
37    ///
38    /// # Arguments
39    /// * `v`: The vertex index to check.
40    /// * `s_representative`: The vertex index of the representative (e.g., the source node `s`).
41    ///
42    /// # Returns
43    /// `true` if `v` is on the same side of the cut as `s_representative`, `false` otherwise.
44    ///
45    /// # Panics
46    /// Panics if `v` or `s_representative` are out of bounds for the partition data.
47    pub fn same_side(&self, v: usize, s_representative: usize) -> bool {
48        if v >= self.partition.len() || s_representative >= self.partition.len() {
49            panic!("Vertex index out of bounds in MinCut::same_side. v: {}, s_rep: {}, partition_len: {}",
50                   v, s_representative, self.partition.len());
51        }
52        // If partition[s_representative] is true, it means "true" denotes the s-side.
53        // So, v is on s-side if partition[v] is also true.
54        // If partition[s_representative] is false, it means "false" denotes the s-side (unexpected, but possible).
55        // So, v is on s-side if partition[v] is also false.
56        // This is equivalent to checking if their boolean values are the same.
57        self.partition[v] == self.partition[s_representative]
58    }
59}
60
61/// Errors that can occur during max-flow computations.
62#[derive(Debug, Clone, thiserror::Error)]
63pub enum MaxFlowError {
64    /// The source and sink vertices are the same.
65    #[error("Source and sink are the same vertex (s: {0}, t: {0})")]
66    SourceEqualsSink(usize),
67    /// A specified vertex was not found in the graph (e.g., index out of bounds).
68    #[error("Vertex {0} not found in graph")]
69    VertexNotFound(usize),
70    /// The algorithm reached its maximum allowed iterations before completion.
71    /// This might indicate a very complex graph or an iteration limit that is too low.
72    #[error("Maximum iterations ({0}) reached in max-flow computation")]
73    MaxIterationsReached(usize),
74    /// The graph has no vertices, making max-flow undefined.
75    #[error("Graph has 0 vertices, max-flow is undefined")]
76    EmptyGraph,
77    /// An unspecified internal error occurred within the max-flow algorithm.
78    #[error("Internal max-flow error: {0}")]
79    InternalError(String),
80}
81
82/// A trait for max-flow algorithms.
83///
84/// Implementors of this trait can compute the maximum flow and corresponding minimum cut
85/// in a given flow network (graph).
86/// `G` is the type of the graph, which must implement `FlowGraph`.
87pub trait MaxFlowSolver<G: FlowGraph> {
88    /// The type used for representing flow values (e.g., `f64`, `i32`).
89    /// Must support basic arithmetic, comparison, and debugging.
90    type Flow: Copy + Default + PartialOrd + std::ops::AddAssign + std::fmt::Debug;
91
92    /// Computes the maximum flow from a `source` to a `sink` in the given `graph`.
93    ///
94    /// # Arguments
95    /// * `graph`: A reference to the graph implementing `FlowGraph`.
96    /// * `source`: The source vertex index.
97    /// * `sink`: The sink vertex index.
98    ///
99    /// # Returns
100    /// A `Result` containing a tuple `(max_flow_value, min_cut_partition)` if successful.
101    /// The `min_cut_partition` (a `MinCut` struct) identifies nodes on the source-side of one minimum cut.
102    /// Returns `MaxFlowError` if an issue occurs.
103    fn max_flow_min_cut(
104        &self,
105        graph: &G,
106        source: usize,
107        sink: usize,
108    ) -> Result<(Self::Flow, MinCut), MaxFlowError>;
109}
110
111/// A trait for graph views that provide access to all original edges.
112///
113/// This is used by algorithms like Dinic's to construct an initial residual graph.
114/// It extends `FlowGraph`.
115pub trait OriginalGraphView: FlowGraph {
116    /// Returns an iterator over all edges in the graph.
117    /// Each item is a tuple `(source_vertex_idx, target_vertex_idx, capacity)`.
118    /// For undirected graphs, an edge `u-v` with capacity `C` might be represented
119    /// by two directed edges `(u,v,C)` and `(v,u,C)` from this iterator if the underlying
120    /// graph implementation is directed (like `AdjacencyListFlowGraph`).
121    fn all_edges(&self) -> Box<dyn Iterator<Item = (usize, usize, f64)> + '_>;
122}