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]
175 pub fn try_add_edge(
176 &mut self,
177 a: G::NodeId,
178 b: G::NodeId,
179 weight: G::EdgeWeight,
180 ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
181 where
182 G: Build,
183 G::NodeId: IndexType,
184 {
185 if a == b {
186 return Err(AcyclicEdgeError::SelfLoop);
188 }
189 self.update_ordering(a, b)?;
190 self.graph
191 .add_edge(a, b, weight)
192 .ok_or(AcyclicEdgeError::InvalidEdge)
193 }
194
195 pub fn try_update_edge(
206 &mut self,
207 a: G::NodeId,
208 b: G::NodeId,
209 weight: G::EdgeWeight,
210 ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
211 where
212 G: Build,
213 G::NodeId: IndexType,
214 {
215 if a == b {
216 return Err(AcyclicEdgeError::SelfLoop);
218 }
219 self.update_ordering(a, b)?;
220 Ok(self.graph.update_edge(a, b, weight))
221 }
222
223 pub fn is_valid_edge(&self, a: G::NodeId, b: G::NodeId) -> bool
227 where
228 G::NodeId: IndexType,
229 {
230 if a == b {
231 false } else if self.get_position(a) < self.get_position(b) {
233 true } else {
235 self.causal_cones(b, a).is_ok()
238 }
239 }
240
241 #[track_caller]
248 fn update_ordering(&mut self, a: G::NodeId, b: G::NodeId) -> Result<(), Cycle<G::NodeId>>
249 where
250 G::NodeId: IndexType,
251 {
252 let min_order = self.get_position(b);
253 let max_order = self.get_position(a);
254 if min_order >= max_order {
255 return Ok(());
257 }
258
259 let (b_fut, a_past) = self.causal_cones(b, a)?;
262
263 let all_positions: BTreeSet<_> = b_fut.keys().chain(a_past.keys()).copied().collect();
267 let all_nodes = a_past.values().chain(b_fut.values()).copied();
268
269 debug_assert_eq!(all_positions.len(), b_fut.len() + a_past.len());
270
271 for (pos, node) in all_positions.into_iter().zip(all_nodes) {
272 self.order_map.set_position(node, pos, &self.graph);
273 }
274 Ok(())
275 }
276
277 #[allow(clippy::type_complexity)]
286 fn causal_cones(
287 &self,
288 min_node: G::NodeId,
289 max_node: G::NodeId,
290 ) -> Result<
291 (
292 BTreeMap<TopologicalPosition, G::NodeId>,
293 BTreeMap<TopologicalPosition, G::NodeId>,
294 ),
295 Cycle<G::NodeId>,
296 >
297 where
298 G::NodeId: IndexType,
299 {
300 debug_assert!(self.discovered.borrow().is_clear());
301 debug_assert!(self.finished.borrow().is_clear());
302
303 let min_order = self.get_position(min_node);
304 let max_order = self.get_position(max_node);
305
306 if self.discovered.borrow().len() < self.graph.node_bound() {
308 self.discovered.borrow_mut().grow(self.graph.node_bound());
309 self.finished.borrow_mut().grow(self.graph.node_bound());
310 }
311
312 let mut forward_cone = BTreeMap::new();
314 let mut backward_cone = BTreeMap::new();
315
316 let mut run_dfs = || {
319 self.future_cone(min_node, min_order, max_order, &mut forward_cone)?;
321
322 self.past_cone(max_node, min_order, max_order, &mut backward_cone)
326 .expect("cycles already checked in future_cone");
327
328 Ok(())
329 };
330
331 let success = run_dfs();
332
333 for &v in forward_cone.values().chain(backward_cone.values()) {
336 self.discovered.borrow_mut().set(v.index(), false);
337 self.finished.borrow_mut().set(v.index(), false);
338 }
339 debug_assert!(self.discovered.borrow().is_clear());
340 debug_assert!(self.finished.borrow().is_clear());
341
342 match success {
343 Ok(()) => Ok((forward_cone, backward_cone)),
344 Err(cycle) => Err(cycle),
345 }
346 }
347
348 fn future_cone(
349 &self,
350 start: G::NodeId,
351 min_position: TopologicalPosition,
352 max_position: TopologicalPosition,
353 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
354 ) -> Result<(), Cycle<G::NodeId>>
355 where
356 G::NodeId: IndexType,
357 {
358 dfs(
359 &self.graph,
360 start,
361 &self.order_map,
362 |order| {
363 debug_assert!(order >= min_position, "invalid topological order");
364 match order.cmp(&max_position) {
365 Ordering::Less => Ok(true), Ordering::Equal => Err(Cycle(start)), Ordering::Greater => Ok(false), }
369 },
370 res,
371 &mut self.discovered.borrow_mut(),
372 &mut self.finished.borrow_mut(),
373 )
374 }
375
376 fn past_cone(
377 &self,
378 start: G::NodeId,
379 min_position: TopologicalPosition,
380 max_position: TopologicalPosition,
381 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
382 ) -> Result<(), Cycle<G::NodeId>>
383 where
384 G::NodeId: IndexType,
385 {
386 dfs(
387 Reversed(&self.graph),
388 start,
389 &self.order_map,
390 |order| {
391 debug_assert!(order <= max_position, "invalid topological order");
392 match order.cmp(&min_position) {
393 Ordering::Less => Ok(false), Ordering::Equal => unreachable!("checked by future_cone"), Ordering::Greater => Ok(true), }
397 },
398 res,
399 &mut self.discovered.borrow_mut(),
400 &mut self.finished.borrow_mut(),
401 )
402 }
403}
404
405impl<G: Visitable> GraphBase for Acyclic<G> {
406 type NodeId = G::NodeId;
407 type EdgeId = G::EdgeId;
408}
409
410impl<G: Default + Visitable> Default for Acyclic<G> {
411 fn default() -> Self {
412 let graph: G = Default::default();
413 let order_map = Default::default();
414 let discovered = RefCell::new(FixedBitSet::default());
415 let finished = RefCell::new(FixedBitSet::default());
416 Self {
417 graph,
418 order_map,
419 discovered,
420 finished,
421 }
422 }
423}
424
425impl<G: Build + Visitable + NodeIndexable> Build for Acyclic<G>
426where
427 for<'a> &'a G: IntoNeighborsDirected
428 + IntoNodeIdentifiers
429 + Visitable<Map = G::Map>
430 + GraphBase<NodeId = G::NodeId>,
431 G::NodeId: IndexType,
432{
433 fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
434 let n = self.graph.add_node(weight);
435 self.order_map.add_node(n, &self.graph);
436 n
437 }
438
439 fn add_edge(
440 &mut self,
441 a: Self::NodeId,
442 b: Self::NodeId,
443 weight: Self::EdgeWeight,
444 ) -> Option<Self::EdgeId> {
445 self.try_add_edge(a, b, weight).ok()
446 }
447
448 fn update_edge(
449 &mut self,
450 a: Self::NodeId,
451 b: Self::NodeId,
452 weight: Self::EdgeWeight,
453 ) -> Self::EdgeId {
454 self.try_update_edge(a, b, weight).unwrap()
455 }
456}
457
458impl<G: Create + Visitable + NodeIndexable> Create for Acyclic<G>
459where
460 for<'a> &'a G: IntoNeighborsDirected
461 + IntoNodeIdentifiers
462 + Visitable<Map = G::Map>
463 + GraphBase<NodeId = G::NodeId>,
464 G::NodeId: IndexType,
465{
466 fn with_capacity(nodes: usize, edges: usize) -> Self {
467 let graph = G::with_capacity(nodes, edges);
468 let order_map = OrderMap::with_capacity(nodes);
469 let discovered = FixedBitSet::with_capacity(nodes);
470 let finished = FixedBitSet::with_capacity(nodes);
471 Self {
472 graph,
473 order_map,
474 discovered: RefCell::new(discovered),
475 finished: RefCell::new(finished),
476 }
477 }
478}
479
480impl<G: Visitable> Deref for Acyclic<G> {
481 type Target = G;
482
483 fn deref(&self) -> &Self::Target {
484 &self.graph
485 }
486}
487
488fn dfs<G: NodeIndexable + IntoNeighborsDirected + IntoNodeIdentifiers + Visitable>(
491 graph: G,
492 start: G::NodeId,
493 order_map: &OrderMap<G::NodeId>,
494 mut valid_order: impl FnMut(TopologicalPosition) -> Result<bool, Cycle<G::NodeId>>,
497 res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
498 discovered: &mut FixedBitSet,
499 finished: &mut FixedBitSet,
500) -> Result<(), Cycle<G::NodeId>>
501where
502 G::NodeId: IndexType,
503{
504 dfs_visitor(
505 graph,
506 start,
507 &mut |ev| -> Result<Control<()>, Cycle<G::NodeId>> {
508 match ev {
509 DfsEvent::Discover(u, _) => {
510 let order = order_map.get_position(u, &graph);
512 res.insert(order, u);
513 Ok(Control::Continue)
514 }
515 DfsEvent::TreeEdge(_, u) => {
516 let order = order_map.get_position(u, &graph);
518 match valid_order(order) {
519 Ok(true) => Ok(Control::Continue),
520 Ok(false) => Ok(Control::Prune),
521 Err(cycle) => Err(cycle),
522 }
523 }
524 _ => Ok(Control::Continue),
525 }
526 },
527 discovered,
528 finished,
529 &mut Time::default(),
530 )?;
531
532 Ok(())
533}
534
535impl<G: Visitable + Data> Data for Acyclic<G> {
562 type NodeWeight = G::NodeWeight;
563 type EdgeWeight = G::EdgeWeight;
564}
565
566impl<G: Visitable + DataMap> DataMap for Acyclic<G> {
567 fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
568 self.inner().node_weight(id)
569 }
570
571 fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
572 self.inner().edge_weight(id)
573 }
574}
575
576impl<G: Visitable + DataMapMut> DataMapMut for Acyclic<G> {
577 fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
578 self.inner_mut().node_weight_mut(id)
579 }
580
581 fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
582 self.inner_mut().edge_weight_mut(id)
583 }
584}
585
586impl<G: Visitable + EdgeCount> EdgeCount for Acyclic<G> {
587 fn edge_count(&self) -> usize {
588 self.inner().edge_count()
589 }
590}
591
592impl<G: Visitable + EdgeIndexable> EdgeIndexable for Acyclic<G> {
593 fn edge_bound(&self) -> usize {
594 self.inner().edge_bound()
595 }
596
597 fn to_index(&self, a: Self::EdgeId) -> usize {
598 self.inner().to_index(a)
599 }
600
601 fn from_index(&self, i: usize) -> Self::EdgeId {
602 self.inner().from_index(i)
603 }
604}
605
606impl<G: Visitable + GetAdjacencyMatrix> GetAdjacencyMatrix for Acyclic<G> {
607 type AdjMatrix = G::AdjMatrix;
608
609 fn adjacency_matrix(&self) -> Self::AdjMatrix {
610 self.inner().adjacency_matrix()
611 }
612
613 fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool {
614 self.inner().is_adjacent(matrix, a, b)
615 }
616}
617
618impl<G: Visitable + GraphProp> GraphProp for Acyclic<G> {
619 type EdgeType = G::EdgeType;
620}
621
622impl<G: Visitable + NodeCompactIndexable> NodeCompactIndexable for Acyclic<G> {}
623
624impl<G: Visitable + NodeCount> NodeCount for Acyclic<G> {
625 fn node_count(&self) -> usize {
626 self.inner().node_count()
627 }
628}
629
630impl<G: Visitable + NodeIndexable> NodeIndexable for Acyclic<G> {
631 fn node_bound(&self) -> usize {
632 self.inner().node_bound()
633 }
634
635 fn to_index(&self, a: Self::NodeId) -> usize {
636 self.inner().to_index(a)
637 }
638
639 fn from_index(&self, i: usize) -> Self::NodeId {
640 self.inner().from_index(i)
641 }
642}
643
644impl<G: Visitable> Visitable for Acyclic<G> {
645 type Map = G::Map;
646
647 fn visit_map(&self) -> Self::Map {
648 self.inner().visit_map()
649 }
650
651 fn reset_map(&self, map: &mut Self::Map) {
652 self.inner().reset_map(map)
653 }
654}
655
656macro_rules! impl_graph_traits {
657 ($graph_type:ident) => {
658 impl<N, E, Ix: IndexType> Acyclic<$graph_type<N, E, Ix>> {
660 pub fn remove_edge(
664 &mut self,
665 e: <$graph_type<N, E, Ix> as GraphBase>::EdgeId,
666 ) -> Option<E> {
667 self.graph.remove_edge(e)
668 }
669
670 pub fn remove_node(
676 &mut self,
677 n: <$graph_type<N, E, Ix> as GraphBase>::NodeId,
678 ) -> Option<N> {
679 self.order_map.remove_node(n, &self.graph);
680 self.graph.remove_node(n)
681 }
682 }
683
684 impl<N, E, Ix: IndexType> TryFrom<$graph_type<N, E, Ix>>
685 for Acyclic<$graph_type<N, E, Ix>>
686 {
687 type Error = Cycle<NodeIndex<Ix>>;
688
689 fn try_from(graph: $graph_type<N, E, Ix>) -> Result<Self, Self::Error> {
690 let order_map = OrderMap::try_from_graph(&graph)?;
691 let discovered = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
692 let finished = RefCell::new(FixedBitSet::with_capacity(graph.node_bound()));
693 Ok(Self {
694 graph,
695 order_map,
696 discovered,
697 finished,
698 })
699 }
700 }
701
702 impl<'a, N, E, Ix: IndexType> IntoEdgeReferences for &'a Acyclic<$graph_type<N, E, Ix>> {
703 type EdgeRef = <&'a $graph_type<N, E, Ix> as IntoEdgeReferences>::EdgeRef;
704 type EdgeReferences = <&'a $graph_type<N, E, Ix> as IntoEdgeReferences>::EdgeReferences;
705
706 fn edge_references(self) -> Self::EdgeReferences {
707 self.inner().edge_references()
708 }
709 }
710
711 impl<'a, N, E, Ix: IndexType> IntoEdges for &'a Acyclic<$graph_type<N, E, Ix>> {
712 type Edges = <&'a $graph_type<N, E, Ix> as IntoEdges>::Edges;
713
714 fn edges(self, a: Self::NodeId) -> Self::Edges {
715 self.inner().edges(a)
716 }
717 }
718
719 impl<'a, N, E, Ix: IndexType> IntoEdgesDirected for &'a Acyclic<$graph_type<N, E, Ix>> {
720 type EdgesDirected = <&'a $graph_type<N, E, Ix> as IntoEdgesDirected>::EdgesDirected;
721
722 fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected {
723 self.inner().edges_directed(a, dir)
724 }
725 }
726
727 impl<'a, N, E, Ix: IndexType> IntoNeighbors for &'a Acyclic<$graph_type<N, E, Ix>> {
728 type Neighbors = <&'a $graph_type<N, E, Ix> as IntoNeighbors>::Neighbors;
729
730 fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
731 self.inner().neighbors(a)
732 }
733 }
734
735 impl<'a, N, E, Ix: IndexType> IntoNeighborsDirected for &'a Acyclic<$graph_type<N, E, Ix>> {
736 type NeighborsDirected =
737 <&'a $graph_type<N, E, Ix> as IntoNeighborsDirected>::NeighborsDirected;
738
739 fn neighbors_directed(self, n: Self::NodeId, d: Direction) -> Self::NeighborsDirected {
740 self.inner().neighbors_directed(n, d)
741 }
742 }
743
744 impl<'a, N, E, Ix: IndexType> IntoNodeIdentifiers for &'a Acyclic<$graph_type<N, E, Ix>> {
745 type NodeIdentifiers =
746 <&'a $graph_type<N, E, Ix> as IntoNodeIdentifiers>::NodeIdentifiers;
747
748 fn node_identifiers(self) -> Self::NodeIdentifiers {
749 self.inner().node_identifiers()
750 }
751 }
752
753 impl<'a, N, E, Ix: IndexType> IntoNodeReferences for &'a Acyclic<$graph_type<N, E, Ix>> {
754 type NodeRef = <&'a $graph_type<N, E, Ix> as IntoNodeReferences>::NodeRef;
755 type NodeReferences = <&'a $graph_type<N, E, Ix> as IntoNodeReferences>::NodeReferences;
756
757 fn node_references(self) -> Self::NodeReferences {
758 self.inner().node_references()
759 }
760 }
761 };
762}
763
764impl_graph_traits!(DiGraph);
765#[cfg(feature = "stable_graph")]
766impl_graph_traits!(StableDiGraph);
767
768#[cfg(test)]
769mod tests {
770 use alloc::vec::Vec;
771
772 use super::*;
773 use crate::prelude::DiGraph;
774 use crate::visit::IntoNodeReferences;
775
776 #[cfg(feature = "stable_graph")]
777 use crate::prelude::StableDiGraph;
778
779 #[test]
780 fn test_acyclic_graph() {
781 let mut graph = DiGraph::<(), ()>::new();
783 let a = graph.add_node(());
784 let c = graph.add_node(());
785 let b = graph.add_node(());
786 graph.add_edge(a, b, ());
787 graph.add_edge(b, c, ());
788
789 let mut acyclic = Acyclic::try_from_graph(graph).unwrap();
791
792 assert_valid_topological_order(&acyclic);
794
795 assert!(acyclic.try_add_edge(a, c, ()).is_ok());
797 assert_valid_topological_order(&acyclic);
798
799 assert!(acyclic.try_add_edge(c, a, ()).is_err());
801
802 let d = acyclic.add_node(());
804 assert!(acyclic.try_add_edge(c, d, ()).is_ok());
805 assert_valid_topological_order(&acyclic);
806
807 assert!(acyclic.add_edge(d, a, ()).is_none());
809 }
810
811 #[cfg(feature = "stable_graph")]
812 #[test]
813 fn test_acyclic_graph_add_remove() {
814 let mut acyclic = Acyclic::<StableDiGraph<(), ()>>::new();
816 let a = acyclic.add_node(());
817 let b = acyclic.add_node(());
818 assert!(acyclic.try_add_edge(a, b, ()).is_ok());
819
820 assert_valid_topological_order(&acyclic);
822
823 let c = acyclic.add_node(());
825 assert!(acyclic.try_add_edge(b, c, ()).is_ok());
826
827 assert_valid_topological_order(&acyclic);
829
830 acyclic.remove_node(b);
832
833 assert_valid_topological_order(&acyclic);
835
836 let remaining_nodes: Vec<_> = acyclic
838 .inner()
839 .node_references()
840 .map(|(id, _)| id)
841 .collect();
842 assert_eq!(remaining_nodes.len(), 2);
843 assert!(remaining_nodes.contains(&a));
844 assert!(remaining_nodes.contains(&c));
845 assert!(!acyclic.inner().contains_edge(a, c));
846 }
847
848 fn assert_valid_topological_order<'a, G>(acyclic: &'a Acyclic<G>)
849 where
850 G: Visitable + NodeCount + NodeIndexable,
851 &'a G: NodeIndexable
852 + IntoNodeReferences
853 + IntoNeighborsDirected
854 + GraphBase<NodeId = G::NodeId>,
855 G::NodeId: core::fmt::Debug,
856 {
857 let ordered_nodes: Vec<_> = acyclic.nodes_iter().collect();
858 assert_eq!(ordered_nodes.len(), acyclic.node_count());
859 let nodes: Vec<_> = acyclic.inner().node_identifiers().collect();
860
861 let mut last_position = None;
863 for (idx, &node) in ordered_nodes.iter().enumerate() {
864 assert!(nodes.contains(&node));
865
866 let pos = acyclic.get_position(node);
868 assert!(Some(pos) > last_position);
869 last_position = Some(pos);
870
871 for neighbor in acyclic.inner().neighbors(node) {
873 let neighbour_idx = ordered_nodes.iter().position(|&n| n == neighbor).unwrap();
874 assert!(neighbour_idx > idx);
875 }
876 }
877 }
878}