#![deny(missing_docs)]
#![feature(conservative_impl_trait)]
extern crate petgraph;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
#[macro_use]
extern crate text_io;
#[cfg(test)]
mod tests;
mod matrices;
pub use matrices::*;
use petgraph::graph::NodeIndex;
use petgraph::visit::NodeRef;
use petgraph::visit::Data;
use petgraph::visit::GraphBase;
use petgraph::visit::NodeCount;
use petgraph::visit::IntoNodeIdentifiers;
use petgraph::visit::IntoNodeReferences;
use petgraph::visit::IntoEdgeReferences;
use petgraph::visit::EdgeRef;
use petgraph::visit::GraphProp;
pub fn floyd_warshall<G>(g: G) -> PathMatrix<G::NodeWeight>
where
G: Data
+ GraphBase<NodeId = NodeIndex>
+ NodeCount
+ IntoNodeIdentifiers<NodeId = NodeIndex>
+ IntoNodeReferences
+ IntoEdgeReferences
+ GraphProp,
G::NodeWeight: Clone,
G::EdgeWeight: Clone + Into<usize>,
{
assert!(!g.is_directed());
let mut m = PathMatrix::new(g.node_count());
m.set_path_len(0, 0, 0);
for e in g.edge_references() {
let n1 = e.source().index();
let n2 = e.target().index();
let w: G::EdgeWeight = e.weight().clone();
let w: usize = w.into();
m.set_path_len(n1, n2, w);
}
for k in g.node_references() {
let kw = k.weight();
let k = k.id().index();
for n1 in g.node_identifiers() {
let n1 = n1.index();
for n2 in g.node_identifiers() {
let n2 = n2.index();
if n1 == n2 {
continue;
}
if n1 > n2 {
continue;
}
if n1 == k || n2 == k {
continue;
}
let mut v1 = None;
if m.does_path_exist(n1, n2) {
v1 = Some(m.get_path_len(n1, n2));
}
let v2_exists = m.does_path_exist(n1, k);
let v2_exists = v2_exists && m.does_path_exist(k, n2);
let mut v2 = None;
if v2_exists {
let part1 = m.get_path_len(n1, k);
let part2 = m.get_path_len(k, n2);
v2 = Some(part1.saturating_add(part2));
}
if v2.is_some() && (v1.is_none() || v2.unwrap() < v1.unwrap()) {
let v2 = v2.unwrap();
m.set_path_len(n1, n2, v2);
let mut v: Vec<G::NodeWeight> = Vec::new();
if n1 <= k {
v.extend(m.get_path_iter(n1, k).cloned());
} else {
v.extend(m.get_path_iter(n1, k).rev().cloned());
}
v.push(kw.clone());
if k <= n2 {
v.extend(m.get_path_iter(k, n2).cloned());
} else {
v.extend(m.get_path_iter(k, n2).rev().cloned());
}
m.get_path_mut(n1, n2).set_vector(v);
}
}
}
}
m
}