petgraph/visit/
mod.rs

1//! Graph traits and graph traversals.
2//!
3//! ### The `Into-` Traits
4//!
5//! Graph traits like [`IntoNeighbors`][in] create iterators and use the same
6//! pattern that `IntoIterator` does: the trait takes a reference to a graph,
7//! and produces an iterator. These traits are quite composable, but with the
8//! limitation that they only use shared references to graphs.
9//!
10//! ### Graph Traversal
11//!
12//! [`Dfs`](struct.Dfs.html), [`Bfs`][bfs], [`DfsPostOrder`][dfspo] and
13//! [`Topo`][topo]  are basic visitors and they use “walker” methods: the
14//! visitors don't hold the graph as borrowed during traversal, only for the
15//! `.next()` call on the walker. They can be converted to iterators
16//! through the [`Walker`][w] trait.
17//!
18//! There is also the callback based traversal [`depth_first_search`][dfs].
19//!
20//! [bfs]: struct.Bfs.html
21//! [dfspo]: struct.DfsPostOrder.html
22//! [topo]: struct.Topo.html
23//! [dfs]: fn.depth_first_search.html
24//! [w]: trait.Walker.html
25//!
26//! ### Other Graph Traits
27//!
28//! The traits are rather loosely coupled at the moment (which is intentional,
29//! but will develop a bit), and there are traits missing that could be added.
30//!
31//! Not much is needed to be able to use the visitors on a graph. A graph
32//! needs to define [`GraphBase`][gb], [`IntoNeighbors`][in] and
33//! [`Visitable`][vis] as a minimum.
34//!
35//! [gb]: trait.GraphBase.html
36//! [in]: trait.IntoNeighbors.html
37//! [vis]: trait.Visitable.html
38//!
39
40// filter, reversed have their `mod` lines at the end,
41// so that they can use the trait template macros
42pub use self::filter::*;
43pub use self::reversed::*;
44
45#[macro_use]
46mod macros;
47
48mod dfsvisit;
49mod traversal;
50pub use self::dfsvisit::*;
51pub use self::traversal::*;
52
53use fixedbitset::FixedBitSet;
54
55#[cfg(feature = "std")]
56use std::{
57    collections::HashSet,
58    hash::{BuildHasher, Hash},
59};
60
61#[cfg(not(feature = "std"))]
62use core::hash::Hash;
63
64#[cfg(not(feature = "std"))]
65use alloc::collections::BTreeSet as HashSet;
66
67use super::{graph, EdgeType};
68use crate::graph::NodeIndex;
69
70#[cfg(feature = "graphmap")]
71use crate::prelude::GraphMap;
72
73#[cfg(feature = "stable_graph")]
74use crate::prelude::StableGraph;
75use crate::prelude::{Direction, Graph};
76
77use crate::csr::Csr;
78use crate::graph::Frozen;
79use crate::graph::IndexType;
80#[cfg(feature = "stable_graph")]
81use crate::stable_graph;
82#[cfg(feature = "matrix_graph")]
83use crate::matrix_graph::MatrixGraph;
84#[cfg(feature = "graphmap")]
85use crate::graphmap::{self, NodeTrait};
86
87trait_template! {
88/// Base graph trait: defines the associated node identifier and
89/// edge identifier types.
90pub trait GraphBase {
91    // FIXME: We can drop this escape/nodelegate stuff in Rust 1.18
92    @escape [type NodeId]
93    @escape [type EdgeId]
94    @section nodelegate
95    /// edge identifier
96    type EdgeId: Copy + PartialEq;
97    /// node identifier
98    type NodeId: Copy + PartialEq;
99}
100}
101
102GraphBase! {delegate_impl []}
103GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]}
104
105/// A copyable reference to a graph.
106pub trait GraphRef: Copy + GraphBase {}
107
108impl<'a, G> GraphRef for &'a G where G: GraphBase {}
109
110impl<'a, G> GraphBase for Frozen<'a, G>
111where
112    G: GraphBase,
113{
114    type NodeId = G::NodeId;
115    type EdgeId = G::EdgeId;
116}
117
118#[cfg(feature = "stable_graph")]
119impl<'a, N, E: 'a, Ty, Ix> IntoNeighbors for &'a StableGraph<N, E, Ty, Ix>
120where
121    Ty: EdgeType,
122    Ix: IndexType,
123{
124    type Neighbors = stable_graph::Neighbors<'a, E, Ix>;
125    fn neighbors(self, n: Self::NodeId) -> Self::Neighbors {
126        (*self).neighbors(n)
127    }
128}
129
130#[cfg(feature = "graphmap")]
131impl<'a, N: 'a, E, Ty> IntoNeighbors for &'a GraphMap<N, E, Ty>
132where
133    N: Copy + Ord + Hash,
134    Ty: EdgeType,
135{
136    type Neighbors = graphmap::Neighbors<'a, N, Ty>;
137    fn neighbors(self, n: Self::NodeId) -> Self::Neighbors {
138        self.neighbors(n)
139    }
140}
141
142trait_template! {
143/// Access to the neighbors of each node
144///
145/// The neighbors are, depending on the graph’s edge type:
146///
147/// - `Directed`: All targets of edges from `a`.
148/// - `Undirected`: All other endpoints of edges connected to `a`.
149pub trait IntoNeighbors : GraphRef {
150    @section type
151    type Neighbors: Iterator<Item=Self::NodeId>;
152    @section self
153    /// Return an iterator of the neighbors of node `a`.
154    fn neighbors(self: Self, a: Self::NodeId) -> Self::Neighbors;
155}
156}
157
158IntoNeighbors! {delegate_impl []}
159
160trait_template! {
161/// Access to the neighbors of each node, through incoming or outgoing edges.
162///
163/// Depending on the graph’s edge type, the neighbors of a given directionality
164/// are:
165///
166/// - `Directed`, `Outgoing`: All targets of edges from `a`.
167/// - `Directed`, `Incoming`: All sources of edges to `a`.
168/// - `Undirected`: All other endpoints of edges connected to `a`.
169pub trait IntoNeighborsDirected : IntoNeighbors {
170    @section type
171    type NeighborsDirected: Iterator<Item=Self::NodeId>;
172    @section self
173    fn neighbors_directed(self, n: Self::NodeId, d: Direction)
174        -> Self::NeighborsDirected;
175}
176}
177
178impl<'a, N, E: 'a, Ty, Ix> IntoNeighbors for &'a Graph<N, E, Ty, Ix>
179where
180    Ty: EdgeType,
181    Ix: IndexType,
182{
183    type Neighbors = graph::Neighbors<'a, E, Ix>;
184    fn neighbors(self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix> {
185        Graph::neighbors(self, n)
186    }
187}
188
189impl<'a, N, E: 'a, Ty, Ix> IntoNeighborsDirected for &'a Graph<N, E, Ty, Ix>
190where
191    Ty: EdgeType,
192    Ix: IndexType,
193{
194    type NeighborsDirected = graph::Neighbors<'a, E, Ix>;
195    fn neighbors_directed(
196        self,
197        n: graph::NodeIndex<Ix>,
198        d: Direction,
199    ) -> graph::Neighbors<'a, E, Ix> {
200        Graph::neighbors_directed(self, n, d)
201    }
202}
203
204#[cfg(feature = "stable_graph")]
205impl<'a, N, E: 'a, Ty, Ix> IntoNeighborsDirected for &'a StableGraph<N, E, Ty, Ix>
206where
207    Ty: EdgeType,
208    Ix: IndexType,
209{
210    type NeighborsDirected = stable_graph::Neighbors<'a, E, Ix>;
211    fn neighbors_directed(self, n: graph::NodeIndex<Ix>, d: Direction) -> Self::NeighborsDirected {
212        StableGraph::neighbors_directed(self, n, d)
213    }
214}
215
216#[cfg(feature = "graphmap")]
217impl<'a, N: 'a, E, Ty> IntoNeighborsDirected for &'a GraphMap<N, E, Ty>
218where
219    N: Copy + Ord + Hash,
220    Ty: EdgeType,
221{
222    type NeighborsDirected = graphmap::NeighborsDirected<'a, N, Ty>;
223    fn neighbors_directed(self, n: N, dir: Direction) -> Self::NeighborsDirected {
224        self.neighbors_directed(n, dir)
225    }
226}
227
228trait_template! {
229/// Access to the edges of each node.
230///
231/// The edges are, depending on the graph’s edge type:
232///
233/// - `Directed`: All edges from `a`.
234/// - `Undirected`: All edges connected to `a`.
235///
236/// This is an extended version of the trait `IntoNeighbors`; the former
237/// only iterates over the target node identifiers, while this trait
238/// yields edge references (trait [`EdgeRef`][er]).
239///
240/// [er]: trait.EdgeRef.html
241pub trait IntoEdges : IntoEdgeReferences + IntoNeighbors {
242    @section type
243    type Edges: Iterator<Item=Self::EdgeRef>;
244    @section self
245    fn edges(self, a: Self::NodeId) -> Self::Edges;
246}
247}
248
249IntoEdges! {delegate_impl []}
250
251trait_template! {
252/// Access to all edges of each node, in the specified direction.
253///
254/// The edges are, depending on the direction and the graph’s edge type:
255///
256///
257/// - `Directed`, `Outgoing`: All edges from `a`.
258/// - `Directed`, `Incoming`: All edges to `a`.
259/// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each edge.
260/// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each edge.
261///
262/// This is an extended version of the trait `IntoNeighborsDirected`; the former
263/// only iterates over the target node identifiers, while this trait
264/// yields edge references (trait [`EdgeRef`][er]).
265///
266/// [er]: trait.EdgeRef.html
267pub trait IntoEdgesDirected : IntoEdges + IntoNeighborsDirected {
268    @section type
269    type EdgesDirected: Iterator<Item=Self::EdgeRef>;
270    @section self
271    fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected;
272}
273}
274
275IntoEdgesDirected! {delegate_impl []}
276
277trait_template! {
278/// Access to the sequence of the graph’s `NodeId`s.
279pub trait IntoNodeIdentifiers : GraphRef {
280    @section type
281    type NodeIdentifiers: Iterator<Item=Self::NodeId>;
282    @section self
283    fn node_identifiers(self) -> Self::NodeIdentifiers;
284}
285}
286
287IntoNodeIdentifiers! {delegate_impl []}
288
289impl<'a, N, E: 'a, Ty, Ix> IntoNodeIdentifiers for &'a Graph<N, E, Ty, Ix>
290where
291    Ty: EdgeType,
292    Ix: IndexType,
293{
294    type NodeIdentifiers = graph::NodeIndices<Ix>;
295    fn node_identifiers(self) -> graph::NodeIndices<Ix> {
296        Graph::node_indices(self)
297    }
298}
299
300impl<N, E, Ty, Ix> NodeCount for Graph<N, E, Ty, Ix>
301where
302    Ty: EdgeType,
303    Ix: IndexType,
304{
305    fn node_count(&self) -> usize {
306        self.node_count()
307    }
308}
309
310#[cfg(feature = "stable_graph")]
311impl<'a, N, E: 'a, Ty, Ix> IntoNodeIdentifiers for &'a StableGraph<N, E, Ty, Ix>
312where
313    Ty: EdgeType,
314    Ix: IndexType,
315{
316    type NodeIdentifiers = stable_graph::NodeIndices<'a, N, Ix>;
317    fn node_identifiers(self) -> Self::NodeIdentifiers {
318        StableGraph::node_indices(self)
319    }
320}
321
322#[cfg(feature = "stable_graph")]
323impl<N, E, Ty, Ix> NodeCount for StableGraph<N, E, Ty, Ix>
324where
325    Ty: EdgeType,
326    Ix: IndexType,
327{
328    fn node_count(&self) -> usize {
329        self.node_count()
330    }
331}
332
333IntoNeighborsDirected! {delegate_impl []}
334
335trait_template! {
336/// Define associated data for nodes and edges
337pub trait Data : GraphBase {
338    @section type
339    type NodeWeight;
340    type EdgeWeight;
341}
342}
343
344Data! {delegate_impl []}
345Data! {delegate_impl [['a, G], G, &'a mut G, deref]}
346
347/// An edge reference.
348///
349/// Edge references are used by traits `IntoEdges` and `IntoEdgeReferences`.
350pub trait EdgeRef: Copy {
351    type NodeId;
352    type EdgeId;
353    type Weight;
354    /// The source node of the edge.
355    fn source(&self) -> Self::NodeId;
356    /// The target node of the edge.
357    fn target(&self) -> Self::NodeId;
358    /// A reference to the weight of the edge.
359    fn weight(&self) -> &Self::Weight;
360    /// The edge’s identifier.
361    fn id(&self) -> Self::EdgeId;
362}
363
364impl<'a, N, E> EdgeRef for (N, N, &'a E)
365where
366    N: Copy,
367{
368    type NodeId = N;
369    type EdgeId = (N, N);
370    type Weight = E;
371
372    fn source(&self) -> N {
373        self.0
374    }
375    fn target(&self) -> N {
376        self.1
377    }
378    fn weight(&self) -> &E {
379        self.2
380    }
381    fn id(&self) -> (N, N) {
382        (self.0, self.1)
383    }
384}
385
386/// A node reference.
387pub trait NodeRef: Copy {
388    type NodeId;
389    type Weight;
390    fn id(&self) -> Self::NodeId;
391    fn weight(&self) -> &Self::Weight;
392}
393
394trait_template! {
395/// Access to the sequence of the graph’s nodes
396pub trait IntoNodeReferences : Data + IntoNodeIdentifiers {
397    @section type
398    type NodeRef: NodeRef<NodeId=Self::NodeId, Weight=Self::NodeWeight>;
399    type NodeReferences: Iterator<Item=Self::NodeRef>;
400    @section self
401    fn node_references(self) -> Self::NodeReferences;
402}
403}
404
405IntoNodeReferences! {delegate_impl []}
406
407impl<Id> NodeRef for (Id, ())
408where
409    Id: Copy,
410{
411    type NodeId = Id;
412    type Weight = ();
413    fn id(&self) -> Self::NodeId {
414        self.0
415    }
416    fn weight(&self) -> &Self::Weight {
417        static DUMMY: () = ();
418        &DUMMY
419    }
420}
421
422impl<'a, Id, W> NodeRef for (Id, &'a W)
423where
424    Id: Copy,
425{
426    type NodeId = Id;
427    type Weight = W;
428    fn id(&self) -> Self::NodeId {
429        self.0
430    }
431    fn weight(&self) -> &Self::Weight {
432        self.1
433    }
434}
435
436trait_template! {
437/// Access to the sequence of the graph’s edges
438pub trait IntoEdgeReferences : Data + GraphRef {
439    @section type
440    type EdgeRef: EdgeRef<NodeId=Self::NodeId, EdgeId=Self::EdgeId,
441                          Weight=Self::EdgeWeight>;
442    type EdgeReferences: Iterator<Item=Self::EdgeRef>;
443    @section self
444    fn edge_references(self) -> Self::EdgeReferences;
445}
446}
447
448IntoEdgeReferences! {delegate_impl [] }
449
450#[cfg(feature = "graphmap")]
451impl<N, E, Ty> Data for GraphMap<N, E, Ty>
452where
453    N: Copy + PartialEq,
454    Ty: EdgeType,
455{
456    type NodeWeight = N;
457    type EdgeWeight = E;
458}
459
460trait_template! {
461    /// Edge kind property (directed or undirected edges)
462pub trait GraphProp : GraphBase {
463    @section type
464    /// The kind edges in the graph.
465    type EdgeType: EdgeType;
466
467    @section nodelegate
468    fn is_directed(&self) -> bool {
469        <Self::EdgeType>::is_directed()
470    }
471}
472}
473
474GraphProp! {delegate_impl []}
475
476impl<N, E, Ty, Ix> GraphProp for Graph<N, E, Ty, Ix>
477where
478    Ty: EdgeType,
479    Ix: IndexType,
480{
481    type EdgeType = Ty;
482}
483
484#[cfg(feature = "stable_graph")]
485impl<N, E, Ty, Ix> GraphProp for StableGraph<N, E, Ty, Ix>
486where
487    Ty: EdgeType,
488    Ix: IndexType,
489{
490    type EdgeType = Ty;
491}
492
493#[cfg(feature = "graphmap")]
494impl<N, E, Ty> GraphProp for GraphMap<N, E, Ty>
495where
496    N: NodeTrait,
497    Ty: EdgeType,
498{
499    type EdgeType = Ty;
500}
501
502impl<'a, N: 'a, E: 'a, Ty, Ix> IntoEdgeReferences for &'a Graph<N, E, Ty, Ix>
503where
504    Ty: EdgeType,
505    Ix: IndexType,
506{
507    type EdgeRef = graph::EdgeReference<'a, E, Ix>;
508    type EdgeReferences = graph::EdgeReferences<'a, E, Ix>;
509    fn edge_references(self) -> Self::EdgeReferences {
510        (*self).edge_references()
511    }
512}
513
514trait_template! {
515    /// The graph’s `NodeId`s map to indices
516    pub trait NodeIndexable : GraphBase {
517        @section self
518        /// Return an upper bound of the node indices in the graph
519        /// (suitable for the size of a bitmap).
520        fn node_bound(self: &Self) -> usize;
521        /// Convert `a` to an integer index.
522        fn to_index(self: &Self, a: Self::NodeId) -> usize;
523        /// Convert `i` to a node index
524        fn from_index(self: &Self, i: usize) -> Self::NodeId;
525    }
526}
527
528NodeIndexable! {delegate_impl []}
529
530trait_template! {
531/// A graph with a known node count.
532pub trait NodeCount : GraphBase {
533    @section self
534    fn node_count(self: &Self) -> usize;
535}
536}
537
538NodeCount! {delegate_impl []}
539
540trait_template! {
541/// The graph’s `NodeId`s map to indices, in a range without holes.
542///
543/// The graph's node identifiers correspond to exactly the indices
544/// `0..self.node_bound()`.
545pub trait NodeCompactIndexable : NodeIndexable + NodeCount { }
546}
547
548NodeCompactIndexable! {delegate_impl []}
549
550impl<N, E, Ty, Ix> NodeIndexable for Graph<N, E, Ty, Ix>
551where
552    Ty: EdgeType,
553    Ix: IndexType,
554{
555    #[inline]
556    fn node_bound(&self) -> usize {
557        self.node_count()
558    }
559    #[inline]
560    fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
561        ix.index()
562    }
563    #[inline]
564    fn from_index(&self, ix: usize) -> Self::NodeId {
565        NodeIndex::new(ix)
566    }
567}
568
569impl<N, E, Ty, Ix> NodeCompactIndexable for Graph<N, E, Ty, Ix>
570where
571    Ty: EdgeType,
572    Ix: IndexType,
573{
574}
575
576/// A mapping for storing the visited status for NodeId `N`.
577pub trait VisitMap<N> {
578    /// Mark `a` as visited.
579    ///
580    /// Return **true** if this is the first visit, false otherwise.
581    fn visit(&mut self, a: N) -> bool;
582
583    /// Return whether `a` has been visited before.
584    fn is_visited(&self, a: &N) -> bool;
585}
586
587impl<Ix> VisitMap<Ix> for FixedBitSet
588where
589    Ix: IndexType,
590{
591    fn visit(&mut self, x: Ix) -> bool {
592        !self.put(x.index())
593    }
594    fn is_visited(&self, x: &Ix) -> bool {
595        self.contains(x.index())
596    }
597}
598
599#[cfg(feature = "std")]
600impl<N, S> VisitMap<N> for HashSet<N, S>
601where
602    N: Hash + Eq,
603    S: BuildHasher,
604{
605    fn visit(&mut self, x: N) -> bool {
606        self.insert(x)
607    }
608    fn is_visited(&self, x: &N) -> bool {
609        self.contains(x)
610    }
611}
612
613#[cfg(not(feature = "std"))]
614impl<N> VisitMap<N> for HashSet<N>
615where
616    N: Ord + Eq,
617{
618    fn visit(&mut self, x: N) -> bool {
619        self.insert(x)
620    }
621    fn is_visited(&self, x: &N) -> bool {
622        self.contains(x)
623    }
624}
625
626trait_template! {
627/// A graph that can create a map that tracks the visited status of its nodes.
628pub trait Visitable : GraphBase {
629    @section type
630    /// The associated map type
631    type Map: VisitMap<Self::NodeId>;
632    @section self
633    /// Create a new visitor map
634    fn visit_map(self: &Self) -> Self::Map;
635    /// Reset the visitor map (and resize to new size of graph if needed)
636    fn reset_map(self: &Self, map: &mut Self::Map);
637}
638}
639Visitable! {delegate_impl []}
640
641impl<N, E, Ty, Ix> GraphBase for Graph<N, E, Ty, Ix>
642where
643    Ix: IndexType,
644{
645    type NodeId = graph::NodeIndex<Ix>;
646    type EdgeId = graph::EdgeIndex<Ix>;
647}
648
649impl<N, E, Ty, Ix> Visitable for Graph<N, E, Ty, Ix>
650where
651    Ty: EdgeType,
652    Ix: IndexType,
653{
654    type Map = FixedBitSet;
655    fn visit_map(&self) -> FixedBitSet {
656        FixedBitSet::with_capacity(self.node_count())
657    }
658
659    fn reset_map(&self, map: &mut Self::Map) {
660        map.clear();
661        map.grow(self.node_count());
662    }
663}
664
665#[cfg(feature = "stable_graph")]
666impl<N, E, Ty, Ix> GraphBase for StableGraph<N, E, Ty, Ix>
667where
668    Ix: IndexType,
669{
670    type NodeId = graph::NodeIndex<Ix>;
671    type EdgeId = graph::EdgeIndex<Ix>;
672}
673
674#[cfg(feature = "stable_graph")]
675impl<N, E, Ty, Ix> Visitable for StableGraph<N, E, Ty, Ix>
676where
677    Ty: EdgeType,
678    Ix: IndexType,
679{
680    type Map = FixedBitSet;
681    fn visit_map(&self) -> FixedBitSet {
682        FixedBitSet::with_capacity(self.node_bound())
683    }
684    fn reset_map(&self, map: &mut Self::Map) {
685        map.clear();
686        map.grow(self.node_bound());
687    }
688}
689
690#[cfg(feature = "stable_graph")]
691impl<N, E, Ty, Ix> Data for StableGraph<N, E, Ty, Ix>
692where
693    Ty: EdgeType,
694    Ix: IndexType,
695{
696    type NodeWeight = N;
697    type EdgeWeight = E;
698}
699
700#[cfg(feature = "graphmap")]
701impl<N, E, Ty> GraphBase for GraphMap<N, E, Ty>
702where
703    N: Copy + PartialEq,
704{
705    type NodeId = N;
706    type EdgeId = (N, N);
707}
708
709#[cfg(feature = "graphmap")]
710impl<N, E, Ty> Visitable for GraphMap<N, E, Ty>
711where
712    N: Copy + Ord + Hash,
713    Ty: EdgeType,
714{
715    type Map = HashSet<N>;
716    fn visit_map(&self) -> HashSet<N> {
717        HashSet::new()
718    }
719    fn reset_map(&self, map: &mut Self::Map) {
720        map.clear();
721    }
722}
723
724trait_template! {
725/// Create or access the adjacency matrix of a graph.
726///
727/// The implementor can either create an adjacency matrix, or it can return
728/// a placeholder if it has the needed representation internally.
729pub trait GetAdjacencyMatrix : GraphBase {
730    @section type
731    /// The associated adjacency matrix type
732    type AdjMatrix;
733    @section self
734    /// Create the adjacency matrix
735    fn adjacency_matrix(self: &Self) -> Self::AdjMatrix;
736    /// Return true if there is an edge from `a` to `b`, false otherwise.
737    ///
738    /// Computes in O(1) time.
739    fn is_adjacent(self: &Self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
740}
741}
742
743GetAdjacencyMatrix! {delegate_impl []}
744
745#[cfg(feature = "graphmap")]
746/// The `GraphMap` keeps an adjacency matrix internally.
747impl<N, E, Ty> GetAdjacencyMatrix for GraphMap<N, E, Ty>
748where
749    N: Copy + Ord + Hash,
750    Ty: EdgeType,
751{
752    type AdjMatrix = ();
753    #[inline]
754    fn adjacency_matrix(&self) {}
755    #[inline]
756    fn is_adjacent(&self, _: &(), a: N, b: N) -> bool {
757        self.contains_edge(a, b)
758    }
759}
760
761trait_template! {
762/// A graph with a known edge count.
763pub trait EdgeCount : GraphBase {
764    @section self
765    /// Return the number of edges in the graph.
766    fn edge_count(self: &Self) -> usize;
767}
768}
769
770EdgeCount! {delegate_impl []}
771
772impl<N, E, Ty, Ix> EdgeCount for Graph<N, E, Ty, Ix>
773where
774    Ty: EdgeType,
775    Ix: IndexType,
776{
777    #[inline]
778    fn edge_count(&self) -> usize {
779        self.edge_count()
780    }
781}
782
783#[cfg(feature = "stable_graph")]
784impl<N, E, Ty, Ix> EdgeCount for StableGraph<N, E, Ty, Ix>
785where
786    Ty: EdgeType,
787    Ix: IndexType,
788{
789    #[inline]
790    fn edge_count(&self) -> usize {
791        self.edge_count()
792    }
793}
794
795#[cfg(feature = "graphmap")]
796impl<N, E, Ty> EdgeCount for GraphMap<N, E, Ty>
797where
798    N: NodeTrait,
799    Ty: EdgeType,
800{
801    #[inline]
802    fn edge_count(&self) -> usize {
803        self.edge_count()
804    }
805}
806
807#[cfg(feature = "matrix_graph")]
808impl<N, E, Ty> EdgeCount for MatrixGraph<N, E, Ty>
809where
810    N: NodeTrait,
811    Ty: EdgeType,
812{
813    #[inline]
814    fn edge_count(&self) -> usize {
815        self.edge_count()
816    }
817}
818
819impl<N, E, Ty, Ix> EdgeCount for Csr<N, E, Ty, Ix>
820where
821    Ty: EdgeType,
822    Ix: IndexType,
823{
824    #[inline]
825    fn edge_count(&self) -> usize {
826        self.edge_count()
827    }
828}
829
830mod filter;
831mod reversed;