use std::collections::VecDeque;
use super::topology::Transitive;
use super::Graph;
impl<T, R> Graph<T, R> {
#[inline]
#[must_use]
pub fn is_source(&self, node: usize) -> bool {
let incoming = self.topology.incoming();
incoming[node].is_empty()
}
#[inline]
#[must_use]
pub fn is_sink(&self, node: usize) -> bool {
let outgoing = self.topology.outgoing();
outgoing[node].is_empty()
}
#[inline]
#[must_use]
pub fn is_predecessor(&self, source: usize, target: usize) -> bool {
let outgoing = self.topology.outgoing();
outgoing[source].contains(&target)
}
#[inline]
#[must_use]
pub fn is_successor(&self, source: usize, target: usize) -> bool {
let incoming = self.topology.incoming();
incoming[source].contains(&target)
}
#[must_use]
pub fn is_acyclic(&self) -> bool {
let incoming = self.topology.incoming();
let outgoing = self.topology.outgoing();
let mut degrees = incoming.degrees().to_vec();
let mut queue: VecDeque<usize> =
self.iter().filter(|&node| degrees[node] == 0).collect();
let mut visited = 0;
while let Some(source) = queue.pop_front() {
visited += 1;
for &target in &outgoing[source] {
degrees[target] -= 1;
if degrees[target] == 0 {
queue.push_back(target);
}
}
}
visited == self.len()
}
}
impl<T> Graph<T, Transitive> {
#[inline]
#[must_use]
pub fn is_ancestor(&self, source: usize, target: usize) -> bool {
self.topology.has_path(source, target)
}
#[inline]
#[must_use]
pub fn is_descendant(&self, source: usize, target: usize) -> bool {
self.topology.has_path(target, source)
}
}