1use alloc::collections::{BTreeMap, BTreeSet};
4use core::{
5 cell::RefCell,
6 cmp::Ordering,
7 convert::TryFrom,
8 ops::{Deref, RangeBounds},
9};
10
11use crate::{
12 adj::IndexType,
13 algo::Cycle,
14 data::{Build, Create, DataMap, DataMapMut},
15 graph::NodeIndex,
16 prelude::DiGraph,
17 visit::{
18 dfs_visitor, Control, Data, DfsEvent, EdgeCount, EdgeIndexable, GetAdjacencyMatrix,
19 GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNeighbors,
20 IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable,
21 NodeCount, NodeIndexable, Reversed, Time, Visitable,
22 },
23 Direction,
24};
25
26#[cfg(feature = "stable_graph")]
27use crate::stable_graph::StableDiGraph;
28
29mod order_map;
30use fixedbitset::FixedBitSet;
31use order_map::OrderMap;
32pub use order_map::TopologicalPosition;
33
34#[derive(Clone, Debug)]
68pub struct Acyclic<G: Visitable> {
69 graph: G,
71 order_map: OrderMap<G::NodeId>,
73
74 discovered: RefCell<FixedBitSet>,
78 finished: RefCell<FixedBitSet>,
80}
81
82#[derive(Clone, Debug, PartialEq)]
84pub enum AcyclicEdgeError<N> {
85 Cycle(Cycle<N>),
87 SelfLoop,
89 InvalidEdge,
91}
92
93impl<N> From<Cycle<N>> for AcyclicEdgeError<N> {
94 fn from(cycle: Cycle<N>) -> Self {
95 AcyclicEdgeError::Cycle(cycle)
96 }
97}
98
99impl<G: Visitable> Acyclic<G> {
100 pub fn new() -> Self
102 where
103 G: Default,
104 {
105 Default::default()
106 }
107
108 pub fn nodes_iter(&self) -> impl Iterator<Item = G::NodeId> + '_ {
110 self.order_map.nodes_iter()
111 }
112
113 pub fn range<'r>(
117 &'r self,
118 range: impl RangeBounds<TopologicalPosition> + 'r,
119 ) -> impl Iterator<Item = G::NodeId> + 'r {
120 self.order_map.range(range)
121 }
122
123 pub fn inner(&self) -> &G {
125 &self.graph
126 }
127
128 fn inner_mut(&mut self) -> &mut G {
132 &mut self.graph
133 }
134
135 pub fn into_inner(self) -> G {
137 self.graph
138 }
139}
140
141impl<G: Visitable + NodeIndexable> Acyclic<G>
142where
143 for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + GraphBase<NodeId = G::NodeId>,
144{
145 pub fn try_from_graph(graph: G) -> Result<Self, Cycle<G::NodeId>> {
151 let order_map = OrderMap::try_from_graph(&graph)?;
152 let discovered = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
153 let finished = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
154 Ok(Self {
155 graph,
156 order_map,
157 discovered,
158 finished,
159 })
160 }
161
162 #[track_caller]
179 pub fn try_add_edge(
180 &mut self,
181 a: G::NodeId,
182 b: G::NodeId,
183 weight: G::EdgeWeight,
184 ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
185 where
186 G: Build,
187 G::NodeId: IndexType,
188 {
189 if a == b {
190 return Err(AcyclicEdgeError::SelfLoop);
192 }
193 self.update_ordering(a, b)?;
194 self.graph
195 .add_edge(a, b, weight)
196 .ok_or(AcyclicEdgeError::InvalidEdge)
197 }
198
199 pub fn try_update_edge(
210 &mut self,
211 a: G::NodeId,
212 b: G::NodeId,
213 weight: G::EdgeWeight,
214 ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
215 where
216 G: Build,
217 G::NodeId: IndexType,
218 {
219 if a == b {
220 return Err(AcyclicEdgeError::SelfLoop);
222 }
223 self.update_ordering(a, b)?;
224 Ok(self.graph.update_edge(a, b, weight))
225 }
226
227 pub fn is_valid_edge(&self, a: G::NodeId, b: G::NodeId) -> bool
231 where
232 G::NodeId: IndexType,
233 {
234 if a == b {
235 false } else if self.get_position(a) < self.get_position(b) {
237 true } else {
239 self.causal_cones(b, a).is_ok()
242 }
243 }
244
245 #[track_caller]
252 fn update_ordering(&mut self, a: G::NodeId, b: G::NodeId) -> Result<(), Cycle<G::NodeId>>
253 where
254 G::NodeId: IndexType,
255 {
256 let min_order = self.get_position(b);
257 let max_order = self.get_position(a);
258 if min_order >= max_order {
259 return Ok(());
261 }
262
263 let (b_fut, a_past) = self.causal_cones(b, a)?;
266
267 let all_positions: BTreeSet<_> = b_fut.keys().chain(a_past.keys()).copied().collect();
271 let all_nodes = a_past.values().chain(b_fut.values()).copied();
272
273 debug_assert_eq!(all_positions.len(), b_fut.len() + a_past.len());
274
275 for (pos, node) in all_positions.into_iter().zip(all_nodes) {
276 self.order_map.set_position(node, pos, &self.graph);
277 }
278 Ok(())
279 }
280
281 #[allow(clippy::type_complexity)]
290 fn causal_cones(
291 &self,
292 min_node: G::NodeId,
293 max_node: G::NodeId,
294 ) -> Result<
295 (
296 BTreeMap<TopologicalPosition, G::NodeId>,
297 BTreeMap<TopologicalPosition, G::NodeId>,
298 ),
299 Cycle<G::NodeId>,
300 >
301 where
302 G::NodeId: IndexType,
303 {
304 debug_assert!(self.discovered.borrow().is_clear());
305 debug_assert!(self.finished.borrow().is_clear());
306
307 let min_order = self.get_position(min_node);
308 let max_order = self.get_position(max_node);
309
310 if self.discovered.borrow().len() < self.graph.node_bound() {
312 self.discovered.borrow_mut().grow(self.graph.node_bound());
313 self.finished.borrow_mut().grow(self.graph.node_bound());
314 }
315
316 let mut forward_cone = BTreeMap::new();
318 let mut backward_cone = BTreeMap::new();
319
320 let mut run_dfs = || {
323 self.future_cone(min_node, min_order, max_order, &mut forward_cone)?;
325
326 self.past_cone(max_node, min_order, max_order, &mut backward_cone)
330 .expect("cycles already checked in future_cone");
331
332 Ok(())
333 };
334
335 let success = run_dfs();
336
337 for &v in forward_cone.values().chain(backward_cone.values()) {
340 self.discovered.borrow_mut().set(v.index(), false);
341 self.finished.borrow_mut().set(v.index(), false);
342 }
343 debug_assert!(self.discovered.borrow().is_clear());
344 debug_assert!(self.finished.borrow().is_clear());
345
346 match success {
347 Ok(()) => Ok((forward_cone, backward_cone)),
348 Err(cycle) => Err(cycle),
349 }
350 }
351
352 fn future_cone(
353 &self,
354 start: G::NodeId,
355 min_position: TopologicalPosition,
356 max_position: TopologicalPosition,
357 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
358 ) -> Result<(), Cycle<G::NodeId>>
359 where
360 G::NodeId: IndexType,
361 {
362 dfs(
363 &self.graph,
364 start,
365 &self.order_map,
366 |order| {
367 debug_assert!(order >= min_position, "invalid topological order");
368 match order.cmp(&max_position) {
369 Ordering::Less => Ok(true), Ordering::Equal => Err(Cycle(start)), Ordering::Greater => Ok(false), }
373 },
374 res,
375 &mut self.discovered.borrow_mut(),
376 &mut self.finished.borrow_mut(),
377 )
378 }
379
380 fn past_cone(
381 &self,
382 start: G::NodeId,
383 min_position: TopologicalPosition,
384 max_position: TopologicalPosition,
385 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
386 ) -> Result<(), Cycle<G::NodeId>>
387 where
388 G::NodeId: IndexType,
389 {
390 dfs(
391 Reversed(&self.graph),
392 start,
393 &self.order_map,
394 |order| {
395 debug_assert!(order <= max_position, "invalid topological order");
396 match order.cmp(&min_position) {
397 Ordering::Less => Ok(false), Ordering::Equal => unreachable!("checked by future_cone"), Ordering::Greater => Ok(true), }
401 },
402 res,
403 &mut self.discovered.borrow_mut(),
404 &mut self.finished.borrow_mut(),
405 )
406 }
407}
408
409impl<G: Visitable> GraphBase for Acyclic<G> {
410 type NodeId = G::NodeId;
411 type EdgeId = G::EdgeId;
412}
413
414impl<G: Default + Visitable> Default for Acyclic<G> {
415 fn default() -> Self {
416 let graph: G = Default::default();
417 let order_map = Default::default();
418 let discovered = RefCell::new(FixedBitSet::default());
419 let finished = RefCell::new(FixedBitSet::default());
420 Self {
421 graph,
422 order_map,
423 discovered,
424 finished,
425 }
426 }
427}
428
429impl<G: Build + Visitable + NodeIndexable> Build for Acyclic<G>
430where
431 for<'a> &'a G: IntoNeighborsDirected
432 + IntoNodeIdentifiers
433 + Visitable<Map = G::Map>
434 + GraphBase<NodeId = G::NodeId>,
435 G::NodeId: IndexType,
436{
437 fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
438 let n = self.graph.add_node(weight);
439 self.order_map.add_node(n, &self.graph);
440 n
441 }
442
443 fn add_edge(
444 &mut self,
445 a: Self::NodeId,
446 b: Self::NodeId,
447 weight: Self::EdgeWeight,
448 ) -> Option<Self::EdgeId> {
449 self.try_add_edge(a, b, weight).ok()
450 }
451
452 fn update_edge(
453 &mut self,
454 a: Self::NodeId,
455 b: Self::NodeId,
456 weight: Self::EdgeWeight,
457 ) -> Self::EdgeId {
458 self.try_update_edge(a, b, weight).unwrap()
459 }
460}
461
462impl<G: Create + Visitable + NodeIndexable> Create for Acyclic<G>
463where
464 for<'a> &'a G: IntoNeighborsDirected
465 + IntoNodeIdentifiers
466 + Visitable<Map = G::Map>
467 + GraphBase<NodeId = G::NodeId>,
468 G::NodeId: IndexType,
469{
470 fn with_capacity(nodes: usize, edges: usize) -> Self {
471 let graph = G::with_capacity(nodes, edges);
472 let order_map = OrderMap::with_capacity(nodes);
473 let discovered = FixedBitSet::with_capacity(nodes);
474 let finished = FixedBitSet::with_capacity(nodes);
475 Self {
476 graph,
477 order_map,
478 discovered: RefCell::new(discovered),
479 finished: RefCell::new(finished),
480 }
481 }
482}
483
484impl<G: Visitable> Deref for Acyclic<G> {
485 type Target = G;
486
487 fn deref(&self) -> &Self::Target {
488 &self.graph
489 }
490}
491
492fn dfs<G: NodeIndexable + IntoNeighborsDirected + IntoNodeIdentifiers + Visitable>(
495 graph: G,
496 start: G::NodeId,
497 order_map: &OrderMap<G::NodeId>,
498 mut valid_order: impl FnMut(TopologicalPosition) -> Result<bool, Cycle<G::NodeId>>,
501 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
502 discovered: &mut FixedBitSet,
503 finished: &mut FixedBitSet,
504) -> Result<(), Cycle<G::NodeId>>
505where
506 G::NodeId: IndexType,
507{
508 dfs_visitor(
509 graph,
510 start,
511 &mut |ev| -> Result<Control<()>, Cycle<G::NodeId>> {
512 match ev {
513 DfsEvent::Discover(u, _) => {
514 let order = order_map.get_position(u, &graph);
516 res.insert(order, u);
517 Ok(Control::Continue)
518 }
519 DfsEvent::TreeEdge(_, u) => {
520 let order = order_map.get_position(u, &graph);
522 match valid_order(order) {
523 Ok(true) => Ok(Control::Continue),
524 Ok(false) => Ok(Control::Prune),
525 Err(cycle) => Err(cycle),
526 }
527 }
528 _ => Ok(Control::Continue),
529 }
530 },
531 discovered,
532 finished,
533 &mut Time::default(),
534 )?;
535
536 Ok(())
537}
538
539impl<G: Visitable + Data> Data for Acyclic<G> {
566 type NodeWeight = G::NodeWeight;
567 type EdgeWeight = G::EdgeWeight;
568}
569
570impl<G: Visitable + DataMap> DataMap for Acyclic<G> {
571 fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
572 self.inner().node_weight(id)
573 }
574
575 fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
576 self.inner().edge_weight(id)
577 }
578}
579
580impl<G: Visitable + DataMapMut> DataMapMut for Acyclic<G> {
581 fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
582 self.inner_mut().node_weight_mut(id)
583 }
584
585 fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
586 self.inner_mut().edge_weight_mut(id)
587 }
588}
589
590impl<G: Visitable + EdgeCount> EdgeCount for Acyclic<G> {
591 fn edge_count(&self) -> usize {
592 self.inner().edge_count()
593 }
594}
595
596impl<G: Visitable + EdgeIndexable> EdgeIndexable for Acyclic<G> {
597 fn edge_bound(&self) -> usize {
598 self.inner().edge_bound()
599 }
600
601 fn to_index(&self, a: Self::EdgeId) -> usize {
602 self.inner().to_index(a)
603 }
604
605 fn from_index(&self, i: usize) -> Self::EdgeId {
606 self.inner().from_index(i)
607 }
608}
609
610impl<G: Visitable + GetAdjacencyMatrix> GetAdjacencyMatrix for Acyclic<G> {
611 type AdjMatrix = G::AdjMatrix;
612
613 fn adjacency_matrix(&self) -> Self::AdjMatrix {
614 self.inner().adjacency_matrix()
615 }
616
617 fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool {
618 self.inner().is_adjacent(matrix, a, b)
619 }
620}
621
622impl<G: Visitable + GraphProp> GraphProp for Acyclic<G> {
623 type EdgeType = G::EdgeType;
624}
625
626impl<G: Visitable + NodeCompactIndexable> NodeCompactIndexable for Acyclic<G> {}
627
628impl<G: Visitable + NodeCount> NodeCount for Acyclic<G> {
629 fn node_count(&self) -> usize {
630 self.inner().node_count()
631 }
632}
633
634impl<G: Visitable + NodeIndexable> NodeIndexable for Acyclic<G> {
635 fn node_bound(&self) -> usize {
636 self.inner().node_bound()
637 }
638
639 fn to_index(&self, a: Self::NodeId) -> usize {
640 self.inner().to_index(a)
641 }
642
643 fn from_index(&self, i: usize) -> Self::NodeId {
644 self.inner().from_index(i)
645 }
646}
647
648impl<G: Visitable> Visitable for Acyclic<G> {
649 type Map = G::Map;
650
651 fn visit_map(&self) -> Self::Map {
652 self.inner().visit_map()
653 }
654
655 fn reset_map(&self, map: &mut Self::Map) {
656 self.inner().reset_map(map)
657 }
658}
659
660macro_rules! impl_graph_traits {
661 ($graph_type:ident) => {
662 impl<N, E, Ix: IndexType> Acyclic<$graph_type<N, E, Ix>> {
664 pub fn remove_edge(
668 &mut self,
669 e: <$graph_type<N, E, Ix> as GraphBase>::EdgeId,
670 ) -> Option<E> {
671 self.graph.remove_edge(e)
672 }
673
674 pub fn remove_node(
680 &mut self,
681 n: <$graph_type<N, E, Ix> as GraphBase>::NodeId,
682 ) -> Option<N> {
683 self.order_map.remove_node(n, &self.graph);
684 self.graph.remove_node(n)
685 }
686 }
687
688 impl<N, E, Ix: IndexType> TryFrom<$graph_type<N, E, Ix>>
689 for Acyclic<$graph_type<N, E, Ix>>
690 {
691 type Error = Cycle<NodeIndex<Ix>>;
692
693 fn try_from(graph: $graph_type<N, E, Ix>) -> Result<Self, Self::Error> {
694 let order_map = OrderMap::try_from_graph(&graph)?;
695 let discovered = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
696 let finished = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
697 Ok(Self {
698 graph,
699 order_map,
700 discovered,
701 finished,
702 })
703 }
704 }
705
706 impl<'a, N, E, Ix: IndexType> IntoEdgeReferences for &'a Acyclic<$graph_type<N, E, Ix>> {
707 type EdgeRef = <&'a $graph_type<N, E, Ix> as IntoEdgeReferences>::EdgeRef;
708 type EdgeReferences = <&'a $graph_type<N, E, Ix> as IntoEdgeReferences>::EdgeReferences;
709
710 fn edge_references(self) -> Self::EdgeReferences {
711 self.inner().edge_references()
712 }
713 }
714
715 impl<'a, N, E, Ix: IndexType> IntoEdges for &'a Acyclic<$graph_type<N, E, Ix>> {
716 type Edges = <&'a $graph_type<N, E, Ix> as IntoEdges>::Edges;
717
718 fn edges(self, a: Self::NodeId) -> Self::Edges {
719 self.inner().edges(a)
720 }
721 }
722
723 impl<'a, N, E, Ix: IndexType> IntoEdgesDirected for &'a Acyclic<$graph_type<N, E, Ix>> {
724 type EdgesDirected = <&'a $graph_type<N, E, Ix> as IntoEdgesDirected>::EdgesDirected;
725
726 fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected {
727 self.inner().edges_directed(a, dir)
728 }
729 }
730
731 impl<'a, N, E, Ix: IndexType> IntoNeighbors for &'a Acyclic<$graph_type<N, E, Ix>> {
732 type Neighbors = <&'a $graph_type<N, E, Ix> as IntoNeighbors>::Neighbors;
733
734 fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
735 self.inner().neighbors(a)
736 }
737 }
738
739 impl<'a, N, E, Ix: IndexType> IntoNeighborsDirected for &'a Acyclic<$graph_type<N, E, Ix>> {
740 type NeighborsDirected =
741 <&'a $graph_type<N, E, Ix> as IntoNeighborsDirected>::NeighborsDirected;
742
743 fn neighbors_directed(self, n: Self::NodeId, d: Direction) -> Self::NeighborsDirected {
744 self.inner().neighbors_directed(n, d)
745 }
746 }
747
748 impl<'a, N, E, Ix: IndexType> IntoNodeIdentifiers for &'a Acyclic<$graph_type<N, E, Ix>> {
749 type NodeIdentifiers =
750 <&'a $graph_type<N, E, Ix> as IntoNodeIdentifiers>::NodeIdentifiers;
751
752 fn node_identifiers(self) -> Self::NodeIdentifiers {
753 self.inner().node_identifiers()
754 }
755 }
756
757 impl<'a, N, E, Ix: IndexType> IntoNodeReferences for &'a Acyclic<$graph_type<N, E, Ix>> {
758 type NodeRef = <&'a $graph_type<N, E, Ix> as IntoNodeReferences>::NodeRef;
759 type NodeReferences = <&'a $graph_type<N, E, Ix> as IntoNodeReferences>::NodeReferences;
760
761 fn node_references(self) -> Self::NodeReferences {
762 self.inner().node_references()
763 }
764 }
765 };
766}
767
768impl_graph_traits!(DiGraph);
769#[cfg(feature = "stable_graph")]
770impl_graph_traits!(StableDiGraph);
771
772#[cfg(test)]
773mod tests {
774 use alloc::vec::Vec;
775
776 use super::*;
777 use crate::prelude::DiGraph;
778 use crate::visit::IntoNodeReferences;
779
780 #[cfg(feature = "stable_graph")]
781 use crate::prelude::StableDiGraph;
782
783 #[test]
784 fn test_acyclic_graph() {
785 let mut graph = DiGraph::<(), ()>::new();
787 let a = graph.add_node(());
788 let c = graph.add_node(());
789 let b = graph.add_node(());
790 graph.add_edge(a, b, ());
791 graph.add_edge(b, c, ());
792
793 let mut acyclic = Acyclic::try_from_graph(graph).unwrap();
795
796 assert_valid_topological_order(&acyclic);
798
799 assert!(acyclic.try_add_edge(a, c, ()).is_ok());
801 assert_valid_topological_order(&acyclic);
802
803 assert!(acyclic.try_add_edge(c, a, ()).is_err());
805
806 let d = acyclic.add_node(());
808 assert!(acyclic.try_add_edge(c, d, ()).is_ok());
809 assert_valid_topological_order(&acyclic);
810
811 assert!(acyclic.add_edge(d, a, ()).is_none());
813 }
814
815 #[cfg(feature = "stable_graph")]
816 #[test]
817 fn test_acyclic_graph_add_remove() {
818 let mut acyclic = Acyclic::<StableDiGraph<(), ()>>::new();
820 let a = acyclic.add_node(());
821 let b = acyclic.add_node(());
822 assert!(acyclic.try_add_edge(a, b, ()).is_ok());
823
824 assert_valid_topological_order(&acyclic);
826
827 let c = acyclic.add_node(());
829 assert!(acyclic.try_add_edge(b, c, ()).is_ok());
830
831 assert_valid_topological_order(&acyclic);
833
834 acyclic.remove_node(b);
836
837 assert_valid_topological_order(&acyclic);
839
840 let remaining_nodes: Vec<_> = acyclic
842 .inner()
843 .node_references()
844 .map(|(id, _)| id)
845 .collect();
846 assert_eq!(remaining_nodes.len(), 2);
847 assert!(remaining_nodes.contains(&a));
848 assert!(remaining_nodes.contains(&c));
849 assert!(!acyclic.inner().contains_edge(a, c));
850 }
851
852 fn assert_valid_topological_order<'a, G>(acyclic: &'a Acyclic<G>)
853 where
854 G: Visitable + NodeCount + NodeIndexable,
855 &'a G: NodeIndexable
856 + IntoNodeReferences
857 + IntoNeighborsDirected
858 + GraphBase<NodeId = G::NodeId>,
859 G::NodeId: core::fmt::Debug,
860 {
861 let ordered_nodes: Vec<_> = acyclic.nodes_iter().collect();
862 assert_eq!(ordered_nodes.len(), acyclic.node_count());
863 let nodes: Vec<_> = acyclic.inner().node_identifiers().collect();
864
865 let mut last_position = None;
867 for (idx, &node) in ordered_nodes.iter().enumerate() {
868 assert!(nodes.contains(&node));
869
870 let pos = acyclic.get_position(node);
872 assert!(Some(pos) > last_position);
873 last_position = Some(pos);
874
875 for neighbor in acyclic.inner().neighbors(node) {
877 let neighbour_idx = ordered_nodes.iter().position(|&n| n == neighbor).unwrap();
878 assert!(neighbour_idx > idx);
879 }
880 }
881 }
882
883 #[cfg(feature = "graphmap")]
884 #[test]
885 fn test_multiedge_allowed() {
886 use crate::prelude::GraphMap;
887 use crate::Directed;
888
889 let mut graph = Acyclic::<GraphMap<usize, (), Directed>>::new();
890 graph.add_node(0);
891 graph.add_node(1);
892 graph.try_update_edge(0, 1, ()).unwrap();
893 graph.try_update_edge(0, 1, ()).unwrap(); }
895}