use graph::{Graph, Digraph, IndexGraph, IndexDigraph};
use vec::NodeVec;
use builder::Builder;
use std::collections::HashSet;
use std::cmp::{min, max};
use std::usize;
pub fn complement<'g, 'h, G, H>(g: &'g G) -> H
where G: IndexGraph<'g>,
H: Graph<'h>,
{
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>,
{
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 = nodevec![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, NodeVec<'g, G, usize>)
where G: IndexGraph<'g>
{
if g.num_nodes() == 0 { return (0, nodevec![g; 0]); }
let mut components = nodevec![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 {Graph, IndexGraph, LinkedListGraph};
use linkedlistgraph::Edge;
use classes::*;
use algorithms::complement;
use std::cmp::{min, max};
#[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);
}
}