use graph::{Graph, Digraph, IndexGraph, IndexDigraph};
use builder::Builder;
use std::collections::HashSet;
use std::cmp::{min, max};
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()
}
#[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);
}
}