1use std::cmp::{Eq, Ordering};
14use std::collections::BinaryHeap;
15use std::error::Error;
16use std::fmt::{Display, Formatter};
17use std::hash::Hash;
18
19use hashbrown::{HashMap, HashSet};
20use std::fmt::Debug;
21use std::mem::swap;
22
23use petgraph::algo;
24use petgraph::data::DataMap;
25use petgraph::visit::{
26 EdgeRef, GraphBase, GraphProp, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers,
27 NodeCount, NodeIndexable, Visitable,
28};
29use petgraph::Directed;
30
31use num_traits::{Num, Zero};
32
33use crate::err::LayersError;
34
35#[inline(always)]
39pub fn traversal_directions(reverse: bool) -> (petgraph::Direction, petgraph::Direction) {
40 if reverse {
41 (petgraph::Direction::Outgoing, petgraph::Direction::Incoming)
42 } else {
43 (petgraph::Direction::Incoming, petgraph::Direction::Outgoing)
44 }
45}
46
47#[derive(Debug, PartialEq, Eq)]
49pub enum TopologicalSortError<E: Error> {
50 CycleOrBadInitialState,
51 KeyError(E),
52}
53
54impl<E: Error> Display for TopologicalSortError<E> {
55 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
56 match self {
57 TopologicalSortError::CycleOrBadInitialState => {
58 write!(f, "At least one initial node is reachable from another")
59 }
60 TopologicalSortError::KeyError(ref e) => {
61 write!(f, "The key callback failed with: {:?}", e)
62 }
63 }
64 }
65}
66
67impl<E: Error> Error for TopologicalSortError<E> {}
68
69pub fn lexicographical_topological_sort<G, F, K, E>(
146 dag: G,
147 mut key: F,
148 reverse: bool,
149 initial: Option<&[G::NodeId]>,
150) -> Result<Vec<G::NodeId>, TopologicalSortError<E>>
151where
152 G: GraphProp<EdgeType = Directed>
153 + IntoNodeIdentifiers
154 + IntoNeighborsDirected
155 + IntoEdgesDirected
156 + NodeCount,
157 <G as GraphBase>::NodeId: Hash + Eq + Ord,
158 F: FnMut(G::NodeId) -> Result<K, E>,
159 K: Ord,
160 E: Error,
161{
162 let node_count = dag.node_count();
164 let (in_dir, out_dir) = traversal_directions(reverse);
165
166 #[derive(Clone, Eq, PartialEq)]
167 struct State<K: Ord, N: Eq + PartialOrd> {
168 key: K,
169 node: N,
170 }
171
172 impl<K: Ord, N: Eq + Ord> Ord for State<K, N> {
173 fn cmp(&self, other: &State<K, N>) -> Ordering {
174 other
178 .key
179 .cmp(&self.key)
180 .then_with(|| other.node.cmp(&self.node))
181 }
182 }
183
184 impl<K: Ord, N: Eq + Ord> PartialOrd for State<K, N> {
186 fn partial_cmp(&self, other: &State<K, N>) -> Option<Ordering> {
187 Some(self.cmp(other))
188 }
189 }
190
191 let mut in_degree_map: HashMap<G::NodeId, usize> = HashMap::with_capacity(node_count);
192 if let Some(initial) = initial {
193 for node in initial {
196 in_degree_map.insert(*node, 0);
197 }
198 } else {
199 for node in dag.node_identifiers() {
200 in_degree_map.insert(node, dag.edges_directed(node, in_dir).count());
201 }
202 }
203
204 let mut zero_indegree = BinaryHeap::with_capacity(node_count);
205 for (node, degree) in in_degree_map.iter() {
206 if *degree == 0 {
207 let map_key = key(*node).map_err(|e| TopologicalSortError::KeyError(e))?;
208 zero_indegree.push(State {
209 key: map_key,
210 node: *node,
211 });
212 }
213 }
214 let mut out_list: Vec<G::NodeId> = Vec::with_capacity(node_count);
215 while let Some(State { node, .. }) = zero_indegree.pop() {
216 let neighbors = dag.neighbors_directed(node, out_dir);
217 for child in neighbors {
218 let child_degree = in_degree_map
219 .entry(child)
220 .or_insert_with(|| dag.edges_directed(child, in_dir).count());
221 if *child_degree == 0 {
222 return Err(TopologicalSortError::CycleOrBadInitialState);
223 } else if *child_degree == 1 {
224 let map_key = key(child).map_err(|e| TopologicalSortError::KeyError(e))?;
225 zero_indegree.push(State {
226 key: map_key,
227 node: child,
228 });
229 in_degree_map.remove(&child);
230 } else {
231 *child_degree -= 1;
232 }
233 }
234 out_list.push(node)
235 }
236 Ok(out_list)
237}
238
239type NodeId<G> = <G as GraphBase>::NodeId;
241type LongestPathResult<G, T, E> = Result<Option<(Vec<NodeId<G>>, T)>, E>;
242
243pub fn longest_path<G, F, T, E>(graph: G, mut weight_fn: F) -> LongestPathResult<G, T, E>
285where
286 G: GraphProp<EdgeType = Directed> + IntoNodeIdentifiers + IntoEdgesDirected + Visitable,
287 F: FnMut(G::EdgeRef) -> Result<T, E>,
288 T: Num + Zero + PartialOrd + Copy,
289 <G as GraphBase>::NodeId: Hash + Eq + PartialOrd,
290{
291 let mut path: Vec<NodeId<G>> = Vec::new();
292 let nodes = match algo::toposort(graph, None) {
293 Ok(nodes) => nodes,
294 Err(_) => return Ok(None), };
296
297 if nodes.is_empty() {
298 return Ok(Some((path, T::zero())));
299 }
300
301 let mut dist: HashMap<G::NodeId, (T, G::NodeId)> = HashMap::with_capacity(nodes.len()); for node in nodes {
305 let parents = graph.edges_directed(node, petgraph::Direction::Incoming);
306 let mut incoming_path: Vec<(T, G::NodeId)> = Vec::new(); for p_edge in parents {
308 let p_node = p_edge.source();
309 let weight: T = weight_fn(p_edge)?;
310 let length = dist[&p_node].0 + weight;
311 incoming_path.push((length, p_node));
312 }
313 let max_path: (T, G::NodeId) = incoming_path
315 .into_iter()
316 .max_by(|a, b| a.0.partial_cmp(&b.0).unwrap())
317 .unwrap_or((T::zero(), node)); dist.insert(node, max_path);
321 }
322 let (first, _) = dist
323 .iter()
324 .max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
325 .unwrap();
326 let mut v = *first;
327 let mut u: Option<G::NodeId> = None;
328 #[allow(clippy::unnecessary_map_or)]
330 while u.map_or(true, |u| u != v) {
331 path.push(v);
332 u = Some(v);
333 v = dist[&v].1;
334 }
335 path.reverse(); let path_weight = dist[first].0; Ok(Some((path, path_weight)))
339}
340
341pub fn layers<G>(
377 graph: G,
378 first_layer: Vec<G::NodeId>,
379) -> impl Iterator<Item = Result<Vec<G::NodeId>, LayersError>>
380where
381 G: NodeIndexable + IntoNodeIdentifiers + IntoNeighborsDirected + IntoEdgesDirected, <G as GraphBase>::NodeId: Debug + Copy + Eq + Hash,
386{
387 LayersIter {
388 graph,
389 cur_layer: first_layer,
390 next_layer: vec![],
391 predecessor_count: HashMap::new(),
392 first_iter: true,
393 cycle_check: HashSet::default(),
394 }
395}
396
397#[derive(Debug, Clone)]
398struct LayersIter<G, N> {
399 graph: G,
400 cur_layer: Vec<N>,
401 next_layer: Vec<N>,
402 predecessor_count: HashMap<N, usize>,
403 first_iter: bool,
404 cycle_check: HashSet<N>, }
406
407impl<G, N> Iterator for LayersIter<G, N>
408where
409 G: NodeIndexable + IntoNodeIdentifiers + IntoNeighborsDirected + IntoEdgesDirected + GraphBase<NodeId = N>,
414 N: Debug + Copy + Eq + Hash,
415{
416 type Item = Result<Vec<N>, LayersError>;
417 fn next(&mut self) -> Option<Self::Item> {
418 if self.first_iter {
419 self.first_iter = false;
420 for node in &self.cur_layer {
421 if self.graph.to_index(*node) >= self.graph.node_bound() {
422 panic!("Node {:#?} is not present in the graph.", node);
423 }
424 if self.cycle_check.contains(node) {
425 return Some(Err(LayersError(format!(
426 "An invalid first layer was provided: {:#?} appears more than once.",
427 node
428 ))));
429 }
430 self.cycle_check.insert(*node);
431 }
432 Some(Ok(self.cur_layer.clone()))
433 } else if self.cur_layer.is_empty() {
434 None
435 } else {
436 for node in &self.cur_layer {
437 if self.graph.to_index(*node) >= self.graph.node_bound() {
438 panic!("Node {:#?} is not present in the graph.", node);
439 }
440 let children = self
441 .graph
442 .neighbors_directed(*node, petgraph::Direction::Outgoing);
443 let mut used_indices: HashSet<G::NodeId> = HashSet::new();
444 for succ in children {
445 if used_indices.contains(&succ) {
447 continue;
448 }
449 used_indices.insert(succ);
450 let mut multiplicity: usize = 0;
451 let raw_edges: G::EdgesDirected = self
452 .graph
453 .edges_directed(*node, petgraph::Direction::Outgoing);
454 for edge in raw_edges {
455 if edge.target() == succ {
456 multiplicity += 1;
457 }
458 }
459 self.predecessor_count
460 .entry(succ)
461 .and_modify(|e| *e -= multiplicity)
462 .or_insert(
463 self.graph
465 .edges_directed(succ, petgraph::Direction::Incoming)
466 .count()
467 - multiplicity,
468 );
469 if *self.predecessor_count.get(&succ).unwrap() == 0 {
470 if self.cycle_check.contains(&succ) {
471 return Some(Err(LayersError("The provided graph contains a cycle or an invalid first layer was provided.".to_string())));
472 }
473 self.next_layer.push(succ);
474 self.cycle_check.insert(succ);
475 self.predecessor_count.remove(&succ);
476 }
477 }
478 }
479 swap(&mut self.cur_layer, &mut self.next_layer);
480 self.next_layer.clear();
481 if self.cur_layer.is_empty() {
482 None
483 } else {
484 Some(Ok(self.cur_layer.clone()))
485 }
486 }
487 }
488}
489
490pub fn collect_bicolor_runs<G, F, C, E>(
553 graph: G,
554 filter_fn: F,
555 color_fn: C,
556) -> Result<Option<Vec<Vec<G::NodeId>>>, E>
557where
558 F: Fn(<G as GraphBase>::NodeId) -> Result<Option<bool>, E>,
559 C: Fn(<G as GraphBase>::EdgeId) -> Result<Option<usize>, E>,
560 G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoEdgesDirected + Visitable + DataMap, <G as GraphBase>::NodeId: Eq + Hash,
566 <G as GraphBase>::EdgeId: Eq + Hash,
567{
568 let mut pending_list: Vec<Vec<G::NodeId>> = Vec::new();
569 let mut block_id: Vec<Option<usize>> = Vec::new();
570 let mut block_list: Vec<Vec<G::NodeId>> = Vec::new();
571
572 let nodes = match algo::toposort(graph, None) {
573 Ok(nodes) => nodes,
574 Err(_) => return Ok(None), };
576
577 macro_rules! ensure_vector_has_index {
579 ($pending_list: expr, $block_id: expr, $color: expr) => {
580 if $color >= $pending_list.len() {
581 $pending_list.resize($color + 1, Vec::new());
582 $block_id.resize($color + 1, None);
583 }
584 };
585 }
586
587 for node in nodes {
588 if let Some(is_match) = filter_fn(node)? {
589 let raw_edges = graph.edges_directed(node, petgraph::Direction::Outgoing);
590
591 let colors = raw_edges
593 .map(|edge| color_fn(edge.id()))
594 .collect::<Result<Vec<Option<usize>>, _>>()?;
595
596 let colors = colors.into_iter().flatten().collect::<Vec<usize>>();
598
599 match (colors.len(), is_match) {
600 (1, true) => {
601 let c0 = colors[0];
602 ensure_vector_has_index!(pending_list, block_id, c0);
603 if let Some(c0_block_id) = block_id[c0] {
604 block_list[c0_block_id].push(node);
605 } else {
606 pending_list[c0].push(node);
607 }
608 }
609 (2, true) => {
610 let c0 = colors[0];
611 let c1 = colors[1];
612 ensure_vector_has_index!(pending_list, block_id, c0);
613 ensure_vector_has_index!(pending_list, block_id, c1);
614
615 if block_id[c0].is_some()
616 && block_id[c1].is_some()
617 && block_id[c0] == block_id[c1]
618 {
619 block_list[block_id[c0].unwrap_or_default()].push(node);
620 } else {
621 let mut new_block: Vec<G::NodeId> =
622 Vec::with_capacity(pending_list[c0].len() + pending_list[c1].len() + 1);
623
624 new_block.append(&mut pending_list[c0]);
626 new_block.append(&mut pending_list[c1]);
627
628 new_block.push(node);
629
630 block_id[c0] = Some(block_list.len());
632 block_id[c1] = Some(block_list.len());
633 block_list.push(new_block);
634 }
635 }
636 _ => {
637 for color in colors {
638 ensure_vector_has_index!(pending_list, block_id, color);
639 if let Some(color_block_id) = block_id[color] {
640 block_list[color_block_id].append(&mut pending_list[color]);
641 }
642 block_id[color] = None;
643 pending_list[color].clear();
644 }
645 }
646 }
647 }
648 }
649
650 Ok(Some(block_list))
651}
652
653pub fn collect_runs<G, F, E>(
694 graph: G,
695 include_node_fn: F,
696) -> Option<impl Iterator<Item = Result<Vec<G::NodeId>, E>>>
697where
698 G: GraphProp<EdgeType = Directed>
699 + IntoNeighborsDirected
700 + IntoNodeIdentifiers
701 + Visitable
702 + NodeCount,
703 F: Fn(G::NodeId) -> Result<bool, E>,
704 <G as GraphBase>::NodeId: Hash + Eq,
705{
706 let mut nodes = match algo::toposort(graph, None) {
707 Ok(nodes) => nodes,
708 Err(_) => return None,
709 };
710
711 nodes.reverse(); let runs = Runs {
714 graph,
715 seen: HashSet::with_capacity(nodes.len()),
716 sorted_nodes: nodes,
717 include_node_fn,
718 };
719
720 Some(runs)
721}
722
723struct Runs<G, F, E>
730where
731 G: GraphProp<EdgeType = Directed>
732 + IntoNeighborsDirected
733 + IntoNodeIdentifiers
734 + Visitable
735 + NodeCount,
736 F: Fn(G::NodeId) -> Result<bool, E>,
737{
738 graph: G,
739 sorted_nodes: Vec<G::NodeId>, seen: HashSet<G::NodeId>,
741 include_node_fn: F, }
743
744impl<G, F, E> Iterator for Runs<G, F, E>
745where
746 G: GraphProp<EdgeType = Directed>
747 + IntoNeighborsDirected
748 + IntoNodeIdentifiers
749 + Visitable
750 + NodeCount,
751 F: Fn(G::NodeId) -> Result<bool, E>,
752 <G as GraphBase>::NodeId: Hash + Eq,
753{
754 type Item = Result<Vec<G::NodeId>, E>;
756
757 fn next(&mut self) -> Option<Self::Item> {
758 while let Some(node) = self.sorted_nodes.pop() {
759 if self.seen.contains(&node) {
760 continue;
761 }
762 self.seen.insert(node);
763
764 match (self.include_node_fn)(node) {
765 Ok(false) => continue,
766 Err(e) => return Some(Err(e)),
767 _ => (),
768 }
769
770 let mut run: Vec<G::NodeId> = vec![node];
771 loop {
772 let mut successors: Vec<G::NodeId> = self
773 .graph
774 .neighbors_directed(*run.last().unwrap(), petgraph::Direction::Outgoing)
775 .collect();
776 successors.dedup();
777
778 if successors.len() != 1 || self.seen.contains(&successors[0]) {
779 break;
780 }
781
782 self.seen.insert(successors[0]);
783
784 match (self.include_node_fn)(successors[0]) {
785 Ok(false) => continue,
786 Err(e) => return Some(Err(e)),
787 _ => (),
788 }
789
790 run.push(successors[0]);
791 }
792
793 if !run.is_empty() {
794 return Some(Ok(run));
795 }
796 }
797
798 None
799 }
800
801 fn size_hint(&self) -> (usize, Option<usize>) {
802 (0, Some(self.sorted_nodes.len()))
805 }
806}
807
808#[cfg(test)]
810mod test_longest_path {
811 use super::*;
812 use petgraph::graph::DiGraph;
813 use petgraph::stable_graph::StableDiGraph;
814
815 #[test]
816 fn test_empty_graph() {
817 let graph: DiGraph<(), ()> = DiGraph::new();
818 let weight_fn = |_: petgraph::graph::EdgeReference<()>| Ok::<i32, &str>(0);
819 let result = longest_path(&graph, weight_fn);
820 assert_eq!(result, Ok(Some((vec![], 0))));
821 }
822
823 #[test]
824 fn test_single_node_graph() {
825 let mut graph: DiGraph<(), ()> = DiGraph::new();
826 let n0 = graph.add_node(());
827 let weight_fn = |_: petgraph::graph::EdgeReference<()>| Ok::<i32, &str>(0);
828 let result = longest_path(&graph, weight_fn);
829 assert_eq!(result, Ok(Some((vec![n0], 0))));
830 }
831
832 #[test]
833 fn test_dag_with_multiple_paths() {
834 let mut graph: DiGraph<(), i32> = DiGraph::new();
835 let n0 = graph.add_node(());
836 let n1 = graph.add_node(());
837 let n2 = graph.add_node(());
838 let n3 = graph.add_node(());
839 let n4 = graph.add_node(());
840 let n5 = graph.add_node(());
841 graph.add_edge(n0, n1, 3);
842 graph.add_edge(n0, n2, 2);
843 graph.add_edge(n1, n2, 1);
844 graph.add_edge(n1, n3, 4);
845 graph.add_edge(n2, n3, 2);
846 graph.add_edge(n3, n4, 2);
847 graph.add_edge(n2, n5, 1);
848 graph.add_edge(n4, n5, 3);
849 let weight_fn = |edge: petgraph::graph::EdgeReference<i32>| Ok::<i32, &str>(*edge.weight());
850 let result = longest_path(&graph, weight_fn);
851 assert_eq!(result, Ok(Some((vec![n0, n1, n3, n4, n5], 12))));
852 }
853
854 #[test]
855 fn test_graph_with_cycle() {
856 let mut graph: DiGraph<(), i32> = DiGraph::new();
857 let n0 = graph.add_node(());
858 let n1 = graph.add_node(());
859 graph.add_edge(n0, n1, 1);
860 graph.add_edge(n1, n0, 1); let weight_fn = |edge: petgraph::graph::EdgeReference<i32>| Ok::<i32, &str>(*edge.weight());
863 let result = longest_path(&graph, weight_fn);
864 assert_eq!(result, Ok(None));
865 }
866
867 #[test]
868 fn test_negative_weights() {
869 let mut graph: DiGraph<(), i32> = DiGraph::new();
870 let n0 = graph.add_node(());
871 let n1 = graph.add_node(());
872 let n2 = graph.add_node(());
873 graph.add_edge(n0, n1, -1);
874 graph.add_edge(n0, n2, 2);
875 graph.add_edge(n1, n2, -2);
876 let weight_fn = |edge: petgraph::graph::EdgeReference<i32>| Ok::<i32, &str>(*edge.weight());
877 let result = longest_path(&graph, weight_fn);
878 assert_eq!(result, Ok(Some((vec![n0, n2], 2))));
879 }
880
881 #[test]
882 fn test_longest_path_in_stable_digraph() {
883 let mut graph: StableDiGraph<(), i32> = StableDiGraph::new();
884 let n0 = graph.add_node(());
885 let n1 = graph.add_node(());
886 let n2 = graph.add_node(());
887 graph.add_edge(n0, n1, 1);
888 graph.add_edge(n0, n2, 3);
889 graph.add_edge(n1, n2, 1);
890 let weight_fn =
891 |edge: petgraph::stable_graph::EdgeReference<'_, i32>| Ok::<i32, &str>(*edge.weight());
892 let result = longest_path(&graph, weight_fn);
893 assert_eq!(result, Ok(Some((vec![n0, n2], 3))));
894 }
895
896 #[test]
897 fn test_error_handling() {
898 let mut graph: DiGraph<(), i32> = DiGraph::new();
899 let n0 = graph.add_node(());
900 let n1 = graph.add_node(());
901 let n2 = graph.add_node(());
902 graph.add_edge(n0, n1, 1);
903 graph.add_edge(n0, n2, 2);
904 graph.add_edge(n1, n2, 1);
905 let weight_fn = |edge: petgraph::graph::EdgeReference<i32>| {
906 if *edge.weight() == 2 {
907 Err("Error: edge weight is 2")
908 } else {
909 Ok::<i32, &str>(*edge.weight())
910 }
911 };
912 let result = longest_path(&graph, weight_fn);
913 assert_eq!(result, Err("Error: edge weight is 2"));
914 }
915}
916
917#[cfg(test)]
919mod test_lexicographical_topological_sort {
920 use super::*;
921 use petgraph::graph::{DiGraph, NodeIndex};
922 use petgraph::stable_graph::StableDiGraph;
923 use std::convert::Infallible;
924
925 #[test]
926 fn test_empty_graph() {
927 let graph: DiGraph<(), ()> = DiGraph::new();
928 let sort_fn = |_: NodeIndex| -> Result<String, Infallible> { Ok("a".to_string()) };
929 let result = lexicographical_topological_sort(&graph, sort_fn, false, None);
930 assert_eq!(result, Ok(vec![]));
931 }
932
933 #[test]
934 fn test_empty_stable_graph() {
935 let graph: StableDiGraph<(), ()> = StableDiGraph::new();
936 let sort_fn = |_: NodeIndex| -> Result<String, Infallible> { Ok("a".to_string()) };
937 let result = lexicographical_topological_sort(&graph, sort_fn, false, None);
938 assert_eq!(result, Ok(vec![]));
939 }
940
941 #[test]
942 fn test_simple_layer() {
943 let mut graph: DiGraph<String, ()> = DiGraph::new();
944 let mut nodes: Vec<NodeIndex> = Vec::new();
945 nodes.push(graph.add_node("a".to_string()));
946 for i in 0..5 {
947 nodes.push(graph.add_node(i.to_string()));
948 }
949 nodes.push(graph.add_node("A parent".to_string()));
950 for (source, target) in [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (6, 3)] {
951 graph.add_edge(nodes[source], nodes[target], ());
952 }
953 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
954 let result = lexicographical_topological_sort(&graph, sort_fn, false, None);
955 assert_eq!(
956 result,
957 Ok(vec![
958 NodeIndex::new(6),
959 NodeIndex::new(0),
960 NodeIndex::new(1),
961 NodeIndex::new(2),
962 NodeIndex::new(3),
963 NodeIndex::new(4),
964 NodeIndex::new(5)
965 ])
966 )
967 }
968
969 #[test]
970 fn test_simple_layer_stable() {
971 let mut graph: StableDiGraph<String, ()> = StableDiGraph::new();
972 let mut nodes: Vec<NodeIndex> = Vec::new();
973 nodes.push(graph.add_node("a".to_string()));
974 for i in 0..5 {
975 nodes.push(graph.add_node(i.to_string()));
976 }
977 nodes.push(graph.add_node("A parent".to_string()));
978 for (source, target) in [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (6, 3)] {
979 graph.add_edge(nodes[source], nodes[target], ());
980 }
981 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
982 let result = lexicographical_topological_sort(&graph, sort_fn, false, None);
983 assert_eq!(
984 result,
985 Ok(vec![
986 NodeIndex::new(6),
987 NodeIndex::new(0),
988 NodeIndex::new(1),
989 NodeIndex::new(2),
990 NodeIndex::new(3),
991 NodeIndex::new(4),
992 NodeIndex::new(5)
993 ])
994 )
995 }
996
997 #[test]
998 fn test_reverse_graph() {
999 let mut graph: DiGraph<String, ()> = DiGraph::new();
1000 let mut nodes: Vec<NodeIndex> = Vec::new();
1001 for weight in ["a", "b", "c", "d", "e", "f"] {
1002 nodes.push(graph.add_node(weight.to_string()));
1003 }
1004 let edges = [
1005 (nodes[0], nodes[1]),
1006 (nodes[0], nodes[2]),
1007 (nodes[1], nodes[3]),
1008 (nodes[2], nodes[3]),
1009 (nodes[1], nodes[4]),
1010 (nodes[2], nodes[5]),
1011 ];
1012
1013 for (source, target) in edges {
1014 graph.add_edge(source, target, ());
1015 }
1016 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
1017 let result = lexicographical_topological_sort(&graph, sort_fn, true, None);
1018 graph.reverse();
1019 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
1020 let expected = lexicographical_topological_sort(&graph, sort_fn, false, None);
1021 assert_eq!(result, expected,)
1022 }
1023
1024 #[test]
1025 fn test_reverse_graph_stable() {
1026 let mut graph: StableDiGraph<String, ()> = StableDiGraph::new();
1027 let mut nodes: Vec<NodeIndex> = Vec::new();
1028 for weight in ["a", "b", "c", "d", "e", "f"] {
1029 nodes.push(graph.add_node(weight.to_string()));
1030 }
1031 let edges = [
1032 (nodes[0], nodes[1]),
1033 (nodes[0], nodes[2]),
1034 (nodes[1], nodes[3]),
1035 (nodes[2], nodes[3]),
1036 (nodes[1], nodes[4]),
1037 (nodes[2], nodes[5]),
1038 ];
1039
1040 for (source, target) in edges {
1041 graph.add_edge(source, target, ());
1042 }
1043 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
1044 let result = lexicographical_topological_sort(&graph, sort_fn, true, None);
1045 graph.reverse();
1046 let sort_fn = |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].clone()) };
1047 let expected = lexicographical_topological_sort(&graph, sort_fn, false, None);
1048 assert_eq!(result, expected,)
1049 }
1050
1051 #[test]
1052 fn test_initial() {
1053 let mut graph: StableDiGraph<u8, ()> = StableDiGraph::new();
1054 let mut nodes: Vec<NodeIndex> = Vec::new();
1055 for weight in 0..9 {
1056 nodes.push(graph.add_node(weight));
1057 }
1058 let edges = [
1059 (nodes[0], nodes[1]),
1060 (nodes[0], nodes[2]),
1061 (nodes[1], nodes[3]),
1062 (nodes[2], nodes[4]),
1063 (nodes[3], nodes[4]),
1064 (nodes[4], nodes[5]),
1065 (nodes[5], nodes[6]),
1066 (nodes[4], nodes[7]),
1067 (nodes[6], nodes[8]),
1068 (nodes[7], nodes[8]),
1069 ];
1070 for (source, target) in edges {
1071 graph.add_edge(source, target, ());
1072 }
1073 let sort_fn =
1074 |index: NodeIndex| -> Result<String, Infallible> { Ok(graph[index].to_string()) };
1075 let initial = [nodes[6], nodes[7]];
1076 let result = lexicographical_topological_sort(&graph, sort_fn, false, Some(&initial));
1077 assert_eq!(result, Ok(vec![nodes[6], nodes[7], nodes[8]]));
1078 let initial = [nodes[0]];
1079 let result = lexicographical_topological_sort(&graph, sort_fn, false, Some(&initial));
1080 assert_eq!(
1081 result,
1082 lexicographical_topological_sort(&graph, sort_fn, false, None)
1083 );
1084 let initial = [nodes[7]];
1085 let result = lexicographical_topological_sort(&graph, sort_fn, false, Some(&initial));
1086 assert_eq!(result, Ok(vec![nodes[7]]));
1087 }
1088}
1089
1090#[cfg(test)]
1091mod test_layers {
1092 use super::*;
1093 use petgraph::{
1094 graph::{DiGraph, NodeIndex},
1095 stable_graph::StableDiGraph,
1096 };
1097
1098 #[test]
1099 fn test_empty_graph() {
1100 let graph: DiGraph<(), ()> = DiGraph::new();
1101 let result: Vec<Vec<NodeIndex>> = layers(&graph, vec![]).flatten().collect();
1102 assert_eq!(result, vec![vec![]]);
1103 }
1104
1105 #[test]
1106 fn test_empty_stable_graph() {
1107 let graph: StableDiGraph<(), ()> = StableDiGraph::new();
1108 let result: Vec<Vec<NodeIndex>> = layers(&graph, vec![]).flatten().collect();
1109 assert_eq!(result, vec![vec![]]);
1110 }
1111
1112 #[test]
1113 fn test_simple_layer() {
1114 let mut graph: DiGraph<String, ()> = DiGraph::new();
1115 let mut nodes: Vec<NodeIndex> = Vec::new();
1116 nodes.push(graph.add_node("a".to_string()));
1117 for i in 0..5 {
1118 nodes.push(graph.add_node(i.to_string()));
1119 }
1120 nodes.push(graph.add_node("A parent".to_string()));
1121 for (source, target) in [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (6, 3)] {
1122 graph.add_edge(nodes[source], nodes[target], ());
1123 }
1124 let expected: Vec<Vec<NodeIndex>> = vec![
1125 vec![0.into(), 6.into()],
1126 vec![5.into(), 4.into(), 2.into(), 1.into(), 3.into()],
1127 ];
1128 let result: Vec<Vec<NodeIndex>> =
1129 layers(&graph, vec![0.into(), 6.into()]).flatten().collect();
1130 assert_eq!(result, expected);
1131 }
1132
1133 #[test]
1134 #[should_panic]
1135 fn test_missing_node() {
1136 let edge_list = vec![(0, 1), (1, 2), (2, 3), (3, 4)];
1137 let graph = DiGraph::<u32, u32>::from_edges(&edge_list);
1138 layers(&graph, vec![4.into(), 5.into()]).for_each(|layer| match layer {
1139 Err(e) => panic!("{}", e.0),
1140 Ok(layer) => drop(layer),
1141 });
1142 }
1143
1144 #[test]
1145 fn test_dag_with_multiple_paths() {
1146 let mut graph: DiGraph<(), ()> = DiGraph::new();
1147 let n0 = graph.add_node(());
1148 let n1 = graph.add_node(());
1149 let n2 = graph.add_node(());
1150 let n3 = graph.add_node(());
1151 let n4 = graph.add_node(());
1152 let n5 = graph.add_node(());
1153 graph.add_edge(n0, n1, ());
1154 graph.add_edge(n0, n2, ());
1155 graph.add_edge(n1, n2, ());
1156 graph.add_edge(n1, n3, ());
1157 graph.add_edge(n2, n3, ());
1158 graph.add_edge(n3, n4, ());
1159 graph.add_edge(n2, n5, ());
1160 graph.add_edge(n4, n5, ());
1161
1162 let result: Vec<Vec<NodeIndex>> = layers(&graph, vec![0.into()]).flatten().collect();
1163 assert_eq!(
1164 result,
1165 vec![vec![n0], vec![n1], vec![n2], vec![n3], vec![n4], vec![n5]]
1166 );
1167 }
1168
1169 #[test]
1170 #[should_panic]
1171 fn test_graph_with_cycle() {
1172 let mut graph: DiGraph<(), i32> = DiGraph::new();
1173 let n0 = graph.add_node(());
1174 let n1 = graph.add_node(());
1175 graph.add_edge(n0, n1, 1);
1176 graph.add_edge(n1, n0, 1);
1177
1178 layers(&graph, vec![0.into()]).for_each(|layer| match layer {
1179 Err(e) => panic!("{}", e.0),
1180 Ok(layer) => drop(layer),
1181 });
1182 }
1183}
1184
1185#[cfg(test)]
1187mod test_collect_bicolor_runs {
1188
1189 use super::*;
1190 use petgraph::graph::{DiGraph, EdgeIndex, NodeIndex};
1191 use std::error::Error;
1192
1193 #[test]
1194 fn test_cycle() {
1195 let mut graph = DiGraph::new();
1196 let n0 = graph.add_node(0);
1197 let n1 = graph.add_node(0);
1198 let n2 = graph.add_node(0);
1199 graph.add_edge(n0, n1, 1);
1200 graph.add_edge(n1, n2, 1);
1201 graph.add_edge(n2, n0, 1);
1202
1203 let test_filter_fn =
1204 |_node_id: NodeIndex| -> Result<Option<bool>, Box<dyn Error>> { Ok(Some(true)) };
1205 let test_color_fn =
1206 |_edge_id: EdgeIndex| -> Result<Option<usize>, Box<dyn Error>> { Ok(Some(1)) };
1207 let result = match collect_bicolor_runs(&graph, test_filter_fn, test_color_fn) {
1208 Ok(Some(_value)) => "Not None",
1209 Ok(None) => "None",
1210 Err(_) => "Error",
1211 };
1212 assert_eq!(result, "None")
1213 }
1214
1215 #[test]
1216 fn test_filter_function_inner_exception() {
1217 let mut graph = DiGraph::new();
1218 graph.add_node(0);
1219
1220 let fail_function = |node_id: NodeIndex| -> Result<Option<bool>, Box<dyn Error>> {
1221 let node_weight: &i32 = graph.node_weight(node_id).expect("Invalid NodeId");
1222 if *node_weight > 0 {
1223 Ok(Some(true))
1224 } else {
1225 Err(Box::from("Failed!"))
1226 }
1227 };
1228 let test_color_fn = |edge_id: EdgeIndex| -> Result<Option<usize>, Box<dyn Error>> {
1229 let edge_weight: &i32 = graph.edge_weight(edge_id).expect("Invalid Edge");
1230 Ok(Some(*edge_weight as usize))
1231 };
1232 let result = match collect_bicolor_runs(&graph, fail_function, test_color_fn) {
1233 Ok(Some(_value)) => "Not None",
1234 Ok(None) => "None",
1235 Err(_) => "Error",
1236 };
1237 assert_eq!(result, "Error")
1238 }
1239
1240 #[test]
1241 fn test_empty() {
1242 let graph = DiGraph::new();
1243 let test_filter_fn = |node_id: NodeIndex| -> Result<Option<bool>, Box<dyn Error>> {
1244 let node_weight: &i32 = graph.node_weight(node_id).expect("Invalid NodeId");
1245 Ok(Some(*node_weight > 1))
1246 };
1247 let test_color_fn = |edge_id: EdgeIndex| -> Result<Option<usize>, Box<dyn Error>> {
1248 let edge_weight: &i32 = graph.edge_weight(edge_id).expect("Invalid Edge");
1249 Ok(Some(*edge_weight as usize))
1250 };
1251 let result = collect_bicolor_runs(&graph, test_filter_fn, test_color_fn).unwrap();
1252 let expected: Vec<Vec<NodeIndex>> = vec![];
1253 assert_eq!(result, Some(expected))
1254 }
1255
1256 #[test]
1257 fn test_two_colors() {
1258 let mut graph = DiGraph::new();
1288 let n0 = graph.add_node(0); let n1 = graph.add_node(0); let n2 = graph.add_node(1); let n3 = graph.add_node(1); let n4 = graph.add_node(0); let n5 = graph.add_node(0); graph.add_edge(n0, n2, 0); graph.add_edge(n1, n2, 1); graph.add_edge(n2, n3, 0); graph.add_edge(n2, n3, 1); graph.add_edge(n3, n4, 0); graph.add_edge(n3, n5, 1); let test_filter_fn = |node_id: NodeIndex| -> Result<Option<bool>, Box<dyn Error>> {
1303 let node_weight: &i32 = graph.node_weight(node_id).expect("Invalid NodeId");
1304 Ok(Some(*node_weight > 0))
1305 };
1306 let test_color_fn = |edge_id: EdgeIndex| -> Result<Option<usize>, Box<dyn Error>> {
1308 let edge_weight: &i32 = graph.edge_weight(edge_id).expect("Invalid Edge");
1309 Ok(Some(*edge_weight as usize))
1310 };
1311 let result = collect_bicolor_runs(&graph, test_filter_fn, test_color_fn).unwrap();
1312 let expected: Vec<Vec<NodeIndex>> = vec![vec![n2, n3]]; assert_eq!(result, Some(expected))
1314 }
1315
1316 #[test]
1317 fn test_two_colors_with_pending() {
1318 let mut graph = DiGraph::new();
1368 let n0 = graph.add_node(0); let n1 = graph.add_node(0); let n2 = graph.add_node(1); let n3 = graph.add_node(1); let n4 = graph.add_node(1); let n5 = graph.add_node(1); let n6 = graph.add_node(0); let n7 = graph.add_node(0); graph.add_edge(n0, n2, 0); graph.add_edge(n2, n3, 0); graph.add_edge(n1, n3, 1); graph.add_edge(n3, n4, 0); graph.add_edge(n3, n4, 1); graph.add_edge(n4, n6, 0); graph.add_edge(n4, n5, 1); graph.add_edge(n5, n7, 1); let test_filter_fn = |node_id: NodeIndex| -> Result<Option<bool>, Box<dyn Error>> {
1387 let node_weight: &i32 = graph.node_weight(node_id).expect("Invalid NodeId");
1388 Ok(Some(*node_weight > 0))
1389 };
1390 let test_color_fn = |edge_id: EdgeIndex| -> Result<Option<usize>, Box<dyn Error>> {
1392 let edge_weight: &i32 = graph.edge_weight(edge_id).expect("Invalid Edge");
1393 Ok(Some(*edge_weight as usize))
1394 };
1395 let result = collect_bicolor_runs(&graph, test_filter_fn, test_color_fn).unwrap();
1396 let expected: Vec<Vec<NodeIndex>> = vec![vec![n2, n3, n4, n5]]; assert_eq!(result, Some(expected))
1398 }
1399}
1400
1401#[cfg(test)]
1402mod test_collect_runs {
1403 use super::collect_runs;
1404 use petgraph::{graph::DiGraph, visit::GraphBase};
1405
1406 type BareDiGraph = DiGraph<(), ()>;
1407 type RunResult = Result<Vec<<BareDiGraph as GraphBase>::NodeId>, ()>;
1408
1409 #[test]
1410 fn test_empty_graph() {
1411 let graph: BareDiGraph = DiGraph::new();
1412
1413 let mut runs = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(true) }).expect("Some");
1414
1415 let run = runs.next();
1416 assert!(run == None);
1417
1418 let runs = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(true) }).expect("Some");
1419
1420 let runs: Vec<RunResult> = runs.collect();
1421
1422 assert_eq!(runs, Vec::<RunResult>::new());
1423 }
1424
1425 #[test]
1426 fn test_simple_run_w_filter() {
1427 let mut graph: BareDiGraph = DiGraph::new();
1428 let n1 = graph.add_node(());
1429 let n2 = graph.add_node(());
1430 let n3 = graph.add_node(());
1431 graph.add_edge(n1, n2, ());
1432 graph.add_edge(n2, n3, ());
1433
1434 let mut runs = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(true) }).expect("Some");
1435
1436 let the_run = runs.next().expect("Some").expect("3 nodes");
1437 assert_eq!(the_run.len(), 3);
1438 assert_eq!(runs.next(), None);
1439
1440 assert_eq!(the_run, vec![n1, n2, n3]);
1441
1442 let mut runs = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(false) }).expect("Some");
1444
1445 assert_eq!(runs.next(), None);
1446
1447 let mut runs = collect_runs(&graph, |n| -> Result<bool, ()> { Ok(n != n2) }).expect("Some");
1448
1449 assert_eq!(runs.next(), Some(Ok(vec![n1])));
1450 assert_eq!(runs.next(), Some(Ok(vec![n3])));
1451 }
1452
1453 #[test]
1454 fn test_multiple_runs_w_filter() {
1455 let mut graph: BareDiGraph = DiGraph::new();
1456 let n1 = graph.add_node(());
1457 let n2 = graph.add_node(());
1458 let n3 = graph.add_node(());
1459 let n4 = graph.add_node(());
1460 let n5 = graph.add_node(());
1461 let n6 = graph.add_node(());
1462 let n7 = graph.add_node(());
1463
1464 graph.add_edge(n1, n2, ());
1465 graph.add_edge(n2, n3, ());
1466 graph.add_edge(n3, n7, ());
1467 graph.add_edge(n4, n3, ());
1468 graph.add_edge(n4, n7, ());
1469 graph.add_edge(n5, n4, ());
1470 graph.add_edge(n6, n5, ());
1471
1472 let runs: Vec<RunResult> = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(true) })
1473 .expect("Some")
1474 .collect();
1475
1476 assert_eq!(runs, vec![Ok(vec![n6, n5, n4]), Ok(vec![n1, n2, n3, n7])]);
1477
1478 let runs: Vec<RunResult> =
1480 collect_runs(&graph, |n| -> Result<bool, ()> { Ok(n != n4 && n != n2) })
1481 .expect("Some")
1482 .collect();
1483
1484 assert_eq!(runs, vec![Ok(vec![n6, n5]), Ok(vec![n1]), Ok(vec![n3, n7])]);
1485 }
1486
1487 #[test]
1488 fn test_singleton_runs_w_filter() {
1489 let mut graph: BareDiGraph = DiGraph::new();
1490 let n1 = graph.add_node(());
1491 let n2 = graph.add_node(());
1492 let n3 = graph.add_node(());
1493
1494 graph.add_edge(n1, n2, ());
1495 graph.add_edge(n1, n3, ());
1496
1497 let mut runs = collect_runs(&graph, |_| -> Result<bool, ()> { Ok(true) }).expect("Some");
1498
1499 assert_eq!(runs.next().expect("n1"), Ok(vec![n1]));
1500 assert_eq!(runs.next().expect("n3"), Ok(vec![n3]));
1501 assert_eq!(runs.next().expect("n2"), Ok(vec![n2]));
1502
1503 let runs: Vec<RunResult> = collect_runs(&graph, |n| -> Result<bool, ()> { Ok(n != n1) })
1505 .expect("Some")
1506 .collect();
1507
1508 assert_eq!(runs, vec![Ok(vec![n3]), Ok(vec![n2])]);
1509 }
1510
1511 #[test]
1512 fn test_error_propagation() {
1513 let mut graph: BareDiGraph = DiGraph::new();
1514 graph.add_node(());
1515
1516 let mut runs = collect_runs(&graph, |_| -> Result<bool, ()> { Err(()) }).expect("Some");
1517
1518 assert!(runs.next().expect("Some").is_err());
1519 assert_eq!(runs.next(), None);
1520 }
1521}