daggy/
lib.rs

1//! **daggy** is a directed acyclic graph data structure library.
2//!
3//! The most prominent type is [**Dag**][1] - a wrapper around [petgraph][2]'s [**Graph**][3]
4//! data structure, exposing a refined API targeted towards directed acyclic graph related
5//! functionality.
6//!
7//! The [`Walker`] trait defines a variety of useful methods for traversing any graph type. Its
8//! methods behave similarly to iterator types, however **Walker**s do not require borrowing the
9//! graph. This means that we can still safely mutably borrow from the graph whilst we traverse it.
10//!
11//! [1]: Dag
12//! [2]: petgraph
13//! [3]: petgraph::graph::Graph
14//!
15//!
16//! ## Usage
17//!
18//! Use daggy in your project by adding it to your `Cargo.toml` dependencies:
19//!
20//! ```toml
21//! [dependencies]
22//! daggy = "0.9.0"
23//!
24//! # Enables the `StableDag` type.
25//! daggy = { version = "0.9.0", features = ["stable_dag"] }
26//!
27//! # Allows the `Dag` to be serialized and deserialized.
28//! daggy = { version = "0.9.0", features = ["serde-1"] }
29//! ```
30//!
31//! # Examples
32//!
33//! > Please see the [tests directory][4] for some basic usage examples.
34//!
35//! Transitive reduction:
36//!
37//! ```rust
38//! use daggy::Dag;
39//!
40//! let mut dag = Dag::<&str, &str>::new();
41//!
42//! // Reduce edges:
43//! //
44//! // ```text
45//! // # Before:          | # After:
46//! //                    |
47//! // a -> b ----.       | a -> b ----.
48//! //  |         |       |  |         |
49//! //  |-> c ----|----.  |  '-> c     |
50//! //  |    \    |    |  |       \    |
51//! //  |     \   v    |  |        \   v
52//! //  |------>> d    |  |         '> d
53//! //  |          \   v  |             \
54//! //  '----------->> e  |              '> e
55//! // ```
56//!
57//! let a = dag.add_node("a");
58//!
59//! let (_, b) = dag.add_child(a, "a->b", "b");
60//! let (_, c) = dag.add_child(a, "a->c", "c");
61//! let (_, d) = dag.add_child(a, "a->d", "d");
62//! let (_, e) = dag.add_child(a, "a->e", "e");
63//!
64//! dag.add_edge(b, d, "b->d").unwrap();
65//!
66//! dag.add_edge(c, d, "c->d").unwrap();
67//! dag.add_edge(c, e, "c->e").unwrap();
68//!
69//! dag.add_edge(d, e, "d->e").unwrap();
70//!
71//! assert_eq!(dag.edge_count(), 8);
72//!
73//! dag.transitive_reduce(vec![a]);
74//!
75//! let mut edges = dag.graph().edge_weights().copied().collect::<Vec<_>>();
76//! edges.sort();
77//! assert_eq!(dag.edge_count(), 5);
78//! assert_eq!(&edges, &["a->b", "a->c", "b->d", "c->d", "d->e"]);
79//! ```
80//!
81//! [4]: https://github.com/mitchmindtree/daggy/tree/master/tests
82
83#![forbid(unsafe_code)]
84#![warn(missing_docs)]
85
86pub use petgraph;
87use petgraph as pg;
88use petgraph::algo::{has_path_connecting, DfsSpace};
89use petgraph::graph::{DefaultIx, DiGraph, GraphIndex, IndexType};
90use petgraph::visit::{
91    GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected,
92    IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences,
93    NodeCompactIndexable, NodeCount, NodeIndexable, Visitable,
94};
95use petgraph::IntoWeightedEdge;
96use std::marker::PhantomData;
97use std::ops::{Index, IndexMut};
98
99// Petgraph re-exports.
100pub use petgraph::graph::{EdgeIndex, EdgeWeightsMut, NodeIndex, NodeWeightsMut};
101pub use petgraph::visit::Walker;
102
103#[cfg(feature = "serde-1")]
104mod serde;
105#[cfg(feature = "stable_dag")]
106pub mod stable_dag;
107pub mod walker;
108
109/// Read only access into a **Dag**'s internal node array.
110pub type RawNodes<'a, N, Ix> = &'a [pg::graph::Node<N, Ix>];
111/// Read only access into a **Dag**'s internal edge array.
112pub type RawEdges<'a, E, Ix> = &'a [pg::graph::Edge<E, Ix>];
113/// An iterator yielding all edges to/from some node.
114pub type Edges<'a, E, Ix> = pg::graph::Edges<'a, E, pg::Directed, Ix>;
115
116/// A Directed acyclic graph (DAG) data structure.
117///
118/// Dag is a thin wrapper around petgraph's `Graph` data structure, providing a refined API for
119/// dealing specifically with DAGs.
120///
121/// Note: The following documentation is adapted from petgraph's [**Graph** documentation][1]
122///
123/// **Dag** is parameterized over the node weight **N**, edge weight **E** and index type **Ix**.
124///
125/// **NodeIndex** is a type that acts as a reference to nodes, but these are only stable across
126/// certain operations. **Removing nodes may shift other indices.** Adding kids to the **Dag**
127/// keeps all indices stable, but removing a node will force the last node to shift its index to
128/// take its place.
129///
130/// The fact that the node indices in the **Dag** are numbered in a compact interval from 0 to *n*-1
131/// simplifies some graph algorithms.
132///
133/// The **Ix** parameter is u32 by default. The goal is that you can ignore this parameter
134/// completely unless you need a very large **Dag** -- then you can use usize.
135///
136/// The **Dag** also offers methods for accessing the underlying **Graph**, which can be useful
137/// for taking advantage of petgraph's various graph-related algorithms.
138///
139///
140/// [1]: petgraph::graph::Graph
141#[derive(Clone, Debug)]
142pub struct Dag<N, E, Ix: IndexType = DefaultIx> {
143    graph: DiGraph<N, E, Ix>,
144    cycle_state: DfsSpace<NodeIndex<Ix>, <DiGraph<N, E, Ix> as Visitable>::Map>,
145}
146
147/// A **Walker** type that can be used to step through the children of some parent node.
148pub struct Children<N, E, Ix: IndexType> {
149    walk_edges: pg::graph::WalkNeighbors<Ix>,
150    _node: PhantomData<N>,
151    _edge: PhantomData<E>,
152}
153
154/// A **Walker** type that can be used to step through the parents of some child node.
155pub struct Parents<N, E, Ix: IndexType> {
156    walk_edges: pg::graph::WalkNeighbors<Ix>,
157    _node: PhantomData<N>,
158    _edge: PhantomData<E>,
159}
160
161/// An iterator yielding multiple `EdgeIndex`s, returned by the `Graph::add_edges` method.
162pub struct EdgeIndices<Ix: IndexType> {
163    indices: std::ops::Range<usize>,
164    _phantom: PhantomData<Ix>,
165}
166
167/// An alias to simplify the **Recursive** **Walker** type returned by **Dag**.
168pub type RecursiveWalk<N, E, Ix, F> = walker::Recursive<Dag<N, E, Ix>, F>;
169
170/// An error returned by the `Dag::add_edge` method in the case that adding an edge would have
171/// caused the graph to cycle.
172#[derive(Copy, Clone)]
173pub struct WouldCycle<E>(pub E);
174
175impl<N, E, Ix> Dag<N, E, Ix>
176where
177    Ix: IndexType,
178{
179    /// Create a new, empty `Dag`.
180    pub fn new() -> Self {
181        Self::with_capacity(1, 1)
182    }
183
184    /// Create a new `Dag` with estimated capacity for its node and edge Vecs.
185    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
186        Dag {
187            graph: DiGraph::with_capacity(nodes, edges),
188            cycle_state: DfsSpace::default(),
189        }
190    }
191
192    /// Create a `Dag` from an iterator yielding edges.
193    ///
194    /// Node weights `N` are set to default values.
195    ///
196    /// `Edge` weights `E` may either be specified in the list, or they are filled with default
197    /// values.
198    ///
199    /// Nodes are inserted automatically to match the edges.
200    ///
201    /// Returns an `Err` if adding any of the edges would cause a cycle.
202    pub fn from_edges<I>(edges: I) -> Result<Self, WouldCycle<E>>
203    where
204        I: IntoIterator,
205        I::Item: IntoWeightedEdge<E>,
206        <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
207        N: Default,
208    {
209        let mut dag = Self::default();
210        dag.extend_with_edges(edges)?;
211        Ok(dag)
212    }
213
214    /// Extend the `Dag` with the given edges.
215    ///
216    /// Node weights `N` are set to default values.
217    ///
218    /// Edge weights `E` may either be specified in the list, or they are filled with default
219    /// values.
220    ///
221    /// Nodes are inserted automatically to match the edges.
222    ///
223    /// Returns an `Err` if adding an edge would cause a cycle.
224    pub fn extend_with_edges<I>(&mut self, edges: I) -> Result<(), WouldCycle<E>>
225    where
226        I: IntoIterator,
227        I::Item: IntoWeightedEdge<E>,
228        <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
229        N: Default,
230    {
231        for edge in edges {
232            let (source, target, weight) = edge.into_weighted_edge();
233            let (source, target) = (source.into(), target.into());
234            let nx = std::cmp::max(source, target);
235            while nx.index() >= self.node_count() {
236                self.add_node(N::default());
237            }
238            self.add_edge(source, target, weight)?;
239        }
240        Ok(())
241    }
242
243    /// Create a `Dag` from an iterator yielding elements.
244    ///
245    /// Returns an `Err` if an edge would cause a cycle within the graph.
246    pub fn from_elements<I>(elements: I) -> Result<Self, WouldCycle<E>>
247    where
248        Self: Sized,
249        I: IntoIterator<Item = pg::data::Element<N, E>>,
250    {
251        let mut dag = Self::default();
252        for elem in elements {
253            match elem {
254                pg::data::Element::Node { weight } => {
255                    dag.add_node(weight);
256                }
257                pg::data::Element::Edge {
258                    source,
259                    target,
260                    weight,
261                } => {
262                    let n = NodeIndex::new(source);
263                    let e = NodeIndex::new(target);
264                    dag.update_edge(n, e, weight)?;
265                }
266            }
267        }
268        Ok(dag)
269    }
270
271    /// Create a new `Graph` by mapping node and edge weights to new values.
272    ///
273    /// The resulting graph has the same structure and the same graph indices as `self`.
274    pub fn map<'a, F, G, N2, E2>(&'a self, node_map: F, edge_map: G) -> Dag<N2, E2, Ix>
275    where
276        F: FnMut(NodeIndex<Ix>, &'a N) -> N2,
277        G: FnMut(EdgeIndex<Ix>, &'a E) -> E2,
278    {
279        let graph = self.graph.map(node_map, edge_map);
280        let cycle_state = self.cycle_state.clone();
281        Dag { graph, cycle_state }
282    }
283
284    /// Create a new `Dag` by mapping node and edge weights. A node or edge may be mapped to `None`
285    /// to exclude it from the resulting `Dag`.
286    ///
287    /// Nodes are mapped first with the `node_map` closure, then `edge_map` is called for the edges
288    /// that have not had any endpoint removed.
289    ///
290    /// The resulting graph has the structure of a subgraph of the original graph. If no nodes are
291    /// removed, the resulting graph has compatible node indices.
292    ///
293    /// If neither nodes nor edges are removed, the resulting graph has compatible node indices. If
294    /// neither nodes nor edges are removed the result has the same graph indices as `self`.
295    ///
296    /// The resulting graph has the same structure and the same graph indices as `self`.
297    pub fn filter_map<'a, F, G, N2, E2>(&'a self, node_map: F, edge_map: G) -> Dag<N2, E2, Ix>
298    where
299        F: FnMut(NodeIndex<Ix>, &'a N) -> Option<N2>,
300        G: FnMut(EdgeIndex<Ix>, &'a E) -> Option<E2>,
301    {
302        let graph = self.graph.filter_map(node_map, edge_map);
303        let cycle_state = DfsSpace::new(&graph);
304        Dag { graph, cycle_state }
305    }
306
307    /// Removes all nodes and edges from the **Dag**.
308    pub fn clear(&mut self) {
309        self.graph.clear();
310    }
311
312    /// The total number of nodes in the **Dag**.
313    pub fn node_count(&self) -> usize {
314        self.graph.node_count()
315    }
316
317    /// The total number of edges in the **Dag**.
318    pub fn edge_count(&self) -> usize {
319        self.graph.edge_count()
320    }
321
322    /// Reserves capacity for at least `additional` more nodes to be inserted in
323    /// the graph. Graph may reserve more space to avoid frequent reallocations.
324    ///
325    /// **Panics** if the new capacity overflows `usize`.
326    pub fn reserve_nodes(&mut self, additional: usize) {
327        self.graph.reserve_nodes(additional)
328    }
329
330    /// Reserves the minimum capacity for exactly `additional` more nodes to be
331    /// inserted in the graph. Does nothing if the capacity is already
332    /// sufficient.
333    ///
334    /// Prefer `reserve_nodes` if future insertions are expected.
335    ///
336    /// **Panics** if the new capacity overflows `usize`.
337    pub fn reserve_exact_nodes(&mut self, additional: usize) {
338        self.graph.reserve_exact_nodes(additional)
339    }
340
341    /// Reserves capacity for at least `additional` more edges to be inserted in
342    /// the graph. Graph may reserve more space to avoid frequent reallocations.
343    ///
344    /// **Panics** if the new capacity overflows `usize`.
345    pub fn reserve_edges(&mut self, additional: usize) {
346        self.graph.reserve_edges(additional)
347    }
348
349    /// Reserves the minimum capacity for exactly `additional` more edges to be
350    /// inserted in the graph.
351    /// Does nothing if the capacity is already sufficient.
352    ///
353    /// Prefer `reserve_edges` if future insertions are expected.
354    ///
355    /// **Panics** if the new capacity overflows `usize`.
356    pub fn reserve_exact_edges(&mut self, additional: usize) {
357        self.graph.reserve_exact_edges(additional)
358    }
359
360    /// Shrinks the capacity of the graph as much as possible.
361    pub fn shrink_to_fit(&mut self) {
362        self.graph.shrink_to_fit();
363    }
364
365    /// Shrinks the capacity of the underlying nodes collection as much as possible.
366    pub fn shrink_to_fit_nodes(&mut self) {
367        self.graph.shrink_to_fit_nodes();
368    }
369
370    /// Shrinks the capacity of the underlying edges collection as much as possible.
371    pub fn shrink_to_fit_edges(&mut self) {
372        self.graph.shrink_to_fit_edges();
373    }
374
375    /// Borrow the `Dag`'s underlying `DiGraph<N, Ix>`.
376    ///
377    /// All existing indices may be used to index into this `DiGraph` the same way they may be
378    /// used to index into the `Dag`.
379    pub fn graph(&self) -> &DiGraph<N, E, Ix> {
380        &self.graph
381    }
382
383    /// Take ownership of the `Dag` and return the internal `DiGraph`.
384    ///
385    /// All existing indices may be used to index into this `DiGraph` the same way they may be
386    /// used to index into the `Dag`.
387    pub fn into_graph(self) -> DiGraph<N, E, Ix> {
388        let Dag { graph, .. } = self;
389        graph
390    }
391
392    /// Add a new node to the `Dag` with the given weight.
393    ///
394    /// Computes in **O(1)** time.
395    ///
396    /// Returns the index of the new node.
397    ///
398    /// **Note:** If you're adding a new node and immediately adding a single edge to that node from
399    /// some other node, consider using the [add_child](Dag::add_child) or
400    /// [add_parent](Dag::add_parent) methods instead for better performance.
401    ///
402    /// **Panics** if the Graph is at the maximum number of nodes for its index type.
403    pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
404        self.graph.add_node(weight)
405    }
406
407    /// Add a new directed edge to the `Dag` with the given weight.
408    ///
409    /// The added edge will be in the direction `a` -> `b`
410    ///
411    /// Checks if the edge would create a cycle in the Graph.
412    ///
413    /// If adding the edge **would not** cause the graph to cycle, the edge will be added and its
414    /// `EdgeIndex` returned.
415    ///
416    /// If adding the edge **would** cause the graph to cycle, the edge will not be added and
417    /// instead a `WouldCycle<E>` error with the given weight will be returned.
418    ///
419    /// In the worst case, petgraph's [`is_cyclic_directed`][1]
420    /// function is used to check whether or not adding the edge would create a cycle.
421    ///
422    /// **Note:** Dag allows adding parallel ("duplicate") edges. If you want to avoid this, use
423    /// [`update_edge`][2] instead.
424    ///
425    /// **Note:** If you're adding a new node and immediately adding a single edge to that node from
426    /// some other node, consider using the [add_child][3] or
427    /// [add_parent][4] methods instead for better performance.
428    ///
429    /// **Panics** if either `a` or `b` do not exist within the **Dag**.
430    ///
431    /// **Panics** if the Graph is at the maximum number of edges for its index type.
432    ///
433    ///
434    /// [1]: petgraph::algo::is_cyclic_directed
435    /// [2]: Dag::update_edge
436    /// [3]: Dag::add_child
437    /// [4]: Dag::add_parent
438    pub fn add_edge(
439        &mut self,
440        a: NodeIndex<Ix>,
441        b: NodeIndex<Ix>,
442        weight: E,
443    ) -> Result<EdgeIndex<Ix>, WouldCycle<E>> {
444        let should_check_for_cycle = must_check_for_cycle(self, a, b);
445        let state = Some(&mut self.cycle_state);
446        if should_check_for_cycle && has_path_connecting(&self.graph, b, a, state) {
447            return Err(WouldCycle(weight));
448        }
449
450        Ok(self.graph.add_edge(a, b, weight))
451    }
452
453    /// Adds the given directed edges to the `Dag`, each with their own given weight.
454    ///
455    /// The given iterator should yield a `NodeIndex` pair along with a weight for each Edge to be
456    /// added in a tuple.
457    ///
458    /// If we were to describe the tuple as *(a, b, weight)*, the connection would be directed as
459    /// follows:
460    ///
461    /// *a -> b*
462    ///
463    /// This method behaves similarly to the [`add_edge`][1]
464    /// method, however rather than checking whether or not a cycle has been created after adding
465    /// each edge, it only checks after all edges have been added. This makes it a slightly more
466    /// performant and ergonomic option that repeatedly calling `add_edge`.
467    ///
468    /// If adding the edges **would not** cause the graph to cycle, the edges will be added and
469    /// their indices returned in an `EdgeIndices` iterator, yielding indices for each edge in the
470    /// same order that they were given.
471    ///
472    /// If adding the edges **would** cause the graph to cycle, the edges will not be added and
473    /// instead a `WouldCycle<Vec<E>>` error with the unused weights will be returned. The order of
474    /// the returned `Vec` will be the reverse of the given order.
475    ///
476    /// **Note:** Dag allows adding parallel ("duplicate") edges. If you want to avoid this, use
477    /// [`update_edge`][2] instead.
478    ///
479    /// **Note:** If you're adding a series of new nodes and edges to a single node, consider using
480    ///  the [add_child][3] or [add_parent][4] methods instead for greater convenience.
481    ///
482    /// **Panics** if the Graph is at the maximum number of nodes for its index type.
483    ///
484    ///
485    /// [1]: Dag::add_edge
486    /// [2]: Dag::update_edge
487    /// [3]: Dag::add_child
488    /// [4]: Dag::add_parent
489    pub fn add_edges<I>(&mut self, edges: I) -> Result<EdgeIndices<Ix>, WouldCycle<Vec<E>>>
490    where
491        I: IntoIterator<Item = (NodeIndex<Ix>, NodeIndex<Ix>, E)>,
492    {
493        let mut num_edges = 0;
494        let mut should_check_for_cycle = false;
495
496        for (a, b, weight) in edges {
497            // Check whether or not we'll need to check for cycles.
498            if !should_check_for_cycle && must_check_for_cycle(self, a, b) {
499                should_check_for_cycle = true;
500            }
501
502            self.graph.add_edge(a, b, weight);
503            num_edges += 1;
504        }
505
506        let total_edges = self.edge_count();
507        let new_edges_range = total_edges - num_edges..total_edges;
508
509        // Check if adding the edges has created a cycle.
510        if should_check_for_cycle && pg::algo::is_cyclic_directed(&self.graph) {
511            let removed_edges = new_edges_range.rev().filter_map(|i| {
512                let idx = EdgeIndex::new(i);
513                self.graph.remove_edge(idx)
514            });
515            Err(WouldCycle(removed_edges.collect()))
516        } else {
517            Ok(EdgeIndices {
518                indices: new_edges_range,
519                _phantom: std::marker::PhantomData,
520            })
521        }
522    }
523
524    /// Update the edge from nodes `a` -> `b` with the given weight.
525    ///
526    /// If the edge doesn't already exist, it will be added using the `add_edge` method.
527    ///
528    /// Please read the [`add_edge`](Dag::add_edge) method documentation for more important details.
529    ///
530    /// Checks if the edge would create a cycle in the Graph.
531    ///
532    /// Computes in **O(t + e)** time where "t" is the complexity of `add_edge` and e is the number
533    /// of edges connected to the nodes a and b.
534    ///
535    /// Returns the index of the edge, or a `WouldCycle` error if adding the edge would create a
536    /// cycle.
537    ///
538    /// **Note:** If you're adding a new node and immediately adding a single edge to that node from
539    /// some parent node, consider using the [`add_child`](Dag::add_child)
540    /// method instead for greater convenience.
541    ///
542    /// **Panics** if the Graph is at the maximum number of nodes for its index type.
543    pub fn update_edge(
544        &mut self,
545        a: NodeIndex<Ix>,
546        b: NodeIndex<Ix>,
547        weight: E,
548    ) -> Result<EdgeIndex<Ix>, WouldCycle<E>> {
549        if let Some(edge_idx) = self.find_edge(a, b) {
550            if let Some(edge) = self.edge_weight_mut(edge_idx) {
551                *edge = weight;
552                return Ok(edge_idx);
553            }
554        }
555        self.add_edge(a, b, weight)
556    }
557
558    /// Find and return the index to the edge that describes `a` -> `b` if there is one.
559    ///
560    /// Computes in **O(e')** time, where **e'** is the number of edges connected to the nodes `a`
561    /// and `b`.
562    pub fn find_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
563        self.graph.find_edge(a, b)
564    }
565
566    /// Access the parent and child nodes for the given `EdgeIndex`.
567    pub fn edge_endpoints(&self, e: EdgeIndex<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
568        self.graph.edge_endpoints(e)
569    }
570
571    /// Remove all edges.
572    pub fn clear_edges(&mut self) {
573        self.graph.clear_edges()
574    }
575
576    /// Add a new edge and parent node to the node at the given `NodeIndex`.
577    ///
578    /// Returns both the edge's `EdgeIndex` and the node's `NodeIndex`.
579    ///
580    /// node -> edge -> child
581    ///
582    /// Computes in **O(1)** time.
583    ///
584    /// This is faster than using `add_node` and `add_edge`. This is because we don't have to check
585    /// if the graph would cycle when adding an edge to the new node, as we know it it will be the
586    /// only edge connected to that node.
587    ///
588    /// **Panics** if the given child node doesn't exist.
589    ///
590    /// **Panics** if the Graph is at the maximum number of edges for its index.
591    pub fn add_parent(
592        &mut self,
593        child: NodeIndex<Ix>,
594        edge: E,
595        node: N,
596    ) -> (EdgeIndex<Ix>, NodeIndex<Ix>) {
597        let parent_node = self.graph.add_node(node);
598        let parent_edge = self.graph.add_edge(parent_node, child, edge);
599        (parent_edge, parent_node)
600    }
601
602    /// Add a new edge and child node to the node at the given `NodeIndex`.
603    /// Returns both the edge's `EdgeIndex` and the node's `NodeIndex`.
604    ///
605    /// child -> edge -> node
606    ///
607    /// Computes in **O(1)** time.
608    ///
609    /// This is faster than using `add_node` and `add_edge`. This is because we don't have to check
610    /// if the graph would cycle when adding an edge to the new node, as we know it it will be the
611    /// only edge connected to that node.
612    ///
613    /// **Panics** if the given parent node doesn't exist.
614    ///
615    /// **Panics** if the Graph is at the maximum number of edges for its index.
616    pub fn add_child(
617        &mut self,
618        parent: NodeIndex<Ix>,
619        edge: E,
620        node: N,
621    ) -> (EdgeIndex<Ix>, NodeIndex<Ix>) {
622        let child_node = self.graph.add_node(node);
623        let child_edge = self.graph.add_edge(parent, child_node, edge);
624        (child_edge, child_node)
625    }
626
627    /// Borrow the weight from the node at the given index.
628    pub fn node_weight(&self, node: NodeIndex<Ix>) -> Option<&N> {
629        self.graph.node_weight(node)
630    }
631
632    /// Mutably borrow the weight from the node at the given index.
633    pub fn node_weight_mut(&mut self, node: NodeIndex<Ix>) -> Option<&mut N> {
634        self.graph.node_weight_mut(node)
635    }
636
637    /// Read from the internal node array.
638    pub fn raw_nodes(&self) -> RawNodes<N, Ix> {
639        self.graph.raw_nodes()
640    }
641
642    /// An iterator yielding mutable access to all node weights.
643    ///
644    /// The order in which weights are yielded matches the order of their node indices.
645    pub fn node_weights_mut(&mut self) -> NodeWeightsMut<N, Ix> {
646        self.graph.node_weights_mut()
647    }
648
649    /// Borrow the weight from the edge at the given index.
650    pub fn edge_weight(&self, edge: EdgeIndex<Ix>) -> Option<&E> {
651        self.graph.edge_weight(edge)
652    }
653
654    /// Mutably borrow the weight from the edge at the given index.
655    pub fn edge_weight_mut(&mut self, edge: EdgeIndex<Ix>) -> Option<&mut E> {
656        self.graph.edge_weight_mut(edge)
657    }
658
659    /// Read from the internal edge array.
660    pub fn raw_edges(&self) -> RawEdges<E, Ix> {
661        self.graph.raw_edges()
662    }
663
664    /// An iterator yielding mutable access to all edge weights.
665    ///
666    /// The order in which weights are yielded matches the order of their edge indices.
667    pub fn edge_weights_mut(&mut self) -> EdgeWeightsMut<E, Ix> {
668        self.graph.edge_weights_mut()
669    }
670
671    /// Index the `Dag` by two indices.
672    ///
673    /// Both indices can be either `NodeIndex`s, `EdgeIndex`s or a combination of the two.
674    ///
675    /// **Panics** if the indices are equal or if they are out of bounds.
676    #[allow(clippy::type_complexity)]
677    pub fn index_twice_mut<A, B>(
678        &mut self,
679        a: A,
680        b: B,
681    ) -> (
682        &mut <DiGraph<N, E, Ix> as Index<A>>::Output,
683        &mut <DiGraph<N, E, Ix> as Index<B>>::Output,
684    )
685    where
686        DiGraph<N, E, Ix>: IndexMut<A> + IndexMut<B>,
687        A: GraphIndex,
688        B: GraphIndex,
689    {
690        self.graph.index_twice_mut(a, b)
691    }
692
693    /// Remove the node at the given index from the `Dag` and return it if it exists.
694    ///
695    /// Note: Calling this may shift (and in turn invalidate) previously returned node indices!
696    pub fn remove_node(&mut self, node: NodeIndex<Ix>) -> Option<N> {
697        self.graph.remove_node(node)
698    }
699
700    /// Remove an edge and return its weight, or `None` if it didn't exist.
701    ///
702    /// Computes in **O(e')** time, where **e'** is the size of four particular edge lists, for the
703    /// nodes of **e** and the nodes of another affected edge.
704    pub fn remove_edge(&mut self, e: EdgeIndex<Ix>) -> Option<E> {
705        self.graph.remove_edge(e)
706    }
707
708    /// A **Walker** type that may be used to step through the parents of the given child node.
709    ///
710    /// Unlike iterator types, **Walker**s do not require borrowing the internal **Graph**. This
711    /// makes them useful for traversing the **Graph** while still being able to mutably borrow it.
712    ///
713    /// If you require an iterator, use one of the **Walker** methods for converting this
714    /// **Walker** into a similarly behaving **Iterator** type.
715    ///
716    /// See the [**Walker**](Walker) trait for more useful methods.
717    pub fn parents(&self, child: NodeIndex<Ix>) -> Parents<N, E, Ix> {
718        let walk_edges = self.graph.neighbors_directed(child, pg::Incoming).detach();
719        Parents {
720            walk_edges,
721            _node: PhantomData,
722            _edge: PhantomData,
723        }
724    }
725
726    /// A "walker" object that may be used to step through the children of the given parent node.
727    ///
728    /// Unlike iterator types, **Walker**s do not require borrowing the internal **Graph**. This
729    /// makes them useful for traversing the **Graph** while still being able to mutably borrow it.
730    ///
731    /// If you require an iterator, use one of the **Walker** methods for converting this
732    /// **Walker** into a similarly behaving **Iterator** type.
733    ///
734    /// See the [**Walker**](Walker) trait for more useful methods.
735    pub fn children(&self, parent: NodeIndex<Ix>) -> Children<N, E, Ix> {
736        let walk_edges = self.graph.neighbors_directed(parent, pg::Outgoing).detach();
737        Children {
738            walk_edges,
739            _node: PhantomData,
740            _edge: PhantomData,
741        }
742    }
743
744    /// A **Walker** type that recursively walks the **Dag** using the given `recursive_fn`.
745    ///
746    /// See the [**Walker**](Walker) trait for more useful methods.
747    pub fn recursive_walk<F>(
748        &self,
749        start: NodeIndex<Ix>,
750        recursive_fn: F,
751    ) -> RecursiveWalk<N, E, Ix, F>
752    where
753        F: FnMut(&Self, NodeIndex<Ix>) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)>,
754    {
755        walker::Recursive::new(start, recursive_fn)
756    }
757
758    fn transitive_reduce_iter(
759        &mut self,
760        curr_node: NodeIndex<Ix>,
761        ancestors: &mut Vec<NodeIndex<Ix>>,
762    ) {
763        let mut redundant_edges = Vec::new();
764        for (_, child) in self.children(curr_node).iter(self) {
765            for (edge, coparent) in self.parents(child).iter(self) {
766                if ancestors.contains(&coparent) {
767                    redundant_edges.push(edge);
768                }
769            }
770        }
771        for edge in redundant_edges {
772            self.remove_edge(edge);
773        }
774
775        ancestors.push(curr_node);
776
777        let mut children = self.children(curr_node);
778        while let Some((_, child)) = children.walk_next(self) {
779            self.transitive_reduce_iter(child, ancestors)
780        }
781
782        ancestors.pop();
783    }
784
785    /// Mutates the DAG into its [transitive reduction](https://en.wikipedia.org/wiki/Directed_acyclic_graph#Transitive_closure_and_transitive_reduction)
786    pub fn transitive_reduce(&mut self, roots: Vec<NodeIndex<Ix>>) {
787        for root in roots {
788            self.transitive_reduce_iter(root, &mut Vec::new())
789        }
790    }
791}
792
793/// After adding a new edge to the graph, we use this function immediately after to check whether
794/// or not we need to check for a cycle.
795///
796/// If our parent *a* has no parents or our child *b* has no children, or if there was already an
797/// edge connecting *a* to *b*, we know that adding this edge has not caused the graph to cycle.
798fn must_check_for_cycle<N, E, Ix>(dag: &Dag<N, E, Ix>, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool
799where
800    Ix: IndexType,
801{
802    if a == b {
803        return true;
804    }
805    dag.parents(a).walk_next(dag).is_some()
806        && dag.children(b).walk_next(dag).is_some()
807        && dag.find_edge(a, b).is_none()
808}
809
810// Dag implementations.
811
812impl<N, E, Ix> From<Dag<N, E, Ix>> for DiGraph<N, E, Ix>
813where
814    Ix: IndexType,
815{
816    fn from(val: Dag<N, E, Ix>) -> Self {
817        val.into_graph()
818    }
819}
820
821impl<N, E, Ix> Default for Dag<N, E, Ix>
822where
823    Ix: IndexType,
824{
825    fn default() -> Self {
826        Dag::new()
827    }
828}
829
830impl<N, E, Ix> GraphBase for Dag<N, E, Ix>
831where
832    Ix: IndexType,
833{
834    type NodeId = NodeIndex<Ix>;
835    type EdgeId = EdgeIndex<Ix>;
836}
837
838impl<N, E, Ix> NodeCount for Dag<N, E, Ix>
839where
840    Ix: IndexType,
841{
842    fn node_count(&self) -> usize {
843        Dag::node_count(self)
844    }
845}
846
847impl<N, E, Ix> GraphProp for Dag<N, E, Ix>
848where
849    Ix: IndexType,
850{
851    type EdgeType = pg::Directed;
852    fn is_directed(&self) -> bool {
853        true
854    }
855}
856
857impl<N, E, Ix> pg::visit::Visitable for Dag<N, E, Ix>
858where
859    Ix: IndexType,
860{
861    type Map = <DiGraph<N, E, Ix> as Visitable>::Map;
862    fn visit_map(&self) -> Self::Map {
863        self.graph.visit_map()
864    }
865    fn reset_map(&self, map: &mut Self::Map) {
866        self.graph.reset_map(map)
867    }
868}
869
870impl<N, E, Ix> pg::visit::Data for Dag<N, E, Ix>
871where
872    Ix: IndexType,
873{
874    type NodeWeight = N;
875    type EdgeWeight = E;
876}
877
878impl<N, E, Ix> pg::data::DataMap for Dag<N, E, Ix>
879where
880    Ix: IndexType,
881{
882    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
883        self.graph.node_weight(id)
884    }
885    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
886        self.graph.edge_weight(id)
887    }
888}
889
890impl<N, E, Ix> pg::data::DataMapMut for Dag<N, E, Ix>
891where
892    Ix: IndexType,
893{
894    fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
895        self.graph.node_weight_mut(id)
896    }
897    fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
898        self.graph.edge_weight_mut(id)
899    }
900}
901
902impl<'a, N, E, Ix> IntoNeighbors for &'a Dag<N, E, Ix>
903where
904    Ix: IndexType,
905{
906    type Neighbors = pg::graph::Neighbors<'a, E, Ix>;
907    fn neighbors(self, n: NodeIndex<Ix>) -> Self::Neighbors {
908        self.graph.neighbors(n)
909    }
910}
911
912impl<'a, N, E, Ix> IntoNeighborsDirected for &'a Dag<N, E, Ix>
913where
914    Ix: IndexType,
915{
916    type NeighborsDirected = pg::graph::Neighbors<'a, E, Ix>;
917    fn neighbors_directed(self, n: NodeIndex<Ix>, d: pg::Direction) -> Self::Neighbors {
918        self.graph.neighbors_directed(n, d)
919    }
920}
921
922impl<'a, N, E, Ix> IntoEdgeReferences for &'a Dag<N, E, Ix>
923where
924    Ix: IndexType,
925{
926    type EdgeRef = pg::graph::EdgeReference<'a, E, Ix>;
927    type EdgeReferences = pg::graph::EdgeReferences<'a, E, Ix>;
928    fn edge_references(self) -> Self::EdgeReferences {
929        self.graph.edge_references()
930    }
931}
932
933impl<'a, N, E, Ix> IntoEdges for &'a Dag<N, E, Ix>
934where
935    Ix: IndexType,
936{
937    type Edges = Edges<'a, E, Ix>;
938    fn edges(self, a: Self::NodeId) -> Self::Edges {
939        self.graph.edges(a)
940    }
941}
942
943impl<'a, N, E, Ix> IntoEdgesDirected for &'a Dag<N, E, Ix>
944where
945    Ix: IndexType,
946{
947    type EdgesDirected = Edges<'a, E, Ix>;
948    fn edges_directed(self, a: Self::NodeId, dir: pg::Direction) -> Self::EdgesDirected {
949        self.graph.edges_directed(a, dir)
950    }
951}
952
953impl<N, E, Ix> IntoNodeIdentifiers for &Dag<N, E, Ix>
954where
955    Ix: IndexType,
956{
957    type NodeIdentifiers = pg::graph::NodeIndices<Ix>;
958    fn node_identifiers(self) -> Self::NodeIdentifiers {
959        self.graph.node_identifiers()
960    }
961}
962
963impl<'a, N, E, Ix> IntoNodeReferences for &'a Dag<N, E, Ix>
964where
965    Ix: IndexType,
966{
967    type NodeRef = (NodeIndex<Ix>, &'a N);
968    type NodeReferences = pg::graph::NodeReferences<'a, N, Ix>;
969    fn node_references(self) -> Self::NodeReferences {
970        self.graph.node_references()
971    }
972}
973
974impl<N, E, Ix> NodeIndexable for Dag<N, E, Ix>
975where
976    Ix: IndexType,
977{
978    fn node_bound(&self) -> usize {
979        self.graph.node_bound()
980    }
981    fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
982        self.graph.to_index(ix)
983    }
984    fn from_index(&self, ix: usize) -> Self::NodeId {
985        self.graph.from_index(ix)
986    }
987}
988
989impl<N, E, Ix> NodeCompactIndexable for Dag<N, E, Ix> where Ix: IndexType {}
990
991impl<N, E, Ix> Index<NodeIndex<Ix>> for Dag<N, E, Ix>
992where
993    Ix: IndexType,
994{
995    type Output = N;
996    fn index(&self, index: NodeIndex<Ix>) -> &N {
997        &self.graph[index]
998    }
999}
1000
1001impl<N, E, Ix> IndexMut<NodeIndex<Ix>> for Dag<N, E, Ix>
1002where
1003    Ix: IndexType,
1004{
1005    fn index_mut(&mut self, index: NodeIndex<Ix>) -> &mut N {
1006        &mut self.graph[index]
1007    }
1008}
1009
1010impl<N, E, Ix> Index<EdgeIndex<Ix>> for Dag<N, E, Ix>
1011where
1012    Ix: IndexType,
1013{
1014    type Output = E;
1015    fn index(&self, index: EdgeIndex<Ix>) -> &E {
1016        &self.graph[index]
1017    }
1018}
1019
1020impl<N, E, Ix> IndexMut<EdgeIndex<Ix>> for Dag<N, E, Ix>
1021where
1022    Ix: IndexType,
1023{
1024    fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
1025        &mut self.graph[index]
1026    }
1027}
1028
1029impl<N, E, Ix> GetAdjacencyMatrix for Dag<N, E, Ix>
1030where
1031    Ix: IndexType,
1032{
1033    type AdjMatrix = <DiGraph<N, E, Ix> as GetAdjacencyMatrix>::AdjMatrix;
1034    fn adjacency_matrix(&self) -> Self::AdjMatrix {
1035        self.graph.adjacency_matrix()
1036    }
1037    fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
1038        self.graph.is_adjacent(matrix, a, b)
1039    }
1040}
1041
1042impl<'a, N, E, Ix> Walker<&'a Dag<N, E, Ix>> for Children<N, E, Ix>
1043where
1044    Ix: IndexType,
1045{
1046    type Item = (EdgeIndex<Ix>, NodeIndex<Ix>);
1047    #[inline]
1048    fn walk_next(&mut self, dag: &'a Dag<N, E, Ix>) -> Option<Self::Item> {
1049        self.walk_edges.next(&dag.graph)
1050    }
1051}
1052
1053impl<'a, N, E, Ix> Walker<&'a Dag<N, E, Ix>> for Parents<N, E, Ix>
1054where
1055    Ix: IndexType,
1056{
1057    type Item = (EdgeIndex<Ix>, NodeIndex<Ix>);
1058    #[inline]
1059    fn walk_next(&mut self, dag: &'a Dag<N, E, Ix>) -> Option<Self::Item> {
1060        self.walk_edges.next(&dag.graph)
1061    }
1062}
1063
1064impl<Ix> Iterator for EdgeIndices<Ix>
1065where
1066    Ix: IndexType,
1067{
1068    type Item = EdgeIndex<Ix>;
1069    fn next(&mut self) -> Option<EdgeIndex<Ix>> {
1070        self.indices.next().map(|i| EdgeIndex::new(i))
1071    }
1072}
1073
1074impl<E> std::fmt::Debug for WouldCycle<E> {
1075    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1076        writeln!(f, "WouldCycle")
1077    }
1078}
1079
1080impl<E> std::fmt::Display for WouldCycle<E> {
1081    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
1082        writeln!(f, "{:?}", self)
1083    }
1084}
1085
1086impl<E> std::error::Error for WouldCycle<E> {
1087    fn description(&self) -> &str {
1088        "Adding this edge would have created a cycle"
1089    }
1090}