diff --git a/src/flow/flow.rs b/src/flow/flow.rs new file mode 100644 index 0000000..d49e522 --- /dev/null +++ b/src/flow/flow.rs @@ -0,0 +1,84 @@ +use crate::flow::adjacencies::Adjacencies; +use crate::flow::Node; +use crate::types::{Address, Edge, U256}; +use std::cmp::min; +use std::collections::HashMap; +use std::collections::VecDeque; + +pub fn compute_flow(source: &Address, sink: &Address, edges: &HashMap>) { + let mut adjacencies = Adjacencies::new(edges); + let mut used_edges: HashMap> = HashMap::new(); + + let mut flow = U256::default(); + loop { + let (new_flow, parents) = augmenting_path(source, sink, &mut adjacencies); + if new_flow == U256::default() { + break; + } + flow += new_flow; + for window in parents.windows(2) { + if let [node, prev] = window { + adjacencies.adjust_capacity(prev, node, -new_flow); + adjacencies.adjust_capacity(node, prev, new_flow); + if adjacencies.is_adjacent(node, prev) { + *used_edges + .entry(node.clone()) + .or_default() + .entry(prev.clone()) + .or_default() -= new_flow; + } else { + *used_edges + .entry(prev.clone()) + .or_default() + .entry(node.clone()) + .or_default() -= new_flow; + } + } else { + panic!(); + } + } + } + println!("Max flow: {flow}"); +} + +fn augmenting_path( + source: &Address, + sink: &Address, + adjacencies: &mut Adjacencies, +) -> (U256, Vec) { + let mut parent = HashMap::new(); + if *source == *sink { + return (U256::default(), vec![]); + } + let mut queue = VecDeque::<(Node, U256)>::new(); + queue.push_back((Node::Node(*source), U256::default() - U256::from(1))); + while let Some((node, flow)) = queue.pop_front() { + for (target, capacity) in adjacencies.outgoing_edges_sorted_by_capacity(&node) { + if !parent.contains_key(&target) && capacity > U256::default() { + parent.insert(target.clone(), node.clone()); + let new_flow = min(flow, capacity); + if target == Node::Node(*sink) { + return ( + new_flow, + trace(parent, &Node::Node(*source), &Node::Node(*sink)), + ); + } + queue.push_back((target, new_flow)); + } + } + } + (U256::default(), vec![]) +} + +fn trace(parent: HashMap, source: &Node, sink: &Node) -> Vec { + let mut t = vec![sink.clone()]; + let mut node = sink; + loop { + node = parent.get(node).unwrap(); + t.push(node.clone()); + if *node == *source { + break; + } + } + t +}