From b591e4ea35e6bb8f00ae17a9f093094238de1b3d Mon Sep 17 00:00:00 2001 From: Bas Dirks Date: Sun, 28 Jul 2024 22:25:55 +0200 Subject: [PATCH] release: 0.75.3 Added - Add the `Sources` trait. - Add property test `biclique_sources` for `adjacency_list`. - Add property test `biclique_sources` for `adjacency_matrix`. - Add property test `circuit_sources` for `adjacency_list`. - Add property test `circuit_sources` for `adjacency_matrix`. - Add property test `complete_sources` for `adjacency_list`. - Add property test `complete_sources` for `adjacency_matrix`. - Add property test `cycle_sources` for `adjacency_list`. - Add property test `cycle_sources` for `adjacency_matrix`. - Add property test `empty_sources` for `adjacency_list`. - Add property test `empty_sources` for `adjacency_matrix`. - Add property test `path_sources` for `adjacency_list`. - Add property test `path_sources` for `adjacency_matrix`. - Add property test `random_tournament_sources` for `adjacency_list`. - Add property test `random_tournament_sources` for `adjacency_matrix`. - Add property test `star_sources` for `adjacency_list`. - Add property test `star_sources` for `adjacency_matrix`. - Add unit test `sources_bang_jensen_196` for `adjacency_list`. - Add unit test `sources_bang_jensen_196` for `adjacency_matrix`. - Add unit test `sources_bang_jensen_34` for `adjacency_list`. - Add unit test `sources_bang_jensen_34` for `adjacency_matrix`. - Add unit test `sources_bang_jensen_94` for `adjacency_list`. - Add unit test `sources_bang_jensen_94` for `adjacency_matrix`. - Add unit test `sources_kattis_builddeps` for `adjacency_list`. - Add unit test `sources_kattis_builddeps` for `adjacency_matrix`. - Add unit test `sources_kattis_cantinaofbabel_1` for `adjacency_list`. - Add unit test `sources_kattis_cantinaofbabel_1` for `adjacency_matrix`. - Add unit test `sources_kattis_cantinaofbabel_2` for `adjacency_list`. - Add unit test `sources_kattis_cantinaofbabel_2` for `adjacency_matrix`. - Add unit test `sources_kattis_escapewallmaria_1` for `adjacency_list`. - Add unit test `sources_kattis_escapewallmaria_1` for `adjacency_matrix`. - Add unit test `sources_kattis_escapewallmaria_2` for `adjacency_list`. - Add unit test `sources_kattis_escapewallmaria_2` for `adjacency_matrix`. - Add unit test `sources_kattis_escapewallmaria_3` for `adjacency_list`. - Add unit test `sources_kattis_escapewallmaria_3` for `adjacency_matrix`. --- CHANGELOG.md | 41 ++++++++++- Cargo.toml | 2 +- README.md | 4 +- src/adjacency_list/digraph.rs | 102 ++++++++++++++++++++++++++ src/adjacency_list/fixture.rs | 60 ++++++++-------- src/adjacency_matrix/digraph.rs | 102 ++++++++++++++++++++++++++ src/adjacency_matrix/fixture.rs | 60 ++++++++-------- src/lib.rs | 1 + src/op/mod.rs | 2 + src/op/sources.rs | 123 ++++++++++++++++++++++++++++++++ 10 files changed, 434 insertions(+), 63 deletions(-) create mode 100644 src/op/sources.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e49bb9a..fe71ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,6 @@ - Add the `MinIndegree` trait. - Add the `MinOutdegree` trait. - Add the `MinSemidegree` trait. -- Add the `Sources` trait. - Benchmark against popular graph libraries in other languages. - Benchmark trait implementations. - Implement `Debug` for `adjacency_list::Digraph` to show arcs. @@ -25,6 +24,46 @@ - Implement `Debug` for `adjacency_matrix::Digraph` to show arcs. - Subsume traits with one super trait into the super trait? +## [0.75.3] - 2024-07-28 + +Added + +- Add the `Sources` trait. +- Add property test `biclique_sources` for `adjacency_list`. +- Add property test `biclique_sources` for `adjacency_matrix`. +- Add property test `circuit_sources` for `adjacency_list`. +- Add property test `circuit_sources` for `adjacency_matrix`. +- Add property test `complete_sources` for `adjacency_list`. +- Add property test `complete_sources` for `adjacency_matrix`. +- Add property test `cycle_sources` for `adjacency_list`. +- Add property test `cycle_sources` for `adjacency_matrix`. +- Add property test `empty_sources` for `adjacency_list`. +- Add property test `empty_sources` for `adjacency_matrix`. +- Add property test `path_sources` for `adjacency_list`. +- Add property test `path_sources` for `adjacency_matrix`. +- Add property test `random_tournament_sources` for `adjacency_list`. +- Add property test `random_tournament_sources` for `adjacency_matrix`. +- Add property test `star_sources` for `adjacency_list`. +- Add property test `star_sources` for `adjacency_matrix`. +- Add unit test `sources_bang_jensen_196` for `adjacency_list`. +- Add unit test `sources_bang_jensen_196` for `adjacency_matrix`. +- Add unit test `sources_bang_jensen_34` for `adjacency_list`. +- Add unit test `sources_bang_jensen_34` for `adjacency_matrix`. +- Add unit test `sources_bang_jensen_94` for `adjacency_list`. +- Add unit test `sources_bang_jensen_94` for `adjacency_matrix`. +- Add unit test `sources_kattis_builddeps` for `adjacency_list`. +- Add unit test `sources_kattis_builddeps` for `adjacency_matrix`. +- Add unit test `sources_kattis_cantinaofbabel_1` for `adjacency_list`. +- Add unit test `sources_kattis_cantinaofbabel_1` for `adjacency_matrix`. +- Add unit test `sources_kattis_cantinaofbabel_2` for `adjacency_list`. +- Add unit test `sources_kattis_cantinaofbabel_2` for `adjacency_matrix`. +- Add unit test `sources_kattis_escapewallmaria_1` for `adjacency_list`. +- Add unit test `sources_kattis_escapewallmaria_1` for `adjacency_matrix`. +- Add unit test `sources_kattis_escapewallmaria_2` for `adjacency_list`. +- Add unit test `sources_kattis_escapewallmaria_2` for `adjacency_matrix`. +- Add unit test `sources_kattis_escapewallmaria_3` for `adjacency_list`. +- Add unit test `sources_kattis_escapewallmaria_3` for `adjacency_matrix`. + ## [0.75.2] - 2024-07-28 Added diff --git a/Cargo.toml b/Cargo.toml index 0dcb900..5221cf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "graaf" -version = "0.75.2" +version = "0.75.3" edition = "2021" authors = ["Bas Dirks "] categories = ["algorithms", "data-structures", "mathematics"] diff --git a/README.md b/README.md index a4ecb55..f30e1e0 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Add the following to your `Cargo.toml`: ```toml [dependencies] -graaf = "0.75.2" +graaf = "0.75.3" ``` ## Digraph Types @@ -107,6 +107,7 @@ The extended traits derive their implementation from the basic operations. - [`OutdegreeSequence`] returns the outdegree sequence of a digraph. - [`SemidegreeSequence`] returns the semidegree sequence of a digraph. - [`Sinks`] returns the sinks in a digraph. +- [`Sources`] returns the sources in a digraph. ## Algorithms @@ -241,6 +242,7 @@ A distance matrix contains the shortest distances between all pairs of vertices [`SemidegreeSequence`]: https://docs.rs/graaf/latest/graaf/op/semidegree_sequence/trait.SemidegreeSequence.html [`Sinks`]: https://docs.rs/graaf/latest/graaf/op/sinks/trait.Sinks.html [`Size`]: https://docs.rs/graaf/latest/graaf/op/size/trait.Size.html +[`Sources`]: https://docs.rs/graaf/latest/graaf/op/sources/trait.Sources.html [`Star`]: https://docs.rs/graaf/latest/graaf/gen/star/trait.Star.html [`Vertices`]: https://docs.rs/graaf/latest/graaf/op/vertices/trait.Vertices.html [`algo`]: https://docs.rs/graaf/latest/graaf/algo/index.html diff --git a/src/adjacency_list/digraph.rs b/src/adjacency_list/digraph.rs index ec2b4e0..602388d 100644 --- a/src/adjacency_list/digraph.rs +++ b/src/adjacency_list/digraph.rs @@ -279,6 +279,7 @@ mod tests { OutdegreeSequence, SemidegreeSequence, Sinks, + Sources, }, proptest_strategy::arc, r#gen::Path, @@ -622,6 +623,11 @@ mod tests { assert_eq!(Digraph::biclique(m, n).size(), m * n * 2); } + #[test] + fn biclique_sources(m in 1..25_usize, n in 1..25_usize) { + assert!(Digraph::biclique(m, n).sources().eq([])); + } + #[test] fn circuit_complement_size(order in 1..25_usize) { assert_eq!( @@ -825,6 +831,14 @@ mod tests { ); } + #[test] + fn circuit_sources(order in 1..25_usize) { + let digraph = Digraph::circuit(order); + let sources = digraph.sources(); + + assert!(if order == 1 { sources.eq([0]) } else { sources.eq([]) }); + } + #[test] fn complete_complement_equals_empty(order in 1..25_usize) { assert_eq!( @@ -1021,6 +1035,15 @@ mod tests { assert_eq!(Digraph::complete(order).size(), order * (order - 1)); } + #[test] + fn complete_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::complete(order).sources().eq([0]) + } else { + Digraph::complete(order).sources().eq([]) + }); + } + #[test] fn cycle_complement_size(order in 1..25_usize) { assert_eq!( @@ -1241,6 +1264,15 @@ mod tests { ); } + #[test] + fn cycle_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::cycle(order).sources().eq([0]) + } else { + Digraph::cycle(order).sources().eq([]) + }); + } + #[test] fn empty_arcs(order in 1..25_usize) { assert!(Digraph::empty(order).arcs().eq([])); @@ -1443,6 +1475,11 @@ mod tests { assert_eq!(Digraph::empty(order).size(), 0); } + #[test] + fn empty_sources(order in 1..25_usize) { + assert!(Digraph::empty(order).sources().eq(0..order)); + } + #[test] fn has_arc_out_of_bounds(order in 1..25_usize) { let digraph = Digraph::empty(order); @@ -1667,6 +1704,11 @@ mod tests { assert_eq!(Digraph::path(order).size(), order - 1); } + #[test] + fn path_sources(order in 1..25_usize) { + assert!(Digraph::path(order).sources().eq([0])); + } + #[test] fn random_tournament_complement_size(order in 1..25_usize) { assert_eq!( @@ -2056,6 +2098,15 @@ mod tests { fn star_size(order in 1..25_usize) { assert_eq!(Digraph::star(order).size(), (order - 1) * 2); } + + #[test] + fn star_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::star(order).sources().eq([0]) + } else { + Digraph::star(order).sources().eq([]) + }); + } } #[test] @@ -5602,6 +5653,57 @@ mod tests { assert_eq!(kattis_escapewallmaria_3().size(), 14); } + #[test] + fn sources_bang_jensen_196() { + assert!(bang_jensen_196().sources().eq([])); + } + + #[test] + fn sources_bang_jensen_34() { + assert!(bang_jensen_34().sources().eq([2])); + } + + #[test] + fn sources_bang_jensen_94() { + assert!(bang_jensen_94().sources().eq([0])); + } + + #[test] + fn sources_kattis_builddeps() { + assert!(kattis_builddeps().sources().eq([0, 2])); + } + + #[test] + fn sources_kattis_cantinaofbabel_1() { + assert!(kattis_cantinaofbabel_1().sources().eq([8])); + } + + #[test] + fn sources_kattis_cantinaofbabel_2() { + assert!(kattis_cantinaofbabel_2().sources().eq([])); + } + + #[test] + fn sources_kattis_escapewallmaria_1() { + assert!(kattis_escapewallmaria_1() + .sources() + .eq([0, 1, 2, 3, 4, 7, 8, 10, 11])); + } + + #[test] + fn sources_kattis_escapewallmaria_2() { + assert!(kattis_escapewallmaria_2() + .sources() + .eq([0, 1, 2, 3, 4, 7, 8, 10, 11])); + } + + #[test] + fn sources_kattis_escapewallmaria_3() { + assert!(kattis_escapewallmaria_3() + .sources() + .eq([0, 3, 4, 7, 8, 10, 11])); + } + #[test] fn star_1() { assert!(Digraph::star(1).arcs().eq([])); diff --git a/src/adjacency_list/fixture.rs b/src/adjacency_list/fixture.rs index 4b7fe33..505f6e1 100644 --- a/src/adjacency_list/fixture.rs +++ b/src/adjacency_list/fixture.rs @@ -238,16 +238,16 @@ pub fn kattis_cantinaofbabel_2() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {} -/// 2 -> {} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {6, 9} -/// 6 -> {5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5, 13} +/// 0 -> {} +/// 1 -> {} +/// 2 -> {} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {6, 9} +/// 6 -> {5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5, 13} /// 10 -> {} /// 11 -> {} /// 12 -> {} @@ -277,16 +277,16 @@ pub fn kattis_escapewallmaria_1() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {} -/// 2 -> {} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {6, 9} -/// 6 -> {5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5} +/// 0 -> {} +/// 1 -> {} +/// 2 -> {} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {6, 9} +/// 6 -> {5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5} /// 10 -> {} /// 11 -> {} /// 12 -> {13} @@ -316,16 +316,16 @@ pub fn kattis_escapewallmaria_2() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {2, 5} -/// 2 -> {1, 6} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {1, 6, 9} -/// 6 -> {2, 5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5, 13} +/// 0 -> {} +/// 1 -> {2, 5} +/// 2 -> {1, 6} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {1, 6, 9} +/// 6 -> {2, 5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5, 13} /// 10 -> {} /// 11 -> {} /// 12 -> {13} diff --git a/src/adjacency_matrix/digraph.rs b/src/adjacency_matrix/digraph.rs index d5015fd..e393bc5 100644 --- a/src/adjacency_matrix/digraph.rs +++ b/src/adjacency_matrix/digraph.rs @@ -376,6 +376,7 @@ mod tests { OutdegreeSequence, SemidegreeSequence, Sinks, + Sources, }, proptest_strategy::arc, r#gen::Path, @@ -724,6 +725,11 @@ mod tests { assert_eq!(Digraph::biclique(m, n).size(), m * n * 2); } + #[test] + fn biclique_sources(m in 1..25_usize, n in 1..25_usize) { + assert!(Digraph::biclique(m, n).sources().eq([])); + } + #[test] fn circuit_complement_size(order in 1..25_usize) { assert_eq!( @@ -927,6 +933,14 @@ mod tests { ); } + #[test] + fn circuit_sources(order in 1..25_usize) { + let digraph = Digraph::circuit(order); + let sources = digraph.sources(); + + assert!(if order == 1 { sources.eq([0]) } else { sources.eq([]) }); + } + #[test] fn complete_complement_equals_empty(order in 1..25_usize) { assert_eq!( @@ -1123,6 +1137,15 @@ mod tests { assert_eq!(Digraph::complete(order).size(), order * (order - 1)); } + #[test] + fn complete_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::complete(order).sources().eq([0]) + } else { + Digraph::complete(order).sources().eq([]) + }); + } + #[test] fn cycle_complement_size(order in 1..25_usize) { assert_eq!( @@ -1343,6 +1366,15 @@ mod tests { ); } + #[test] + fn cycle_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::cycle(order).sources().eq([0]) + } else { + Digraph::cycle(order).sources().eq([]) + }); + } + #[test] fn empty_arcs(order in 1..25_usize) { assert!(Digraph::empty(order).arcs().eq([])); @@ -1545,6 +1577,11 @@ mod tests { assert_eq!(Digraph::empty(order).size(), 0); } + #[test] + fn empty_sources(order in 1..25_usize) { + assert!(Digraph::empty(order).sources().eq(0..order)); + } + #[test] fn has_arc_out_of_bounds(order in 1..25_usize) { let digraph = Digraph::empty(order); @@ -1769,6 +1806,11 @@ mod tests { assert_eq!(Digraph::path(order).size(), order - 1); } + #[test] + fn path_sources(order in 1..25_usize) { + assert!(Digraph::path(order).sources().eq([0])); + } + #[test] fn random_tournament_complement_size(order in 1..25_usize) { assert_eq!( @@ -2158,6 +2200,15 @@ mod tests { fn star_size(order in 1..25_usize) { assert_eq!(Digraph::star(order).size(), (order - 1) * 2); } + + #[test] + fn star_sources(order in 1..25_usize) { + assert!(if order == 1 { + Digraph::star(order).sources().eq([0]) + } else { + Digraph::star(order).sources().eq([]) + }); + } } #[test] @@ -5704,6 +5755,57 @@ mod tests { assert_eq!(kattis_escapewallmaria_3().size(), 14); } + #[test] + fn sources_bang_jensen_196() { + assert!(bang_jensen_196().sources().eq([])); + } + + #[test] + fn sources_bang_jensen_34() { + assert!(bang_jensen_34().sources().eq([2])); + } + + #[test] + fn sources_bang_jensen_94() { + assert!(bang_jensen_94().sources().eq([0])); + } + + #[test] + fn sources_kattis_builddeps() { + assert!(kattis_builddeps().sources().eq([0, 2])); + } + + #[test] + fn sources_kattis_cantinaofbabel_1() { + assert!(kattis_cantinaofbabel_1().sources().eq([8])); + } + + #[test] + fn sources_kattis_cantinaofbabel_2() { + assert!(kattis_cantinaofbabel_2().sources().eq([])); + } + + #[test] + fn sources_kattis_escapewallmaria_1() { + assert!(kattis_escapewallmaria_1() + .sources() + .eq([0, 1, 2, 3, 4, 7, 8, 10, 11])); + } + + #[test] + fn sources_kattis_escapewallmaria_2() { + assert!(kattis_escapewallmaria_2() + .sources() + .eq([0, 1, 2, 3, 4, 7, 8, 10, 11])); + } + + #[test] + fn sources_kattis_escapewallmaria_3() { + assert!(kattis_escapewallmaria_3() + .sources() + .eq([0, 3, 4, 7, 8, 10, 11])); + } + #[test] fn star_1() { assert!(Digraph::star(1).arcs().eq([])); diff --git a/src/adjacency_matrix/fixture.rs b/src/adjacency_matrix/fixture.rs index e146b2b..bf77d49 100644 --- a/src/adjacency_matrix/fixture.rs +++ b/src/adjacency_matrix/fixture.rs @@ -69,16 +69,16 @@ pub fn kattis_builddeps() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {} -/// 2 -> {} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {6, 9} -/// 6 -> {5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5, 13} +/// 0 -> {} +/// 1 -> {} +/// 2 -> {} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {6, 9} +/// 6 -> {5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5, 13} /// 10 -> {} /// 11 -> {} /// 12 -> {} @@ -93,16 +93,16 @@ pub fn kattis_escapewallmaria_1() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {} -/// 2 -> {} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {6, 9} -/// 6 -> {5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5} +/// 0 -> {} +/// 1 -> {} +/// 2 -> {} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {6, 9} +/// 6 -> {5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5} /// 10 -> {} /// 11 -> {} /// 12 -> {13} @@ -117,16 +117,16 @@ pub fn kattis_escapewallmaria_2() -> Digraph { /// /// /// ```text -/// 0 -> {} -/// 1 -> {2, 5} -/// 2 -> {1, 6} -/// 3 -> {} -/// 4 -> {} -/// 5 -> {1, 6, 9} -/// 6 -> {2, 5} -/// 7 -> {} -/// 8 -> {} -/// 9 -> {5, 13} +/// 0 -> {} +/// 1 -> {2, 5} +/// 2 -> {1, 6} +/// 3 -> {} +/// 4 -> {} +/// 5 -> {1, 6, 9} +/// 6 -> {2, 5} +/// 7 -> {} +/// 8 -> {} +/// 9 -> {5, 13} /// 10 -> {} /// 11 -> {} /// 12 -> {13} diff --git a/src/lib.rs b/src/lib.rs index f3c5e94..114ffe6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,6 +112,7 @@ //! - [`SemidegreeSequence`](op::SemidegreeSequence) returns the semidegree //! sequence of a digraph. //! - [`Sinks`](op::Sinks) returns the sinks in a digraph. +//! - [`Sources`](op::Sources) returns the sources in a digraph. //! //! # Algorithms //! diff --git a/src/op/mod.rs b/src/op/mod.rs index dcd0cc1..60612e9 100644 --- a/src/op/mod.rs +++ b/src/op/mod.rs @@ -75,6 +75,7 @@ pub mod remove_arc; pub mod semidegree_sequence; pub mod sinks; pub mod size; +pub mod sources; pub mod vertices; pub use { @@ -114,5 +115,6 @@ pub use { semidegree_sequence::SemidegreeSequence, sinks::Sinks, size::Size, + sources::Sources, vertices::Vertices, }; diff --git a/src/op/sources.rs b/src/op/sources.rs new file mode 100644 index 0000000..3035fc2 --- /dev/null +++ b/src/op/sources.rs @@ -0,0 +1,123 @@ +//! Iterate over the sources in a digraph. +//! +//! A source is a vertex with no in-neighbors. +//! +//! # Examples +//! +//! ``` +//! use graaf::{ +//! adjacency_list::Digraph, +//! gen::Empty, +//! op::{ +//! AddArc, +//! Sources, +//! }, +//! }; +//! +//! // 0 -> {1, 2} +//! // 1 -> {2} +//! // 2 -> {} +//! // 3 -> {} +//! +//! let mut digraph = Digraph::empty(4); +//! +//! digraph.add_arc(0, 1); +//! digraph.add_arc(0, 2); +//! digraph.add_arc(1, 2); +//! +//! assert!(digraph.sources().eq([0, 3])); +//! ``` + +use super::{ + Indegree, + Vertices, +}; + +/// Iterate over the sources in a digraph. +/// +/// # How can I implement `Sources`? +/// +/// Provide an implementation of `sources` that returns an iterator over the +/// sources in the digraph OR implement `Indegree` and `Vertices`. +/// +/// ``` +/// use { +/// graaf::op::{ +/// Indegree, +/// Sources, +/// Vertices, +/// }, +/// std::collections::BTreeSet, +/// }; +/// +/// struct Digraph { +/// arcs: Vec>, +/// } +/// +/// impl Indegree for Digraph { +/// fn indegree(&self, u: usize) -> usize { +/// self.arcs.iter().filter(|set| set.contains(&u)).count() +/// } +/// } +/// +/// impl Vertices for Digraph { +/// fn vertices(&self) -> impl Iterator { +/// 0..self.arcs.len() +/// } +/// } +/// +/// // 0 -> {1, 2} +/// // 1 -> {2} +/// // 2 -> {} +/// // 3 -> {} +/// +/// let mut digraph = Digraph { +/// arcs: vec![ +/// BTreeSet::from([1, 2]), +/// BTreeSet::from([2]), +/// BTreeSet::new(), +/// BTreeSet::new(), +/// ], +/// }; +/// +/// assert!(digraph.sources().eq([0, 3])); +/// ``` +/// +/// # Examples +/// +/// ``` +/// use graaf::{ +/// adjacency_list::Digraph, +/// gen::Empty, +/// op::{ +/// AddArc, +/// Sources, +/// }, +/// }; +/// +/// // 0 -> {1, 2} +/// // 1 -> {2} +/// // 2 -> {} +/// // 3 -> {} +/// +/// let mut digraph = Digraph::empty(4); +/// +/// digraph.add_arc(0, 1); +/// digraph.add_arc(0, 2); +/// digraph.add_arc(1, 2); +/// +/// assert!(digraph.sources().eq([0, 3])); +/// ``` +pub trait Sources { + /// Returns an iterator over the sources in the digraph. + fn sources(&self) -> impl Iterator; +} + +impl Sources for D +where + D: Indegree + Vertices, +{ + fn sources(&self) -> impl Iterator { + self.vertices().filter(move |&u| self.is_source(u)) + } +}