use std::collections::VecDeque;
use ndarray::prelude::*;
use crate::{
models::{DiGraph, Graph},
set,
};
pub trait TopologicalOrder {
fn topological_order(&self) -> Option<Vec<usize>>;
}
impl TopologicalOrder for DiGraph {
fn topological_order(&self) -> Option<Vec<usize>> {
let mut in_degree = self
.to_adjacency_matrix()
.mapv(|x| x as usize)
.sum_axis(Axis(0));
let mut to_be_visited: VecDeque<usize> = in_degree
.iter()
.enumerate()
.filter_map(|(i, &d)| if d == 0 { Some(i) } else { None })
.collect();
let mut order = Vec::with_capacity(in_degree.len());
while let Some(i) = to_be_visited.pop_front() {
order.push(i);
self.children(&set![i]).into_iter().for_each(|y| {
in_degree[y] -= 1;
if in_degree[y] == 0 {
to_be_visited.push_back(y);
}
});
}
if in_degree.len() == order.len() {
Some(order)
} else {
None }
}
}