#[derive(Debug, Clone)]
pub struct Node {
pub core: bool,
pub uniq: Option<usize>,
}
impl Node {
pub fn new(core: bool) -> Node {
Node {
core, uniq: None
}
}
}
#[derive(Debug, Clone)]
pub struct Graph {
pub nodes: Vec<Node>,
pub edges: Vec<(usize, usize)>,
}
impl Graph {
pub fn new() -> Graph {
Graph {
nodes: vec![],
edges: vec![],
}
}
pub fn add_node(&mut self, node: Node) -> usize {
let id = self.nodes.len();
self.nodes.push(node);
id
}
pub fn add_edge(&mut self, a: usize, b: usize) -> usize {
let min = a.min(b);
let max = a.max(b);
let id = self.edges.len();
for i in 0..self.edges.len() {
if self.edges[i] == (min, max) {return i};
}
self.edges.push((min, max));
id
}
pub fn cores(&self) -> usize {
let mut sum = 0;
for node in &self.nodes {
if node.core {sum += 1}
}
sum
}
pub fn non_cores(&self) -> usize {
self.nodes.len() - self.cores()
}
pub fn edges_of(&self, node: usize) -> Vec<usize> {
let mut res = vec![];
for &(a, b) in &self.edges {
if a == node {res.push(b)}
if b == node {res.push(a)}
}
res
}
pub fn unique_edges(&self) -> usize {
let mut sum = 0;
for node in &self.nodes {
if node.uniq.is_some() {sum += 1}
}
sum
}
pub fn self_unique_edges(&self) -> usize {
let mut sum = 0;
for i in 0..self.nodes.len() {
if let Some(j) = self.nodes[i].uniq {
if i == j {sum += 1}
}
}
sum
}
pub fn remove_self_unique_edges(&mut self) {
for i in 0..self.nodes.len() {
if let Some(j) = self.nodes[i].uniq {
if i == j {self.nodes[i].uniq = None}
}
}
}
pub fn self_edges(&self) -> usize {
let mut sum = 0;
for &(a, b) in &self.edges {
if a == b {sum += 1}
}
sum
}
pub fn remove_self_edges(&mut self) {
for i in (0..self.edges.len()).rev() {
let (a, b) = self.edges[i];
if a == b {self.edges.swap_remove(i);}
}
}
pub fn matrix(&self) -> Vec<Vec<u8>> {
let n = self.nodes.len();
let mut mat = vec![vec![0; n]; n];
for i in 0..n {
if let Some(j) = self.nodes[i].uniq {
let min = i.min(j);
let max = i.max(j);
mat[min][max] = 2;
}
}
for &(a, b) in &self.edges {
mat[a][b] += 1;
}
mat
}
pub fn distance(&self, ind: usize) -> Result<Vec<(usize, u64)>, Vec<(usize, u64)>> {
let mut dist = vec![(ind, 0)];
let mut nodes: Vec<usize> = (0..self.nodes.len()).filter(|&n| n != ind).collect();
while dist.len() < self.nodes.len() {
let mut found_any = false;
for i in (0..nodes.len()).rev() {
let j = nodes[i];
let edges = self.edges_of(j);
let mut min: Option<u64> = None;
for &e in &edges {
for k in 0..dist.len() {
if dist[k].0 == e {
if min.is_none() || min.unwrap() > dist[k].1 {
min = Some(dist[k].1);
}
}
}
}
if min.is_some() {
dist.push((j, min.unwrap() + 1));
found_any = true;
nodes.swap_remove(i);
}
}
if !found_any {
dist.sort();
return Err(dist);
}
}
dist.sort();
loop {
let mut found_any = false;
for i in 0..dist.len() {
let j = dist[i].0;
let edges = self.edges_of(j);
for &e in &edges {
let k = dist.binary_search_by(|n| n.0.cmp(&e)).unwrap();
if dist[j].1 > dist[k].1 + 1 {
dist[j].1 = dist[k].1 + 1;
found_any = true;
}
}
}
if !found_any {break};
}
Ok(dist)
}
pub fn avatar_distance(&self, ind: usize) -> Vec<(usize, u64)> {
let mut dist = match self.distance(ind) {
Ok(x) => x,
Err(x) => x,
};
dist.sort_by_key(|n| n.1);
let mut count_children = vec![0; self.nodes.len()];
for i in 0..dist.len() {
let j = dist[i].0;
let edges = self.edges_of(j);
let mut count = 0;
for &e in &edges {
for k in 0..i {
if dist[k].0 != e {continue};
count += 1;
}
}
count_children[j] = count;
}
dist.sort_by(|a, b| {
a.1.cmp(&b.1).then((-count_children[a.0]).cmp(&-count_children[b.0]))
});
for i in 0..dist.len() {
let j = dist[i].0;
let edges = self.edges_of(j);
let mut sum = 0;
for &e in &edges {
for k in 0..i {
if dist[k].0 != e {continue};
let m = dist[k].1;
sum += if m == 0 {1} else {m};
}
}
dist[i].1 = sum.max(dist[i].1);
}
dist.sort();
dist
}
pub fn max_avatars(&self, ind: usize) -> (u64, Vec<usize>) {
let dist = self.avatar_distance(ind);
let mut max = 0;
let mut avatars = vec![];
for &(a, n) in &dist {
if n > max {
avatars.clear();
avatars.push(a);
max = n;
} else if n == max {
avatars.push(a);
}
}
(max, avatars)
}
pub fn contractible(&self, ind: usize) -> usize {
let mut dist = match self.distance(ind) {
Ok(x) => x,
Err(x) => x,
};
dist.sort_by_key(|n| n.1);
let mut contr = 0;
for i in 0..dist.len() {
let j = dist[i].0;
let n = dist[i].1;
let edges = self.edges_of(j);
let mut count = 0;
for &e in &edges {
for k in (0..dist.len()).rev() {
if dist[k].0 != e {continue};
let m = dist[k].1;
if m == 0 || m > n {continue};
count += 1;
}
}
if count == 1 {
contr += 1;
}
}
contr
}
pub fn contractibles_of(&self, ind: usize) -> Vec<usize> {
let mut dist = match self.distance(ind) {
Ok(x) => x,
Err(x) => x,
};
dist.sort_by_key(|n| n.1);
let mut res = vec![];
for i in 0..dist.len() {
let j = dist[i].0;
let n = dist[i].1;
let edges = self.edges_of(j);
let mut count = 0;
for &e in &edges {
for k in (0..dist.len()).rev() {
if dist[k].0 != e {continue};
let m = dist[k].1;
if m == 0 || m > n {continue};
count += 1;
}
}
if count == 1 {
res.push(j);
}
}
res
}
pub fn swap(&mut self, a: usize, b: usize) {
for i in 0..self.edges.len() {
let (ea, eb) = self.edges[i];
let ea = if ea == a {b} else if ea == b {a} else {ea};
let eb = if eb == a {b} else if eb == b {a} else {eb};
self.edges[i] = (ea.min(eb), ea.max(eb));
}
for i in 0..self.nodes.len() {
if let Some(j) = self.nodes[i].uniq {
self.nodes[i].uniq = Some(if j == a {b} else if j == b {a} else {j});
}
}
self.nodes.swap(a, b);
}
pub fn along(&self, a: usize, b: usize) -> Result<Vec<usize>, ()> {
let dist = match self.distance(b) {
Ok(x) => x,
Err(_) => return Err(())
};
let k = dist.binary_search_by(|n| n.0.cmp(&a)).map_err(|_| ())?;
let max_dist = dist[k].1;
let mut at = vec![dist[k]];
let mut i = 0;
let mut reached = vec![false; dist.len()];
reached[k] = true;
loop {
if i >= at.len() {break};
if reached.iter().all(|&b| b) {break};
let j = at[i].0;
if at[i].1 != 0 {
let edges = self.edges_of(j);
for e in &edges {
if reached[*e] {continue};
let k = dist.binary_search_by(|n| n.0.cmp(e)).unwrap();
if dist[k].1 > max_dist {continue};
at.push(dist[k]);
reached[k] = true;
}
}
i += 1;
}
let mut nodes: Vec<usize> = at.into_iter().map(|n| n.0).collect();
nodes.sort();
Ok(nodes)
}
pub fn all_reachable_along(&self, a: usize, b: usize) -> bool {
match self.along(a, b) {
Ok(v) => v == (0..self.nodes.len()).collect::<Vec<usize>>(),
Err(()) => false,
}
}
pub fn avatar_connectivity(&self, ind: usize) -> bool {
let dist = self.avatar_distance(ind);
for i in 0..dist.len() {
let j = dist[i].0;
let n = dist[i].1;
let edges = self.edges_of(j);
for &e in &edges {
let k = dist.binary_search_by(|n| n.0.cmp(&e)).unwrap();
let m = dist[k].1;
if dist[k].0 == e {
if !match n {
0 => m == 1,
1 => m == 0 || m > 1,
n => m > 0 && m < n || m > n,
} {return false};
}
}
}
true
}
pub fn avatar_connectivity_failures_of(&self, ind: usize) -> Vec<usize> {
let mut dist = self.avatar_distance(ind);
dist.sort_by_key(|n| n.1);
let mut res = vec![];
for i in 0..dist.len() {
let j = dist[i].0;
if j == ind {continue};
let n = dist[i].1;
let edges = self.edges_of(j);
let mut found = false;
'outer: for &e in &edges {
for k in 0..dist.len() {
let m = dist[k].1;
if dist[k].0 == e {
if !match n {
0 => m == 1,
1 => m == 0 || m > 1,
n => m > 0 && m < n || m > n,
} {
found = true;
break 'outer;
}
}
}
}
if found {
res.push(j);
}
}
res
}
pub fn is_avatar_graph(&self, ind: usize) -> bool {
if self.contractible(ind) != 0 {return false};
if self.distance(ind).is_err() {return false};
let max_avatars = self.max_avatars(ind);
if max_avatars.1.len() != 1 {return false};
if !self.all_reachable_along(max_avatars.1[0], ind) {return false};
if !self.avatar_connectivity(ind) {return false};
true
}
pub fn corify(&mut self) {
for i in 0..self.nodes.len() {
if self.is_avatar_graph(i) {
self.nodes[i].core = true;
self.nodes[i].uniq = Some(self.max_avatars(i).1[0])
} else {
self.nodes[i].core = false;
self.nodes[i].uniq = None;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_graph() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
g.add_edge(a, b);
assert_eq!(g.nodes.len(), 2);
assert_eq!(g.edges.len(), 1);
assert_eq!(g.cores(), 1);
assert_eq!(g.non_cores(), 1);
assert_eq!(g.edges_of(a), vec![b]);
assert_eq!(g.edges_of(b), vec![a]);
assert_eq!(g.self_edges(), 0);
assert_eq!(g.matrix(), vec![
vec![0, 1],
vec![0, 0]
]);
assert_eq!(g.unique_edges(), 0);
}
#[test]
fn remove_self_edges() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
g.add_edge(a, a);
assert_eq!(g.self_edges(), 1);
g.remove_self_edges();
assert_eq!(g.self_edges(), 0);
assert_eq!(g.matrix(), vec![
vec![0]
]);
assert_eq!(g.unique_edges(), 0);
}
#[test]
fn unique_edge() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
assert_eq!(g.matrix(), vec![
vec![0, 0],
vec![0, 0]
]);
assert_eq!(g.unique_edges(), 0);
g.nodes[a].uniq = Some(b);
assert_eq!(g.unique_edges(), 1);
assert_eq!(g.matrix(), vec![
vec![0, 2],
vec![0, 0]
]);
g.add_edge(a, b);
assert_eq!(g.matrix(), vec![
vec![0, 3],
vec![0, 0]
]);
assert_eq!(g.unique_edges(), 1);
}
#[test]
fn self_unique_edge() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
assert_eq!(g.self_unique_edges(), 0);
g.nodes[a].uniq = Some(a);
assert_eq!(g.self_unique_edges(), 1);
g.remove_self_unique_edges();
assert_eq!(g.self_unique_edges(), 0);
}
#[test]
fn order() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
assert_eq!(g.distance(a), Err(vec![(a, 0)]));
assert_eq!(g.distance(b), Err(vec![(b, 0)]));
g.add_edge(a, b);
assert_eq!(g.distance(a), Ok(vec![(a, 0), (b, 1)]));
assert_eq!(g.distance(b), Ok(vec![(a, 1), (b, 0)]));
}
#[test]
fn max_avatars() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
let d = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(a, c);
g.add_edge(b, d);
g.add_edge(c, d);
assert_eq!(g.max_avatars(a), (2, vec![d]));
}
#[test]
fn avatar3() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
let d = g.add_node(Node::new(false));
let e = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(a, c);
g.add_edge(b, d);
g.add_edge(c, d);
g.add_edge(b, e);
g.add_edge(d, e);
assert_eq!(g.avatar_distance(a), vec![(0, 0), (1, 1), (2, 1), (3, 2), (4, 3)]);
}
#[test]
fn contractible() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(b, c);
assert_eq!(g.contractible(a), 1);
}
#[test]
fn swap() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(a, c);
assert_eq!(g.edges, vec![(0, 1), (0, 2)]);
g.swap(a, b);
assert_eq!(g.edges, vec![(0, 1), (1, 2)]);
}
#[test]
fn avatar_graph() {
let mut g = Graph::new();
let a = g.add_node(Node::new(true));
let b = g.add_node(Node::new(false));
assert_eq!(g.is_avatar_graph(a), false);
g.add_edge(a, b);
assert_eq!(g.is_avatar_graph(a), true);
assert_eq!(g.is_avatar_graph(b), true);
let c = g.add_node(Node::new(false));
assert_eq!(g.is_avatar_graph(a), false);
g.add_edge(a, c);
assert_eq!(g.is_avatar_graph(a), false);
let d = g.add_node(Node::new(false));
assert_eq!(g.is_avatar_graph(a), false);
g.add_edge(c, d);
assert_eq!(g.is_avatar_graph(a), false);
g.add_edge(b, d);
assert_eq!(g.is_avatar_graph(a), true);
}
#[test]
fn corify() {
let mut g = Graph::new();
let a = g.add_node(Node::new(false));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
let d = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(a, c);
g.add_edge(b, d);
g.add_edge(c, d);
g.corify();
assert_eq!(g.nodes[a].core, true);
assert_eq!(g.nodes[b].core, true);
assert_eq!(g.nodes[c].core, true);
assert_eq!(g.nodes[d].core, true);
assert_eq!(g.nodes[a].uniq, Some(d));
assert_eq!(g.nodes[b].uniq, Some(c));
assert_eq!(g.nodes[c].uniq, Some(b));
assert_eq!(g.nodes[d].uniq, Some(a));
let mut g = Graph::new();
let a = g.add_node(Node::new(false));
let b = g.add_node(Node::new(false));
let c = g.add_node(Node::new(false));
g.add_edge(a, b);
g.add_edge(b, c);
g.add_edge(c, a);
g.corify();
assert_eq!(g.cores(), 0);
}
#[test]
fn corify_cube() {
let mut g = Graph::new();
let a000 = g.add_node(Node::new(false));
let a100 = g.add_node(Node::new(false));
let a010 = g.add_node(Node::new(false));
let a001 = g.add_node(Node::new(false));
let a011 = g.add_node(Node::new(false));
let a101 = g.add_node(Node::new(false));
let a110 = g.add_node(Node::new(false));
let a111 = g.add_node(Node::new(false));
g.add_edge(a000, a100);
g.add_edge(a000, a010);
g.add_edge(a000, a001);
g.add_edge(a100, a110);
g.add_edge(a100, a101);
g.add_edge(a010, a110);
g.add_edge(a010, a011);
g.add_edge(a001, a101);
g.add_edge(a001, a011);
g.add_edge(a011, a111);
g.add_edge(a101, a111);
g.add_edge(a110, a111);
g.corify();
assert_eq!(g.cores(), 8);
let mut g = Graph::new();
let a000 = g.add_node(Node::new(false));
let a110 = g.add_node(Node::new(false));
let a101 = g.add_node(Node::new(false));
let a100 = g.add_node(Node::new(false));
let a111 = g.add_node(Node::new(false));
let a010 = g.add_node(Node::new(false));
let a001 = g.add_node(Node::new(false));
let a011 = g.add_node(Node::new(false));
g.add_edge(a010, a011);
g.add_edge(a001, a011);
g.add_edge(a000, a010);
g.add_edge(a010, a110);
g.add_edge(a101, a111);
g.add_edge(a000, a001);
g.add_edge(a011, a111);
g.add_edge(a100, a110);
g.add_edge(a100, a101);
g.add_edge(a000, a100);
g.add_edge(a001, a101);
g.add_edge(a110, a111);
g.corify();
assert_eq!(g.cores(), 8);
}
#[test]
fn corify_cube4() {
let mut g = Graph {
nodes: vec![Node::new(false); 16],
edges: vec![
(0, 3), (2, 3), (1, 2), (0, 1),
(0, 4), (4, 7), (3, 7), (6, 7),
(2, 6), (5, 6), (1, 5), (4, 5),
(8, 15), (12, 15), (9, 12), (8, 9),
(9, 11), (10, 11), (8, 10), (10, 14),
(13, 14), (11, 13), (12, 13), (14, 15),
(4, 15), (5, 12), (1, 9), (0, 8),
(6, 13), (7, 14), (3, 10), (2, 11)
]
};
g.corify();
assert_eq!(g.cores(), 16);
}
#[test]
fn corify_5() {
let mut g = Graph {
nodes: vec![Node::new(false); 5],
edges: vec![
(0, 1), (1, 2),
(2, 4), (3, 4),
(0, 3), (2, 3)
]
};
g.corify();
assert_eq!(g.cores(), 2);
}
#[test]
fn corify_7() {
let mut g = Graph {
nodes: vec![Node::new(false); 7],
edges: vec![
(0, 3), (1, 3), (1, 2),
(0, 2), (0, 4), (2, 4),
(2, 5), (1, 5), (5, 6),
(4, 6)
]
};
g.corify();
assert_eq!(g.cores(), 2);
}
#[test]
fn wagner() {
let mut g = Graph {
nodes: vec![Node::new(false); 8],
edges: vec![
(0, 1), (2, 3), (5, 7), (4, 6),
(0, 4), (0, 5), (2, 5), (2, 6),
(1, 6), (1, 7), (3, 7), (3, 4)
]
};
g.corify();
assert_eq!(g.cores(), 8);
}
#[test]
fn corify_8() {
let mut g = Graph {
nodes: vec![Node::new(false); 8],
edges: vec![
(0, 6), (3, 6), (3, 5),
(1, 5), (1, 7), (2, 7),
(2, 4), (0, 4), (4, 5),
(6, 7)
]
};
g.corify();
assert_eq!(g.cores(), 8);
}
}