use builder::{Buildable, Builder};
use graph::{Digraph, Graph, IndexDigraph, IndexGraph, IndexNodeVec};
use std::cmp::{max, min};
use std::collections::HashSet;
use std::usize;
pub fn complement<'g, 'h, G, H>(g: &'g G) -> H
where
G: IndexGraph<'g>,
H: Graph<'h> + Buildable,
{
let mut edges = HashSet::new();
for e in g.edges() {
let (u, v) = g.enodes(e);
edges.insert((min(g.node_id(u), g.node_id(v)), max(g.node_id(u), g.node_id(v))));
}
let n = g.num_nodes();
let mut h = H::Builder::with_capacities(n, n * (n - 1) / 2 - g.num_edges());
let nodes = h.add_nodes(n);
for i in 0..n {
for j in i..n {
if i < j && !edges.contains(&(i, j)) {
h.add_edge(nodes[i], nodes[j]);
}
}
}
h.to_graph()
}
pub fn inverse<'g, 'h, G, H>(g: &'g G) -> H
where
G: IndexDigraph<'g>,
H: Digraph<'h> + Buildable,
{
let mut h = H::Builder::with_capacities(g.num_nodes(), g.num_edges());
let nodes = h.add_nodes(g.num_nodes());
for e in g.edges() {
h.add_edge(nodes[g.node_id(g.snk(e))], nodes[g.node_id(g.src(e))]);
}
h.to_graph()
}
pub fn is_connected<'g, G>(g: &'g G) -> bool
where
G: IndexGraph<'g>,
{
if g.num_nodes() == 0 {
return true;
}
let mut seen = idxnodevec![g; false];
let mut q = vec![g.id2node(0)];
while let Some(u) = q.pop() {
for (_, v) in g.neighs(u) {
if !seen[v] {
seen[v] = true;
q.push(v);
}
}
}
seen.into_iter().all(|&u| u)
}
pub fn components<'g, G>(g: &'g G) -> (usize, IndexNodeVec<'g, G, usize>)
where
G: IndexGraph<'g>,
{
if g.num_nodes() == 0 {
return (0, idxnodevec![g; 0]);
}
let mut components = idxnodevec![g; usize::MAX];
let mut q = vec![];
let mut nodes = g.nodes();
let mut ncomponents = 0;
loop {
while let Some(u) = nodes.next() {
if components[u] == usize::MAX {
components[u] = ncomponents;
q.push(u);
ncomponents += 1;
break;
}
}
if q.is_empty() {
return (ncomponents, components);
}
while let Some(u) = q.pop() {
for (_, v) in g.neighs(u) {
if components[v] != components[u] {
components[v] = components[u];
q.push(v);
}
}
}
}
}
#[cfg(test)]
mod tests {
use algorithms::complement;
use classes::*;
use linkedlistgraph::Edge;
use std::cmp::{max, min};
use {Graph, IndexGraph, LinkedListGraph};
#[test]
fn test_complement() {
let g: LinkedListGraph = cycle(5);
let h: LinkedListGraph = complement(&g);
let l: LinkedListGraph = complement(&h);
fn to_id(g: &LinkedListGraph, e: Edge) -> (usize, usize) {
let (u, v) = g.enodes(e);
let (u, v) = (g.node_id(u), g.node_id(v));
(min(u, v), max(u, v))
}
let mut gedges: Vec<_> = g.edges().map(|e| to_id(&g, e)).collect();
gedges.sort();
let mut hedges: Vec<_> = h.edges().map(|e| to_id(&h, e)).collect();
hedges.sort();
let mut ledges: Vec<_> = g.edges().map(|e| to_id(&l, e)).collect();
ledges.sort();
assert_eq!(hedges, vec![(0, 2), (0, 3), (1, 3), (1, 4), (2, 4)]);
assert_eq!(gedges, ledges);
}
}