use petgraph::visit::{IntoNeighborsDirected, IntoNodeIdentifiers, NodeIndexable};
use petgraph::Direction::{Incoming, Outgoing};
pub fn isolates<G>(graph: G) -> Vec<G::NodeId>
where
G: NodeIndexable + IntoNodeIdentifiers + IntoNeighborsDirected,
{
graph
.node_identifiers()
.filter(|x| {
graph
.neighbors_directed(*x, Incoming)
.chain(graph.neighbors_directed(*x, Outgoing))
.next()
.is_none()
})
.collect()
}
#[cfg(test)]
mod tests {
use crate::connectivity::isolates;
use petgraph::prelude::*;
#[test]
fn test_isolates_directed_empty() {
let graph = DiGraph::<i32, i32>::new();
let res: Vec<NodeIndex> = isolates(&graph);
assert_eq!(res, []);
}
#[test]
fn test_isolates_undirected_empty() {
let graph = UnGraph::<i32, i32>::default();
let res: Vec<NodeIndex> = isolates(&graph);
assert_eq!(res, []);
}
#[test]
fn test_isolates_directed_no_isolates() {
let graph = DiGraph::<i32, i32>::from_edges([(0, 1), (1, 2)]);
let res: Vec<NodeIndex> = isolates(&graph);
assert_eq!(res, []);
}
#[test]
fn test_isolates_undirected_no_isolates() {
let graph = UnGraph::<i32, i32>::from_edges([(0, 1), (1, 2)]);
let res: Vec<NodeIndex> = isolates(&graph);
assert_eq!(res, []);
}
#[test]
fn test_isolates_directed() {
let edge_list = vec![
(0, 1),
(3, 0),
(0, 5),
(8, 0),
(1, 2),
(1, 6),
(2, 3),
(3, 4),
(4, 5),
(6, 7),
(7, 8),
(8, 9),
];
let mut graph = DiGraph::<i32, i32>::from_edges(edge_list);
graph.add_node(10);
graph.add_node(11);
let res: Vec<usize> = isolates(&graph).into_iter().map(|x| x.index()).collect();
assert_eq!(res, [10, 11])
}
#[test]
fn test_isolates_undirected() {
let edge_list = vec![
(0, 1),
(3, 0),
(0, 5),
(8, 0),
(1, 2),
(1, 6),
(2, 3),
(3, 4),
(4, 5),
(6, 7),
(7, 8),
(8, 9),
];
let mut graph = UnGraph::<i32, i32>::from_edges(edge_list);
graph.add_node(10);
graph.add_node(11);
let res: Vec<usize> = isolates(&graph).into_iter().map(|x| x.index()).collect();
assert_eq!(res, [10, 11])
}
}