From 79365b427896691ff4bb5c53bfd866c7eaf2be48 Mon Sep 17 00:00:00 2001 From: Bas Dirks Date: Sat, 5 Oct 2024 11:27:41 +0200 Subject: [PATCH] release: 0.101.0 Changed - Breaking: return `&W` instead of `W` in `DistanceMatrix::diameter`. - Breaking: return `impl Iterator` instead of `Vec` in `DistanceMatrix::eccentricities`. - Breaking: return `impl Iterator + use<'_, W>` instead of `Vec` in `DistanceMatrix::periphery`. --- CHANGELOG.md | 10 +++ Cargo.toml | 2 +- README.md | 2 +- src/algo/distance_matrix.rs | 109 +++++++++++++-------------------- src/algo/tarjan.rs | 68 ++++++-------------- src/repr/adjacency_list/mod.rs | 2 +- 6 files changed, 76 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c29bac..4abd434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ - Standardize the input type for search algorithms. - Test for `order > 0` in `bellman_ford_moore` and other algorithms that take a digraph. - Replace the blanket implementations in `op` with custom implementations for the types in `repr`. In the documentation, describe examples of both the direct and the trait-based implementation of the traits. +- Implement `size_hint` on iterators. +- Return iterators instead of vectors. + +## [0.101.0] - 2024-10-05 + +Changed + +- Breaking: return `&W` instead of `W` in `DistanceMatrix::diameter`. +- Breaking: return `impl Iterator` instead of `Vec` in `DistanceMatrix::eccentricities`. +- Breaking: return `impl Iterator + use<'_, W>` instead of `Vec` in `DistanceMatrix::periphery`. ## [0.100.1] - 2024-10-05 diff --git a/Cargo.toml b/Cargo.toml index 5daebe8..d3325e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "graaf" -version = "0.100.1" +version = "0.101.0" edition = "2021" authors = ["Bas Dirks "] categories = ["algorithms", "data-structures", "mathematics"] diff --git a/README.md b/README.md index 88e2b21..ac92da0 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -graaf = "0.100.1" +graaf = "0.101.0" ``` ## Representations diff --git a/src/algo/distance_matrix.rs b/src/algo/distance_matrix.rs index f2a583c..8138404 100644 --- a/src/algo/distance_matrix.rs +++ b/src/algo/distance_matrix.rs @@ -208,10 +208,11 @@ impl DistanceMatrix { /// digraph.add_arc_weighted(6, 1, 8); /// digraph.add_arc_weighted(6, 2, 5); /// - /// let mut floyd_warshall = FloydWarshall::new(&digraph); - /// let dist = floyd_warshall.distances(); - /// - /// assert!(dist.center().iter().eq(&[0, 1])); + /// assert!(FloydWarshall::new(&digraph) + /// .distances() + /// .center() + /// .iter() + /// .eq(&[0, 1])); /// ``` #[doc(alias = "centre")] #[doc(alias = "jordan_center")] @@ -225,7 +226,7 @@ impl DistanceMatrix { let mut center = Vec::new(); let mut min = self.infinity; - for (i, &e) in ecc.iter().enumerate() { + for (i, &e) in ecc.enumerate() { match e.cmp(&min) { Less => { center.clear(); @@ -277,21 +278,14 @@ impl DistanceMatrix { /// digraph.add_arc_weighted(6, 1, 8); /// digraph.add_arc_weighted(6, 2, 5); /// - /// let mut floyd_warshall = FloydWarshall::new(&digraph); - /// let dist = floyd_warshall.distances(); - /// - /// assert_eq!(dist.diameter(), 17); + /// assert_eq!(FloydWarshall::new(&digraph).distances().diameter(), &17); /// ``` #[must_use] - pub fn diameter(&self) -> W + pub fn diameter(&self) -> &W where W: Copy + Ord, { - self.eccentricities() - .iter() - .copied() - .max() - .unwrap_or(self.infinity) + self.eccentricities().max().unwrap_or(&self.infinity) } /// Return the digraph's eccentricities. @@ -329,25 +323,20 @@ impl DistanceMatrix { /// digraph.add_arc_weighted(6, 1, 8); /// digraph.add_arc_weighted(6, 2, 5); /// - /// let mut floyd_warshall = FloydWarshall::new(&digraph); - /// let dist = floyd_warshall.distances(); - /// - /// assert!(dist.eccentricities().iter().eq(&[5, 5, 14, 11, 17, 11, 10])); + /// assert!(FloydWarshall::new(&digraph) + /// .distances() + /// .eccentricities() + /// .eq(&[5, 5, 14, 11, 17, 11, 10])); /// ``` - #[must_use] - pub fn eccentricities(&self) -> Vec + pub fn eccentricities(&self) -> impl Iterator where - W: Copy + Ord, + W: Ord, { - self.dist - .iter() - .map(|row| { - row.iter() - .reduce(|acc, x| acc.max(x)) - .unwrap_or(&self.infinity) - }) - .copied() - .collect() + self.dist.iter().map(|row| { + row.iter() + .reduce(|acc, x| acc.max(x)) + .unwrap_or(&self.infinity) + }) } /// Check whether the distance matrix is connected. @@ -384,17 +373,14 @@ impl DistanceMatrix { /// digraph.add_arc_weighted(6, 1, 8); /// digraph.add_arc_weighted(6, 2, 5); /// - /// let mut floyd_warshall = FloydWarshall::new(&digraph); - /// let dist = floyd_warshall.distances(); - /// - /// assert!(dist.is_connected()); + /// assert!(FloydWarshall::new(&digraph).distances().is_connected()); /// ``` #[must_use] pub fn is_connected(&self) -> bool where - W: Copy + Ord, + W: Ord, { - self.eccentricities().iter().all(|&e| e != self.infinity) + self.eccentricities().all(|e| e != &self.infinity) } /// Return a digraph's periphery. @@ -431,23 +417,17 @@ impl DistanceMatrix { /// digraph.add_arc_weighted(6, 1, 8); /// digraph.add_arc_weighted(6, 2, 5); /// - /// let mut floyd_warshall = FloydWarshall::new(&digraph); - /// let dist = floyd_warshall.distances(); - /// - /// assert!(dist.periphery().iter().eq(&[4])); + /// assert!(FloydWarshall::new(&digraph).distances().periphery().eq([4])); /// ``` - #[must_use] - pub fn periphery(&self) -> Vec + pub fn periphery(&self) -> impl Iterator + use<'_, W> where W: Copy + Ord, { let ecc = self.eccentricities(); - let diameter = ecc.iter().max().unwrap_or(&self.infinity); + let diameter = self.diameter(); - ecc.iter() - .enumerate() - .filter_map(|(i, &e)| (e == *diameter).then_some(i)) - .collect() + ecc.enumerate() + .filter_map(move |(i, &e)| (e == *diameter).then_some(i)) } } @@ -534,7 +514,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert_eq!(dist.diameter(), 1); + assert_eq!(dist.diameter(), &1); } #[test] @@ -543,7 +523,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert_eq!(dist.diameter(), 4); + assert_eq!(dist.diameter(), &4); } #[test] @@ -552,7 +532,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert_eq!(dist.diameter(), 1); + assert_eq!(dist.diameter(), &1); } #[test] @@ -561,7 +541,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert_eq!(dist.diameter(), 11); + assert_eq!(dist.diameter(), &11); } #[test] @@ -570,7 +550,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert_eq!(dist.diameter(), 0); + assert_eq!(dist.diameter(), &0); } #[test] @@ -579,7 +559,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.eccentricities().iter().eq(&[1, 1, 1])); + assert!(dist.eccentricities().eq(&[1, 1, 1])); } #[test] @@ -588,7 +568,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.eccentricities().iter().eq(&[3, 4, 3, 2, 3, 4])); + assert!(dist.eccentricities().eq(&[3, 4, 3, 2, 3, 4])); } #[test] @@ -597,10 +577,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist - .eccentricities() - .iter() - .eq(&[1, 1, 1, 1, 1, 1, 1, 1, 1, 1])); + assert!(dist.eccentricities().eq(&[1, 1, 1, 1, 1, 1, 1, 1, 1, 1])); } #[test] @@ -609,7 +586,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.eccentricities().iter().eq(&[10, 11, 7, 6])); + assert!(dist.eccentricities().eq(&[10, 11, 7, 6])); } #[test] @@ -618,7 +595,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.eccentricities().iter().eq(&[0])); + assert!(dist.eccentricities().eq(&[0])); } #[test] @@ -766,7 +743,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.periphery().iter().eq(&[0, 1, 2])); + assert!(dist.periphery().eq([0, 1, 2])); } #[test] @@ -775,7 +752,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.periphery().iter().eq(&[1, 5])); + assert!(dist.periphery().eq([1, 5])); } #[test] @@ -784,7 +761,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.periphery().iter().eq(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + assert!(dist.periphery().eq([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); } #[test] @@ -793,7 +770,7 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.periphery().iter().eq(&[1])); + assert!(dist.periphery().eq([1])); } #[test] @@ -802,6 +779,6 @@ mod tests { let mut floyd_warshall = FloydWarshall::new(&digraph); let dist = floyd_warshall.distances(); - assert!(dist.periphery().iter().eq(&[0])); + assert!(dist.periphery().eq([0])); } } diff --git a/src/algo/tarjan.rs b/src/algo/tarjan.rs index 29ec557..add790e 100644 --- a/src/algo/tarjan.rs +++ b/src/algo/tarjan.rs @@ -35,18 +35,11 @@ //! digraph.add_arc(7, 3); //! digraph.add_arc(7, 6); //! -//! assert_eq!( -//! Tarjan::new(&digraph) -//! .components() -//! .iter() -//! .cloned() -//! .collect::>>(), -//! BTreeSet::from([ -//! BTreeSet::from([4, 1, 0]), -//! BTreeSet::from([5, 6]), -//! BTreeSet::from([7, 3, 2]) -//! ]) -//! ); +//! assert!(Tarjan::new(&digraph).components().iter().eq(&[ +//! BTreeSet::from([5, 6]), +//! BTreeSet::from([7, 3, 2]), +//! BTreeSet::from([4, 1, 0]) +//! ])); //! ``` use { @@ -97,18 +90,11 @@ use { /// digraph.add_arc(7, 3); /// digraph.add_arc(7, 6); /// -/// assert_eq!( -/// Tarjan::new(&digraph) -/// .components() -/// .iter() -/// .cloned() -/// .collect::>>(), -/// BTreeSet::from([ -/// BTreeSet::from([4, 1, 0]), -/// BTreeSet::from([5, 6]), -/// BTreeSet::from([7, 3, 2]) -/// ]) -/// ); +/// assert!(Tarjan::new(&digraph).components().iter().eq(&[ +/// BTreeSet::from([5, 6]), +/// BTreeSet::from([7, 3, 2]), +/// BTreeSet::from([4, 1, 0]), +/// ])); /// ``` #[derive(Clone, Debug, Eq, PartialEq)] pub struct Tarjan<'a, D> { @@ -178,18 +164,11 @@ impl<'a, D> Tarjan<'a, D> { /// digraph.add_arc(7, 3); /// digraph.add_arc(7, 6); /// - /// assert_eq!( - /// Tarjan::new(&digraph) - /// .components() - /// .iter() - /// .cloned() - /// .collect::>>(), - /// BTreeSet::from([ - /// BTreeSet::from([4, 1, 0]), - /// BTreeSet::from([5, 6]), - /// BTreeSet::from([7, 3, 2]) - /// ]) - /// ); + /// assert!(Tarjan::new(&digraph).components().iter().eq(&[ + /// BTreeSet::from([5, 6]), + /// BTreeSet::from([7, 3, 2]), + /// BTreeSet::from([4, 1, 0]) + /// ])); /// ``` #[must_use] pub fn components(&mut self) -> &Vec> @@ -271,18 +250,11 @@ mod tests { #[test] fn components_bang_jensen_196() { - assert_eq!( - Tarjan::new(&bang_jensen_196()) - .components() - .iter() - .cloned() - .collect::>>(), - BTreeSet::from([ - BTreeSet::from([0, 1]), - BTreeSet::from([2, 3, 4]), - BTreeSet::from([5, 6, 7]), - ]) - ); + assert!(Tarjan::new(&bang_jensen_196()).components().iter().eq(&[ + BTreeSet::from([2, 3, 4]), + BTreeSet::from([5, 6, 7]), + BTreeSet::from([0, 1]), + ])); } #[test] diff --git a/src/repr/adjacency_list/mod.rs b/src/repr/adjacency_list/mod.rs index 0a3fe45..0358c55 100644 --- a/src/repr/adjacency_list/mod.rs +++ b/src/repr/adjacency_list/mod.rs @@ -556,7 +556,7 @@ impl Indegree for AdjacencyList { } fn is_source(&self, v: usize) -> bool { - self.indegree(v) == 0 + self.arcs.iter().all(|set| !set.contains(&v)) } }