#![allow(dead_code)]
use std::{
cmp::{Ordering, Reverse},
collections::{HashMap, HashSet, VecDeque},
fmt::Debug,
hash::Hash,
mem,
ops::Add,
};
use num::{Unsigned, Zero};
use priority_queue::PriorityQueue;
use crate::{
ArcInfo, Network, arc_storage::ArcStorage, node_storage::NodeStorage, search::Direction,
};
mod preflowpush;
pub use self::preflowpush::preflow_push;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Cyclic;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NegativeCycle;
pub fn topological_sorting<I, NA, AA, NodeStore, ArcStore>(
network: &Network<I, NA, AA, NodeStore, ArcStore>,
) -> Result<Vec<I>, Cyclic>
where
ArcStore: ArcStorage<I, AA>,
NodeStore: NodeStorage<I, NA>,
I: Eq + Hash + Clone,
{
let mut indegrees: HashMap<I, usize> = network
.iter_nodes()
.filter_map(|(node, _)| {
let indegree = network.reverse_arcs(node).count();
if indegree == 0 {
None
} else {
Some((node.clone(), indegree))
}
})
.collect();
let mut indegree_zero: Vec<I> = network
.iter_nodes()
.filter_map(|(node, _)| {
if indegrees.contains_key(node) {
None
} else {
Some(node)
}
})
.cloned()
.collect();
let mut sorting = Vec::with_capacity(network.n_nodes());
while !indegree_zero.is_empty() {
let this_degree = mem::take(&mut indegree_zero);
for node in this_degree {
for neigh in network.forward_arcs(&node) {
*indegrees.get_mut(&neigh.head).expect("Should be present") -= 1;
if *indegrees.get(&neigh.head).expect("Should be present") == 0 {
indegree_zero.push(neigh.head.clone());
indegrees.remove(&neigh.head);
}
}
sorting.push(node);
}
}
if indegrees.is_empty() {
Ok(sorting)
} else {
Err(Cyclic)
}
}
pub fn valid_topological_sorting<I, NodeAttr, ArcAttr, NodeStore, ArcStore>(
network: &Network<I, NodeAttr, ArcAttr, NodeStore, ArcStore>,
ordering: &[I],
) -> bool
where
ArcStore: ArcStorage<I, ArcAttr>,
NodeStore: NodeStorage<I, NodeAttr>,
I: Eq + Hash + PartialEq,
{
let labels: HashMap<&I, usize> = ordering.iter().enumerate().map(|(i, n)| (n, i)).collect();
network.arc_iter().all(|arc| {
let a = labels.get(&arc.tail);
let b = labels.get(&arc.head);
a.and_then(|a| b.map(|b| a < b)).unwrap_or(false)
})
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Distance<T> {
Finite(T),
Infinite,
}
impl<T> Distance<T> {
pub fn finite_value(&self) -> Option<&T> {
match self {
Distance::Finite(x) => Some(x),
Distance::Infinite => None,
}
}
pub fn map<U, F: Fn(T) -> U>(self, f: F) -> Distance<U> {
match self {
Distance::Finite(x) => Distance::Finite(f(x)),
Distance::Infinite => Distance::Infinite,
}
}
}
impl<T: Add<Output = T>> Add for Distance<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Distance::Finite(a), Distance::Finite(b)) => Distance::Finite(a + b),
_ => Distance::Infinite,
}
}
}
impl<T: Zero> Zero for Distance<T> {
fn zero() -> Self {
Distance::Finite(T::zero())
}
fn is_zero(&self) -> bool {
if let Distance::Finite(x) = self {
x.is_zero()
} else {
false
}
}
}
impl<T: Add<T, Output = T>> Add<T> for Distance<T> {
type Output = Distance<T>;
fn add(self, rhs: T) -> Self::Output {
match self {
Distance::Finite(d) => Distance::Finite(d + rhs),
Distance::Infinite => Distance::Infinite,
}
}
}
impl<T: PartialEq> PartialEq<T> for Distance<T> {
fn eq(&self, other: &T) -> bool {
match self {
Distance::Finite(x) => x == other,
Distance::Infinite => false,
}
}
}
impl<T: PartialOrd> PartialOrd<T> for Distance<T> {
fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
match self {
Distance::Finite(x) => x.partial_cmp(other),
Distance::Infinite => Some(Ordering::Greater),
}
}
}
impl<T: PartialOrd> PartialOrd for Distance<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match (self, other) {
(Distance::Finite(a), Distance::Finite(b)) => a.partial_cmp(b),
(Distance::Finite(_), Distance::Infinite) => Some(std::cmp::Ordering::Less),
(Distance::Infinite, Distance::Finite(_)) => Some(std::cmp::Ordering::Greater),
(Distance::Infinite, Distance::Infinite) => Some(std::cmp::Ordering::Equal),
}
}
}
impl<T: Ord + Eq> Ord for Distance<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Distance::Finite(a), Distance::Finite(b)) => a.cmp(b),
(Distance::Finite(_), Distance::Infinite) => std::cmp::Ordering::Less,
(Distance::Infinite, Distance::Finite(_)) => std::cmp::Ordering::Greater,
(Distance::Infinite, Distance::Infinite) => std::cmp::Ordering::Equal,
}
}
}
impl<T: std::fmt::Display> std::fmt::Display for Distance<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Distance::Finite(x) => write!(f, "{x}"),
Distance::Infinite => write!(f, "INFINITE"),
}
}
}
impl<T: std::ops::Add<Output = T> + Copy> std::ops::Add for &Distance<T> {
type Output = Distance<T>;
fn add(self, rhs: Self) -> Self::Output {
if let (Distance::Finite(x), Distance::Finite(y)) = (self, rhs) {
Distance::Finite(*x + *y)
} else {
Distance::Infinite
}
}
}
impl<T: std::ops::AddAssign + Copy> std::ops::AddAssign for Distance<T> {
fn add_assign(&mut self, rhs: Self) {
match (self, rhs) {
(Distance::Finite(x), Distance::Finite(y)) => {
*x += y;
}
(s, _) => {
*s = Distance::Infinite;
}
}
}
}
impl<T: std::ops::SubAssign + Copy> std::ops::SubAssign for Distance<T> {
fn sub_assign(&mut self, rhs: Self) {
match (self, rhs) {
(Distance::Finite(x), Distance::Finite(y)) => {
*x -= y;
}
(_, Distance::Infinite) => panic!("X - INFINITE is not well defined."),
(s, _) => {
*s = Distance::Infinite;
}
}
}
}
pub fn dijkstra_shortest_path<I, NodeAttr, T, NodeStore, ArcStore>(
network: &Network<I, NodeAttr, T, NodeStore, ArcStore>,
source: I,
) -> Network<I, Distance<T>, ()>
where
NodeStore: NodeStorage<I, NodeAttr>,
ArcStore: ArcStorage<I, T>,
I: Hash + Eq + Copy,
T: Ord + Zero + Copy + Unsigned,
{
let mut pred = Network::new();
pred.add_nodes(network.iter_nodes().map(|(n, _)| (*n, Distance::Infinite)));
pred.add_node(source, Distance::Finite(T::zero()));
let mut next_nodes: PriorityQueue<I, Reverse<T>> = PriorityQueue::new();
next_nodes.push(source, Reverse(T::zero()));
while let Some((position, Reverse(cost))) = next_nodes.pop() {
for arc in network.forward_arcs(&position) {
let alt = arc.attributes + cost;
let altd = arc.attributes + cost;
if !pred.contains_node(&arc.head) {
pred.add_node(arc.head, Distance::Infinite);
}
let head_dist: &mut Distance<T> = pred
.node_mut(&arc.head)
.expect("Should be present, we just inserted it.");
if *head_dist > altd {
*head_dist = Distance::Finite(altd);
let arcs_to_remove: Vec<(I, I)> = pred
.forward_arcs(&arc.head)
.map(|a| (a.tail, a.head))
.collect();
pred.remove_arcs(arcs_to_remove.iter().map(|(a, b)| (a, b)));
let _ = pred.add_arc(ArcInfo::new(arc.head, arc.tail, ()));
if next_nodes
.change_priority(&arc.head, Reverse(alt))
.is_none()
{
next_nodes.push(arc.head, Reverse(alt));
}
}
}
}
pred
}
pub fn bellman_ford_shortest_path<I, NA, T, NodeStore, AS>(
network: &Network<I, NA, T, NodeStore, AS>,
source: I,
) -> Result<Network<I, Distance<T>, ()>, NegativeCycle>
where
NodeStore: NodeStorage<I, NA>,
AS: ArcStorage<I, T>,
I: Hash + Eq + Copy + std::fmt::Debug,
T: Ord + Zero + Copy + Debug,
{
let n = network.n_nodes();
let mut pred: Network<I, Distance<T>, ()> = Network::new();
pred.add_nodes(network.iter_nodes().map(|(n, _)| (*n, Distance::Infinite)));
pred.add_node(source, Distance::Finite(T::zero()));
let mut queue = VecDeque::new();
let mut in_queue = HashSet::new();
let mut visit_counts: HashMap<I, usize> = HashMap::new();
queue.push_back(source);
in_queue.insert(source);
while let Some(u) = queue.pop_front() {
in_queue.remove(&u);
if let Some(Distance::Finite(du)) = pred.node(&u).copied() {
for arc in network.forward_arcs(&u) {
let alt = Distance::Finite(du + arc.attributes);
if !pred.contains_node(arc.head()) {
pred.add_node(*arc.head(), Distance::Infinite);
}
let head_dist = pred
.node_mut(&arc.head)
.expect("The arc's head should resolved to a node");
if *head_dist > alt {
*head_dist = alt;
let arcs_to_remove: Vec<(I, I)> = pred
.forward_arcs(&arc.head)
.map(|a| (a.tail, a.head))
.collect();
pred.remove_arcs(arcs_to_remove.iter().map(|(a, b)| (a, b)));
let _ = pred.add_arc(ArcInfo::new(arc.head, arc.tail, ()));
if !in_queue.contains(&arc.head) {
queue.push_back(arc.head);
in_queue.insert(arc.head);
let mut visits = *visit_counts.entry(arc.head).or_default();
visits += 1;
if visits > n {
return Err(NegativeCycle);
}
}
}
}
}
}
Ok(pred)
}
pub fn floyd_worshall_all_pairs_minimum_path<I, NodeAttr, T, NodeStore, ArcStore>(
network: &Network<I, NodeAttr, T, NodeStore, ArcStore>,
) -> HashMap<I, Network<I, Distance<T>, ()>>
where
NodeStore: NodeStorage<I, NodeAttr>,
ArcStore: ArcStorage<I, T>,
I: Hash + Eq + Copy + std::fmt::Debug,
T: Ord + Zero + Copy + Debug,
{
let mut pred = Network::new();
pred.add_nodes(network.iter_nodes().map(|(n, _)| (*n, Distance::Infinite)));
let mut preds: HashMap<I, Network<I, Distance<T>, ()>> = network
.iter_nodes()
.map(|(&id, _)| {
let mut this_pred = pred.clone();
this_pred.add_node(id, Distance::Finite(T::zero()));
(id, this_pred)
})
.collect();
for arc in network.arc_iter() {
*preds
.get_mut(&arc.tail)
.expect("The key should map to a network")
.node_mut(&arc.head)
.expect("Node should exist") = Distance::Finite(arc.attributes);
let _ = preds
.get_mut(&arc.tail)
.expect("The key should map to a network")
.add_arc((arc.head, arc.tail));
}
for k in network.iter_nodes().map(|(i, _)| i) {
for i in network.iter_nodes().map(|(i, _)| i) {
for j in network.iter_nodes().map(|(i, _)| i) {
let dij = preds[i].node(j).expect("Node should exist");
let alt = preds[i].node(k).expect("Node should exist")
+ preds[k].node(j).expect("Node should exist");
if dij > &alt {
*preds
.get_mut(i)
.expect("Key should map to network")
.node_mut(j)
.expect("Node should exist") = alt;
let arcs_to_remove: Vec<(I, I)> =
preds[i].forward_arcs(j).map(|a| (a.tail, a.head)).collect();
preds
.get_mut(i)
.expect("Key should map to network")
.remove_arcs(arcs_to_remove.iter().map(|(a, b)| (a, b)));
let arc_to_add = preds[k]
.forward_arcs(j)
.next()
.expect("One arc from j should exist")
.clone();
let _ = preds
.get_mut(i)
.expect("Key should map to network")
.add_arc(arc_to_add);
}
}
}
}
preds
}
pub fn distance_unit_arcs<I, NA, T, NodeStore, ArcStore, NewNodeStore>(
network: &Network<I, NA, T, NodeStore, ArcStore>,
root_id: &I,
) -> Network<I, Distance<usize>, T, NewNodeStore, ArcStore>
where
NewNodeStore: NodeStorage<I, Distance<usize>> + FromIterator<(I, Distance<usize>)>,
NodeStore: NodeStorage<I, NA>,
ArcStore: ArcStorage<I, T> + Clone,
I: Hash + Eq + Copy + Debug,
{
let mut distances: HashMap<I, Distance<usize>> = HashMap::with_capacity(network.n_nodes());
distances.insert(*root_id, Distance::Finite(0));
for node in network.bfs(root_id, Direction::Reverse).skip(1) {
let distance_to_node = network
.forward_arcs(dbg!(node))
.map(|arc| {
dbg!(
distances
.get(dbg!(&arc.head))
.unwrap_or(&Distance::Infinite)
)
})
.min()
.copied()
.unwrap_or(Distance::Infinite)
+ 1;
distances.insert(*node, dbg!(distance_to_node));
}
dbg!(&distances);
let nodes = network
.iter_nodes()
.map(|(id, _)| {
(
*id,
distances.get(id).copied().unwrap_or(Distance::Infinite),
)
})
.collect();
Network::from_parts(nodes, network.arc_store().clone())
}
#[inline]
fn pred_to_path<'a, I: Hash + Eq>(pred: &'a HashMap<I, I>, start: &'a I) -> Vec<(&'a I, &'a I)> {
let mut cur = start;
let mut path = Vec::new();
while let Some(next) = pred.get(cur) {
path.push((cur, next));
cur = next;
}
path.reverse();
path
}
#[inline]
fn augment<I, T, NA, NodeStore, AS, FlowNodeStore>(
path: &[(&I, &I)],
network: &Network<I, NA, T, NodeStore, AS>,
flow: &mut Network<I, Distance<usize>, T, FlowNodeStore, AS>,
) where
NodeStore: NodeStorage<I, NA>,
FlowNodeStore: NodeStorage<I, Distance<usize>>,
AS: ArcStorage<I, T>,
I: Hash + Eq + Copy,
T: Ord + Zero + Copy + std::ops::SubAssign + std::ops::AddAssign,
{
let delta = path
.iter()
.map(|(tail, head)| network.arc(**tail, **head).expect("Arc should exist"))
.min()
.expect("Minimum should exist");
for (tail, head) in path {
let forward_arc = if let Some(arc) = flow.arc_mut(**tail, **head) {
arc
} else {
let _ = flow.add_arc(ArcInfo::new(**tail, **head, T::zero()));
flow.arc_mut(**tail, **head)
.expect("Should exist, as it was just inserted")
};
*forward_arc -= *delta;
let reverse_arc = if let Some(arc) = flow.arc_mut(**head, **tail) {
arc
} else {
let _ = flow.add_arc(ArcInfo::new(**head, **tail, T::zero()));
flow.arc_mut(**head, **tail)
.expect("Should exist, as it was just inserted")
};
*reverse_arc += *delta;
}
}
#[inline]
fn next_admissible_arc<'a, I, NA, AA, NodeStore, ArcStore, F, T>(
network: &'a Network<I, NA, AA, NodeStore, ArcStore>,
f: F,
node: &'a I,
) -> Option<&'a ArcInfo<I, AA>>
where
NodeStore: NodeStorage<I, NA>,
ArcStore: ArcStorage<I, AA>,
I: Hash + Eq + Copy,
F: Fn(&NA) -> Distance<T>,
T: std::ops::Add<Output = T> + num::One + PartialEq + Copy,
{
let this_distance = f(network.node(node).expect("Should exist"));
for arc in network.forward_arcs(node) {
let head_dist = f(network.node(&arc.head).expect("Should exist"));
if this_distance == head_dist + T::one() {
return Some(arc);
}
}
None
}
#[inline]
fn admissible_arc<'a, I, T, NodeStore, ArcStore>(
node: &'a I,
network: &'a Network<I, Distance<usize>, T, NodeStore, ArcStore>,
) -> Option<&'a ArcInfo<I, T>>
where
NodeStore: NodeStorage<I, Distance<usize>>,
ArcStore: ArcStorage<I, T>,
I: Hash + Eq + Copy,
{
let this_distance = network.node(node).unwrap_or(&Distance::Infinite);
for arc in network.forward_arcs(node) {
let head_dist = network.node(node).unwrap_or(&Distance::Infinite);
if *this_distance == *head_dist + 1 {
return Some(arc);
}
}
None
}
#[cfg(test)]
mod tests {
mod distance {
use super::super::Distance;
#[test]
fn partial_ord() {
let inf: Distance<usize> = Distance::Infinite;
assert!(inf > Distance::Finite(1_usize));
}
#[test]
fn add() {
assert_eq!(Distance::Finite(10) + 1, Distance::Finite(11));
assert_eq!(
Distance::Finite(10) + Distance::Finite(1),
Distance::Finite(11)
);
assert_eq!(
Distance::<usize>::Infinite + Distance::Finite(1),
Distance::Infinite
);
}
}
mod distance_unit_arcs {
use crate::{
Network,
algorithms::{Distance, distance_unit_arcs},
};
#[test]
fn cycle() {
let mut network: Network<usize, (), ()> = Network::new();
network.add_nodes((0..=3).map(|i| (i, ())));
network.add_arcs([(0, 1), (1, 2), (2, 3), (3, 0)]).unwrap();
dbg!(&network);
let distances: Network<usize, Distance<usize>, ()> = distance_unit_arcs(&network, &0);
assert_eq!(distances.node(&0), Some(&Distance::Finite(0)));
assert_eq!(distances.node(&1), Some(&Distance::Finite(3)));
assert_eq!(distances.node(&2), Some(&Distance::Finite(2)));
assert_eq!(distances.node(&3), Some(&Distance::Finite(1)));
}
}
}