This commit is contained in:
chriseth 2022-09-03 23:54:02 +02:00
parent d886e03aa4
commit df7877ea37

84
src/flow/flow.rs Normal file
View file

@ -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<Address, Vec<Edge>>) {
let mut adjacencies = Adjacencies::new(edges);
let mut used_edges: HashMap<Node, HashMap<Node, U256>> = 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<Node>) {
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<Node, Node>, source: &Node, sink: &Node) -> Vec<Node> {
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
}