From 7b52d4b948fcdbc914244d8ec33fffb9dcd859fe Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Tue, 10 Jan 2023 13:05:50 -0800 Subject: [PATCH 01/15] Initial r-ary --- .../src/generators/full_rary_graph.rs | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 rustworkx-core/src/generators/full_rary_graph.rs diff --git a/rustworkx-core/src/generators/full_rary_graph.rs b/rustworkx-core/src/generators/full_rary_graph.rs new file mode 100644 index 000000000..efccd743f --- /dev/null +++ b/rustworkx-core/src/generators/full_rary_graph.rs @@ -0,0 +1,159 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +use std::hash::Hash; +use std::collections::VecDeque; + +use petgraph::data::{Build, Create}; +use petgraph::visit::{Data, NodeIndexable}; + +use super::InvalidInputError; + +/// Creates a full r-ary tree of `n` nodes. +/// Sometimes called a k-ary, n-ary, or m-ary tree. +/// +/// * `branching factor` - The number of children at each node. +/// * `num_nodes` - The number of nodes in the graph. +/// * `weights` - A list of node weights. If the number of weights is +/// less than n, extra nodes with with None weight will be appended. +/// * `default_node_weight` - A callable that will return the weight to use +/// for newly created nodes. This is ignored if `weights` is specified, +/// as the weights from that argument will be used instead. +/// * `default_edge_weight` - A callable that will return the weight object +/// to use for newly created edges. +/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. +/// If the graph is undirected this will result in a pallel edge. +/// +/// # Example +/// ```rust +/// use rustworkx_core::petgraph; +/// use rustworkx_core::generators::full_rary_graph; +/// use rustworkx_core::petgraph::visit::EdgeRef; +/// +/// let expected_edge_list = vec![ +/// (0, 1), +/// (0, 2), +/// (1, 3), +/// (1, 4), +/// (2, 5), +/// (2, 6), +/// (3, 7), +/// (3, 8), +/// (4, 9), +/// ]; +/// let g: petgraph::graph::UnGraph<(), ()> = full_rary_graph( +/// 2, +/// 10, +/// None, +/// || {()}, +/// || {()}, +/// ).unwrap(); +/// assert_eq!( +/// expected_edge_list, +/// g.edge_references() +/// .map(|edge| (edge.source().index(), edge.target().index())) +/// .collect::>(), +/// ) +/// ``` +pub fn full_rary_graph( + branching_factor: u32, + num_nodes: usize, + weights: Option>, + mut default_node_weight: F, + mut default_edge_weight: H, +) -> Result +where + G: Build + Create + Data + NodeIndexable, + F: FnMut() -> T, + H: FnMut() -> M, + G::NodeId: Eq + Hash, +{ + if weights.is_some() { + if weights.len() > num_nodes { + return Err(InvalidInputError {}); + } + } + let mut graph = G::with_capacity(num_nodes, num_nodes * branching_factor - 1); + + let nodes: Vec = match weights { + Some(weights) => { + let mut node_list: Vec = Vec::with_capacity(num_nodes); + let node_count = num_nodes - weights.len(); + for weight in weights { + let index = graph.add_node(weight); + node_list.push(index); + } + for _ in 0..node_count { + let index = graph.add_node(default_node_weight()); + node_list.push(index); + } + node_list + } + None => (0..num_nodes).map(|_| graph.add_node(default_node_weight())).collect(), + }; + if nodes.len() > 0 { + let mut parents = VecDeque::from(vec![nodes[0].index()]); + let mut nod_it: usize = 1; + + while !parents.is_empty() { + let source: usize = parents.pop_front().unwrap(); //If is empty it will never try to pop + for _ in 0..branching_factor { + if nod_it < num_nodes { + let target: usize = nodes[nod_it].index(); + parents.push_back(target); + nod_it += 1; + graph.add_edge(nodes[source], nodes[target], default_edge_weight()); + } + } + } + } + Ok(graph) +} + +#[cfg(test)] +mod tests { + use crate::generators::full_rary_graph; + use crate::generators::InvalidInputError; + use crate::petgraph; + use crate::petgraph::visit::EdgeRef; + + #[test] + fn test_full_rary_graph() { + let expected_edge_list = vec![ + (0, 1), + (0, 2), + (1, 3), + (1, 4), + (2, 5), + (2, 6), + (3, 7), + (3, 8), + (4, 9), + ]; + let g: petgraph::graph::UnGraph<(), ()> = full_rary_graph(2, 10, None, || (), || ()).unwrap(); + assert_eq!( + expected_edge_list, + g.edge_references() + .map(|edge| (edge.source().index(), edge.target().index())) + .collect::>(), + ); + } + + #[test] + fn test_full_rary_error() { + match full_rary_graph::, (), _, _, ()>(3, 2, vec![0, 1, 2, 3], || (), || ()) { + Ok(_) => panic!("Returned a non-error"), + Err(e) => assert_eq!(e, InvalidInputError), + }; + } +} From 3ed72073fa26d6816a4b23510deaba873bed9c98 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Tue, 10 Jan 2023 14:44:26 -0800 Subject: [PATCH 02/15] Complete tests --- ..._rary_graph.rs => full_rary_tree_graph.rs} | 29 +++++---- rustworkx-core/src/generators/mod.rs | 2 + src/generators.rs | 59 ++++++------------- 3 files changed, 39 insertions(+), 51 deletions(-) rename rustworkx-core/src/generators/{full_rary_graph.rs => full_rary_tree_graph.rs} (87%) diff --git a/rustworkx-core/src/generators/full_rary_graph.rs b/rustworkx-core/src/generators/full_rary_tree_graph.rs similarity index 87% rename from rustworkx-core/src/generators/full_rary_graph.rs rename to rustworkx-core/src/generators/full_rary_tree_graph.rs index efccd743f..b67c24b78 100644 --- a/rustworkx-core/src/generators/full_rary_graph.rs +++ b/rustworkx-core/src/generators/full_rary_tree_graph.rs @@ -10,8 +10,8 @@ // License for the specific language governing permissions and limitations // under the License. -use std::hash::Hash; use std::collections::VecDeque; +use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, NodeIndexable}; @@ -65,8 +65,8 @@ use super::InvalidInputError; /// .collect::>(), /// ) /// ``` -pub fn full_rary_graph( - branching_factor: u32, +pub fn full_rary_tree_graph( + branching_factor: usize, num_nodes: usize, weights: Option>, mut default_node_weight: F, @@ -79,11 +79,11 @@ where G::NodeId: Eq + Hash, { if weights.is_some() { - if weights.len() > num_nodes { + if weights.as_ref().unwrap().len() > num_nodes { return Err(InvalidInputError {}); } } - let mut graph = G::with_capacity(num_nodes, num_nodes * branching_factor - 1); + let mut graph = G::with_capacity(num_nodes, num_nodes * branching_factor); let nodes: Vec = match weights { Some(weights) => { @@ -99,17 +99,19 @@ where } node_list } - None => (0..num_nodes).map(|_| graph.add_node(default_node_weight())).collect(), + None => (0..num_nodes) + .map(|_| graph.add_node(default_node_weight())) + .collect(), }; if nodes.len() > 0 { - let mut parents = VecDeque::from(vec![nodes[0].index()]); + let mut parents = VecDeque::from(vec![graph.to_index(nodes[0])]); let mut nod_it: usize = 1; while !parents.is_empty() { let source: usize = parents.pop_front().unwrap(); //If is empty it will never try to pop for _ in 0..branching_factor { if nod_it < num_nodes { - let target: usize = nodes[nod_it].index(); + let target: usize = graph.to_index(nodes[nod_it]); parents.push_back(target); nod_it += 1; graph.add_edge(nodes[source], nodes[target], default_edge_weight()); @@ -140,7 +142,8 @@ mod tests { (3, 8), (4, 9), ]; - let g: petgraph::graph::UnGraph<(), ()> = full_rary_graph(2, 10, None, || (), || ()).unwrap(); + let g: petgraph::graph::UnGraph<(), ()> = + full_rary_graph(2, 10, None, || (), || ()).unwrap(); assert_eq!( expected_edge_list, g.edge_references() @@ -151,7 +154,13 @@ mod tests { #[test] fn test_full_rary_error() { - match full_rary_graph::, (), _, _, ()>(3, 2, vec![0, 1, 2, 3], || (), || ()) { + match full_rary_graph::, (), _, _, ()>( + 3, + 2, + Some(vec![(), (), (), ()]), + || (), + || (), + ) { Ok(_) => panic!("Returned a non-error"), Err(e) => assert_eq!(e, InvalidInputError), }; diff --git a/rustworkx-core/src/generators/mod.rs b/rustworkx-core/src/generators/mod.rs index f242b2979..57617a8bd 100644 --- a/rustworkx-core/src/generators/mod.rs +++ b/rustworkx-core/src/generators/mod.rs @@ -13,6 +13,7 @@ //! This module contains generator functions for building graphs mod cycle_graph; +mod full_rary_tree_graph; mod grid_graph; mod path_graph; mod petersen_graph; @@ -36,6 +37,7 @@ impl fmt::Display for InvalidInputError { } pub use cycle_graph::cycle_graph; +pub use full_rary_tree_graph::full_rary_tree_graph; pub use grid_graph::grid_graph; pub use path_graph::path_graph; pub use petersen_graph::petersen_graph; diff --git a/src/generators.rs b/src/generators.rs index a83f54a17..51584a480 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -10,7 +10,6 @@ // License for the specific language governing permissions and limitations // under the License. -use std::collections::VecDeque; use std::iter; use petgraph::algo; @@ -782,9 +781,11 @@ pub fn binomial_tree_graph( /// Creates a full r-ary tree of `n` nodes. /// Sometimes called a k-ary, n-ary, or m-ary tree. /// -/// :param int order: Order of the tree. +/// :param int branching factor: The number of children at each node. +/// :param int num_nodes: The number of nodes in the graph. /// :param list weights: A list of node weights. If the number of weights is -/// less than n, extra nodes with with None will be appended. +/// less than num_nodes, extra nodes with with None will be appended. The +/// number of weights cannot exceed num_nodes. /// :param bool multigraph: When set to False the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead @@ -806,50 +807,26 @@ pub fn binomial_tree_graph( #[pyo3(text_signature = "(branching_factor, num_nodes, /, weights=None, multigraph=True)")] pub fn full_rary_tree( py: Python, - branching_factor: u32, + branching_factor: usize, num_nodes: usize, weights: Option>, multigraph: bool, ) -> PyResult { - let mut graph = StablePyGraph::::default(); - - let nodes: Vec = match weights { - Some(weights) => { - let mut node_list: Vec = Vec::with_capacity(num_nodes); - if weights.len() > num_nodes { - return Err(PyIndexError::new_err("weights can't be greater than nodes")); - } - let node_count = num_nodes - weights.len(); - for weight in weights { - let index = graph.add_node(weight); - node_list.push(index); - } - for _ in 0..node_count { - let index = graph.add_node(py.None()); - node_list.push(index); - } - node_list + let default_fn = || py.None(); + let graph: StablePyGraph = match core_generators::full_rary_tree_graph( + branching_factor, + num_nodes, + weights, + default_fn, + default_fn, + ) { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "The number of weights cannot exceed num_nodes.", + )) } - None => (0..num_nodes).map(|_| graph.add_node(py.None())).collect(), }; - - if num_nodes > 0 { - let mut parents = VecDeque::from(vec![nodes[0].index()]); - let mut nod_it: usize = 1; - - while !parents.is_empty() { - let source: usize = parents.pop_front().unwrap(); //If is empty it will never try to pop - for _ in 0..branching_factor { - if nod_it < num_nodes { - let target: usize = nodes[nod_it].index(); - parents.push_back(target); - nod_it += 1; - graph.add_edge(nodes[source], nodes[target], py.None()); - } - } - } - } - Ok(graph::PyGraph { graph, node_removed: false, From 85d214e2e0262c8dbd4d59e2a31fae955b2aaa66 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Tue, 10 Jan 2023 15:18:21 -0800 Subject: [PATCH 03/15] Lint and name change --- .../src/generators/full_rary_tree_graph.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rustworkx-core/src/generators/full_rary_tree_graph.rs b/rustworkx-core/src/generators/full_rary_tree_graph.rs index b67c24b78..b58432516 100644 --- a/rustworkx-core/src/generators/full_rary_tree_graph.rs +++ b/rustworkx-core/src/generators/full_rary_tree_graph.rs @@ -37,7 +37,7 @@ use super::InvalidInputError; /// # Example /// ```rust /// use rustworkx_core::petgraph; -/// use rustworkx_core::generators::full_rary_graph; +/// use rustworkx_core::generators::full_rary_tree_graph; /// use rustworkx_core::petgraph::visit::EdgeRef; /// /// let expected_edge_list = vec![ @@ -51,7 +51,7 @@ use super::InvalidInputError; /// (3, 8), /// (4, 9), /// ]; -/// let g: petgraph::graph::UnGraph<(), ()> = full_rary_graph( +/// let g: petgraph::graph::UnGraph<(), ()> = full_rary_tree_graph( /// 2, /// 10, /// None, @@ -78,8 +78,8 @@ where H: FnMut() -> M, G::NodeId: Eq + Hash, { - if weights.is_some() { - if weights.as_ref().unwrap().len() > num_nodes { + if let Some(wt) = weights.as_ref() { + if wt.len() > num_nodes { return Err(InvalidInputError {}); } } @@ -124,7 +124,7 @@ where #[cfg(test)] mod tests { - use crate::generators::full_rary_graph; + use crate::generators::full_rary_tree_graph; use crate::generators::InvalidInputError; use crate::petgraph; use crate::petgraph::visit::EdgeRef; @@ -143,7 +143,7 @@ mod tests { (4, 9), ]; let g: petgraph::graph::UnGraph<(), ()> = - full_rary_graph(2, 10, None, || (), || ()).unwrap(); + full_rary_tree_graph(2, 10, None, || (), || ()).unwrap(); assert_eq!( expected_edge_list, g.edge_references() @@ -154,7 +154,7 @@ mod tests { #[test] fn test_full_rary_error() { - match full_rary_graph::, (), _, _, ()>( + match full_rary_tree_graph::, (), _, _, ()>( 3, 2, Some(vec![(), (), (), ()]), From 8230812599540fbfe5f0acb6c3deae0c54644fa5 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Wed, 11 Jan 2023 11:45:37 -0800 Subject: [PATCH 04/15] Clippy --- rustworkx-core/src/generators/full_rary_tree_graph.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustworkx-core/src/generators/full_rary_tree_graph.rs b/rustworkx-core/src/generators/full_rary_tree_graph.rs index b58432516..181491ddb 100644 --- a/rustworkx-core/src/generators/full_rary_tree_graph.rs +++ b/rustworkx-core/src/generators/full_rary_tree_graph.rs @@ -103,7 +103,7 @@ where .map(|_| graph.add_node(default_node_weight())) .collect(), }; - if nodes.len() > 0 { + if !nodes.is_empty() { let mut parents = VecDeque::from(vec![graph.to_index(nodes[0])]); let mut nod_it: usize = 1; From 4fe1f1708fa7eec711226d52e71373acf3183de2 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Sat, 14 Jan 2023 08:10:48 -0800 Subject: [PATCH 05/15] Code and docs consistency --- .../src/generators/barbell_graph.rs | 19 ++++++------- .../src/generators/binomial_tree_graph.rs | 9 +++--- .../src/generators/complete_graph.rs | 5 ++-- rustworkx-core/src/generators/cycle_graph.rs | 9 +++--- .../src/generators/full_rary_tree_graph.rs | 11 ++++---- rustworkx-core/src/generators/grid_graph.rs | 7 ++--- .../src/generators/heavy_hex_graph.rs | 13 +++++---- .../src/generators/heavy_square_graph.rs | 17 +++++++---- .../src/generators/hexagonal_lattice_graph.rs | 7 ++--- .../src/generators/lollipop_graph.rs | 28 +++++++------------ rustworkx-core/src/generators/mod.rs | 2 +- rustworkx-core/src/generators/path_graph.rs | 9 +++--- .../src/generators/petersen_graph.rs | 9 +++--- rustworkx-core/src/generators/star_graph.rs | 9 +++--- src/generators.rs | 11 -------- src/steiner_tree.rs | 2 +- 16 files changed, 73 insertions(+), 94 deletions(-) diff --git a/rustworkx-core/src/generators/barbell_graph.rs b/rustworkx-core/src/generators/barbell_graph.rs index e7383f5af..6b8d6ccd5 100644 --- a/rustworkx-core/src/generators/barbell_graph.rs +++ b/rustworkx-core/src/generators/barbell_graph.rs @@ -19,33 +19,32 @@ use super::utils::get_num_nodes; use super::utils::pairwise; use super::InvalidInputError; -/// Generate an undirected barbell graph where two identical mesh graphs are +/// Generate an undirected barbell graph where two identical complete graphs are /// connected by a path. /// /// .. note:: /// -/// If neither `num_path_nodes` nor `path_weights` (described below) is not specified -/// then this is equivalent to two mesh graphs joined together. +/// If neither `num_path_nodes` nor `path_weights` (described below) is +/// specified, then this is equivalent to two complete graphs joined together. /// /// Arguments: /// /// * `num_mesh_nodes` - The number of nodes to generate the mesh graph /// with. Node weights will be None if this is specified. If both -/// `num_mesh_nodes` and `mesh_weights` are set this will be ignored and +/// `num_mesh_nodes` and `mesh_weights` are set, this will be ignored and /// `mesh_weights` will be used. /// * `num_path_nodes` - The number of nodes to generate the path /// with. Node weights will be None if this is specified. If both -/// `num_path_nodes` and `path_weights` are set this will be ignored and +/// `num_path_nodes` and `path_weights` are set, this will be ignored and /// `path_weights` will be used. /// * `mesh_weights` - A list of node weights for the mesh graph. If both -/// `num_mesh_nodes` and `mesh_weights` are set `num_mesh_nodes` will +/// `num_mesh_nodes` and `mesh_weights` are set, `num_mesh_nodes` will /// be ignored and `mesh_weights` will be used. /// * `path_weights` - A list of node weights for the path. If both -/// `num_path_nodes` and `path_weights` are set `num_path_nodes` will +/// `num_path_nodes` and `path_weights` are set, `num_path_nodes` will /// be ignored and `path_weights` will be used. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if weights are specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if node weights are specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. /// @@ -147,7 +146,7 @@ where } }; let pathlen = path_nodes.len(); - if pathlen > 0 { + if !path_nodes.is_empty() { graph.add_edge( graph.from_index(meshlen - 1), graph.from_index(meshlen), diff --git a/rustworkx-core/src/generators/binomial_tree_graph.rs b/rustworkx-core/src/generators/binomial_tree_graph.rs index 27837be99..4ee04b47d 100644 --- a/rustworkx-core/src/generators/binomial_tree_graph.rs +++ b/rustworkx-core/src/generators/binomial_tree_graph.rs @@ -21,15 +21,14 @@ use super::InvalidInputError; /// /// * `order` - The order of the binomial tree. /// * `weights` - A `Vec` of node weight objects. If the number of weights is -/// less than 2**order extra nodes with None will be appended. +/// less than 2**order, extra nodes with None will be appended. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/complete_graph.rs b/rustworkx-core/src/generators/complete_graph.rs index 0aa7753c1..c07f4ee3d 100644 --- a/rustworkx-core/src/generators/complete_graph.rs +++ b/rustworkx-core/src/generators/complete_graph.rs @@ -21,12 +21,11 @@ use super::InvalidInputError; /// Arguments: /// /// * `num_nodes` - The number of nodes to create a complete graph for. Either this or -/// `weights must be specified. If both this and `weights are specified, weights +/// `weights` must be specified. If both this and `weights` are specified, `weights` /// will take priorty and this argument will be ignored /// * `weights` - A `Vec` of node weight objects. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. /// diff --git a/rustworkx-core/src/generators/cycle_graph.rs b/rustworkx-core/src/generators/cycle_graph.rs index f8b14838f..0cc603d8b 100644 --- a/rustworkx-core/src/generators/cycle_graph.rs +++ b/rustworkx-core/src/generators/cycle_graph.rs @@ -21,17 +21,16 @@ use super::InvalidInputError; /// Arguments: /// /// * `num_nodes` - The number of nodes to create a cycle graph for. Either this or -/// `weights must be specified. If both this and `weights are specified, weights +/// `weights` must be specified. If both this and `weights` are specified, `weights` /// will take priorty and this argument will be ignored. /// * `weights` - A `Vec` of node weight objects. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/full_rary_tree_graph.rs b/rustworkx-core/src/generators/full_rary_tree_graph.rs index 181491ddb..f8910d33d 100644 --- a/rustworkx-core/src/generators/full_rary_tree_graph.rs +++ b/rustworkx-core/src/generators/full_rary_tree_graph.rs @@ -21,18 +21,19 @@ use super::InvalidInputError; /// Creates a full r-ary tree of `n` nodes. /// Sometimes called a k-ary, n-ary, or m-ary tree. /// +/// Arguments: +/// /// * `branching factor` - The number of children at each node. /// * `num_nodes` - The number of nodes in the graph. /// * `weights` - A list of node weights. If the number of weights is -/// less than n, extra nodes with with None weight will be appended. +/// less than n, extra nodes with None weight will be appended. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/grid_graph.rs b/rustworkx-core/src/generators/grid_graph.rs index 2fdeb3ee7..9444367f4 100644 --- a/rustworkx-core/src/generators/grid_graph.rs +++ b/rustworkx-core/src/generators/grid_graph.rs @@ -21,7 +21,7 @@ use super::InvalidInputError; /// /// * `rows` - The number of rows to generate the graph with. /// If specified, cols also need to be specified. -/// * `cols`: The number of rows to generate the graph with. +/// * `cols`: The number of columns to generate the graph with. /// If specified, rows also need to be specified. rows*cols /// defines the number of nodes in the graph. /// * `weights`: A `Vec` of node weights. Nodes are filled row wise. @@ -32,11 +32,10 @@ use super::InvalidInputError; /// If number of nodes(rows*cols) is greater than length of /// weights list, extra nodes with None weight are appended. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. /// If the graph is undirected this will result in a parallel edge. /// diff --git a/rustworkx-core/src/generators/heavy_hex_graph.rs b/rustworkx-core/src/generators/heavy_hex_graph.rs index 2d2821d8b..0a6b9c5cd 100644 --- a/rustworkx-core/src/generators/heavy_hex_graph.rs +++ b/rustworkx-core/src/generators/heavy_hex_graph.rs @@ -54,16 +54,17 @@ use super::InvalidInputError; /// ... D D-S-D ... /// /// -/// * `d` - Distance of the code. If ``d`` is set to ``1`` a graph with a -/// single node will be returned. d must be an odd number. +/// Arguments: +/// +/// * `d` - Distance of the code. If `d` is set to `1` a graph with a +/// single node will be returned. `d` must be an odd number. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/heavy_square_graph.rs b/rustworkx-core/src/generators/heavy_square_graph.rs index 05e19632c..9dfa86171 100644 --- a/rustworkx-core/src/generators/heavy_square_graph.rs +++ b/rustworkx-core/src/generators/heavy_square_graph.rs @@ -43,12 +43,17 @@ use super::InvalidInputError; /// This function implements Fig 10.b left of the `paper `_. /// This function doesn't support the variant Fig 10.b right. /// -/// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyDiGraph` with a single node will be returned. -/// :param bool multigraph: When set to False the output -/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. +/// Arguments: +/// +/// * `d` - Distance of the code. If `d` is set to `1` a graph with a +/// single node will be returned. `d` must be an odd number. +/// * `default_node_weight` - A callable that will return the weight to use +/// for newly created nodes. This is ignored if `weights` is specified. +/// * `default_edge_weight` - A callable that will return the weight object +/// to use for newly created edges. +/// * `bidirectional` - Whether edges are added bidirectionally. If set to +/// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/hexagonal_lattice_graph.rs b/rustworkx-core/src/generators/hexagonal_lattice_graph.rs index 56f4f58dd..7adbba201 100644 --- a/rustworkx-core/src/generators/hexagonal_lattice_graph.rs +++ b/rustworkx-core/src/generators/hexagonal_lattice_graph.rs @@ -24,13 +24,12 @@ use super::InvalidInputError; /// * `rows` - The number of rows to generate the graph with. /// * `cols` - The number of columns to generate the graph with. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/lollipop_graph.rs b/rustworkx-core/src/generators/lollipop_graph.rs index afbdfc69e..9da1fe4a9 100644 --- a/rustworkx-core/src/generators/lollipop_graph.rs +++ b/rustworkx-core/src/generators/lollipop_graph.rs @@ -15,19 +15,18 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, GraphProp, NodeIndexable}; -use super::utils::pairwise; +use super::utils::{get_num_nodes, pairwise}; use super::InvalidInputError; -/// Generate a lollipop graph +/// Generate an undirected lollipop graph where a complete graph is connected to a +/// path. /// -/// Arguments: +/// .. note:: /// -/// Generate an undirected lollipop graph where a mesh graph is connected to a -/// path. +/// If neither `num_path_nodes` nor `path_weights` (both described +/// below) are specified then this is equivalent to a complete graph. /// -/// If neither `num_path_nodes` nor `path_weights` (both described -/// below) are specified then this is equivalent to -/// :func:`~rustworkx.generators.mesh_graph` +/// Arguments: /// /// * `num_mesh_nodes` - The number of nodes to generate the mesh graph /// with. Node weights will be None if this is specified. If both @@ -44,8 +43,7 @@ use super::InvalidInputError; /// `num_path_nodes` and `path_weights` are set `num_path_nodes` will /// be ignored and `path_weights` will be used. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. /// @@ -98,12 +96,7 @@ where if num_mesh_nodes.is_none() && mesh_weights.is_none() { return Err(InvalidInputError {}); } - let num_nodes: usize; - if let Some(mesh_nodes) = num_mesh_nodes { - num_nodes = mesh_nodes; - } else { - num_nodes = mesh_weights.as_ref().unwrap().len(); - } + let num_nodes = get_num_nodes(&num_mesh_nodes, &mesh_weights); let num_edges = (num_nodes * (num_nodes - 1)) / 2; let mut graph = G::with_capacity(num_nodes, num_edges); @@ -138,8 +131,7 @@ where } } }; - let pathlen = path_nodes.len(); - if pathlen > 0 { + if !path_nodes.is_empty() { graph.add_edge( graph.from_index(meshlen - 1), graph.from_index(meshlen), diff --git a/rustworkx-core/src/generators/mod.rs b/rustworkx-core/src/generators/mod.rs index 40237685d..a5e3b9f3d 100644 --- a/rustworkx-core/src/generators/mod.rs +++ b/rustworkx-core/src/generators/mod.rs @@ -26,7 +26,7 @@ mod path_graph; mod petersen_graph; mod star_graph; -mod utils; +pub mod utils; use std::{error::Error, fmt}; diff --git a/rustworkx-core/src/generators/path_graph.rs b/rustworkx-core/src/generators/path_graph.rs index 2317e47e8..7aff79d7b 100644 --- a/rustworkx-core/src/generators/path_graph.rs +++ b/rustworkx-core/src/generators/path_graph.rs @@ -21,17 +21,16 @@ use super::InvalidInputError; /// Arguments: /// /// * `num_nodes` - The number of nodes to create a path graph for. Either this or -/// `weights must be specified. If both this and `weights are specified, weights +/// `weights` must be specified. If both this and `weights` are specified, `weights` /// will take priorty and this argument will be ignored /// * `weights` - A `Vec` of node weight objects. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/petersen_graph.rs b/rustworkx-core/src/generators/petersen_graph.rs index 905d2fb0d..546c93f64 100644 --- a/rustworkx-core/src/generators/petersen_graph.rs +++ b/rustworkx-core/src/generators/petersen_graph.rs @@ -18,7 +18,7 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; /// Generate a generalized Petersen graph :math:`G(n, k)` with :math:`2n` -/// nodes and :math:`3n` edges. See Watkins [1]_ for more details. +/// nodes and :math:`3n` edges. /// /// .. note:: /// @@ -28,13 +28,12 @@ use super::InvalidInputError; /// n > 2. /// * `k` - Shift that changes the internal star graph. k > 0 and 2 * k < n. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. -/// If the graph is undirected this will result in a pallel edge. +/// If the graph is undirected this will result in a parallel edge. /// /// # Example /// ```rust diff --git a/rustworkx-core/src/generators/star_graph.rs b/rustworkx-core/src/generators/star_graph.rs index a185a943a..4fea65d27 100644 --- a/rustworkx-core/src/generators/star_graph.rs +++ b/rustworkx-core/src/generators/star_graph.rs @@ -20,19 +20,18 @@ use super::InvalidInputError; /// /// Arguments: /// -/// * `num_nodes` - The number of nodes to create a path graph for. Either this or +/// * `num_nodes` - The number of nodes to create a star graph for. Either this or /// `weights` must be specified. If both this and `weights` are specified, weights /// will take priorty and this argument will be ignored /// * `weights` - A `Vec` of node weight objects. /// * `default_node_weight` - A callable that will return the weight to use -/// for newly created nodes. This is ignored if `weights` is specified, -/// as the weights from that argument will be used instead. +/// for newly created nodes. This is ignored if `weights` is specified. /// * `default_edge_weight` - A callable that will return the weight object /// to use for newly created edges. -/// * inward: If set `true` the nodes will be directed towards the +/// * `inward` - If set `true` the nodes will be directed towards the /// center node. This parameter is ignored if `bidirectional` is set to /// `true`. -/// * `bidirectional` - Whether edges are added bidirectionally, if set to +/// * `bidirectional` - Whether edges are added bidirectionally. If set to /// `true` then for any edge `(u, v)` an edge `(v, u)` will also be added. /// If the graph is undirected this will result in a parallel edge. diff --git a/src/generators.rs b/src/generators.rs index e73945744..feacbd719 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -10,10 +10,7 @@ // License for the specific language governing permissions and limitations // under the License. -use std::iter; - use petgraph::algo; -use petgraph::graph::NodeIndex; use petgraph::prelude::*; use petgraph::Undirected; @@ -25,14 +22,6 @@ use pyo3::Python; use super::{digraph, graph, StablePyGraph}; use rustworkx_core::generators as core_generators; -pub fn pairwise(right: I) -> impl Iterator, I::Item)> -where - I: IntoIterator + Clone, -{ - let left = iter::once(None).chain(right.clone().into_iter().map(Some)); - left.zip(right) -} - /// Generate a cycle graph /// /// :param int num_node: The number of nodes to generate the graph with. Node diff --git a/src/steiner_tree.rs b/src/steiner_tree.rs index 018d5bbbf..e2f603724 100644 --- a/src/steiner_tree.rs +++ b/src/steiner_tree.rs @@ -23,12 +23,12 @@ use petgraph::stable_graph::{EdgeIndex, EdgeReference, NodeIndex}; use petgraph::unionfind::UnionFind; use petgraph::visit::{EdgeRef, IntoEdgeReferences, NodeIndexable}; -use crate::generators::pairwise; use crate::graph; use crate::is_valid_weight; use crate::shortest_path::all_pairs_dijkstra::all_pairs_dijkstra_shortest_paths; use rustworkx_core::dictmap::*; +use rustworkx_core::generators::utils::pairwise; use rustworkx_core::shortest_path::dijkstra; struct MetricClosureEdge { From 1764ba151aaa5dc701b161f47adef415e26a44fb Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Sat, 14 Jan 2023 09:46:58 -0800 Subject: [PATCH 06/15] Docs changes to generators.rs --- .../src/generators/barbell_graph.rs | 2 +- .../src/generators/lollipop_graph.rs | 5 +- src/generators.rs | 168 +++++++++--------- 3 files changed, 90 insertions(+), 85 deletions(-) diff --git a/rustworkx-core/src/generators/barbell_graph.rs b/rustworkx-core/src/generators/barbell_graph.rs index 6b8d6ccd5..85d91ddad 100644 --- a/rustworkx-core/src/generators/barbell_graph.rs +++ b/rustworkx-core/src/generators/barbell_graph.rs @@ -24,7 +24,7 @@ use super::InvalidInputError; /// /// .. note:: /// -/// If neither `num_path_nodes` nor `path_weights` (described below) is +/// If neither `num_path_nodes` nor `path_weights` (described below) are /// specified, then this is equivalent to two complete graphs joined together. /// /// Arguments: diff --git a/rustworkx-core/src/generators/lollipop_graph.rs b/rustworkx-core/src/generators/lollipop_graph.rs index 9da1fe4a9..ce32d6e8e 100644 --- a/rustworkx-core/src/generators/lollipop_graph.rs +++ b/rustworkx-core/src/generators/lollipop_graph.rs @@ -23,8 +23,8 @@ use super::InvalidInputError; /// /// .. note:: /// -/// If neither `num_path_nodes` nor `path_weights` (both described -/// below) are specified then this is equivalent to a complete graph. +/// If neither `num_path_nodes` nor `path_weights` (described below) are +/// specified, then this is equivalent to a complete graph. /// /// Arguments: /// @@ -152,6 +152,7 @@ mod tests { use crate::generators::lollipop_graph; use crate::generators::InvalidInputError; use crate::petgraph::visit::EdgeRef; + #[test] fn test_lollipop_mesh_path() { let expected_edge_list = vec![ diff --git a/src/generators.rs b/src/generators.rs index feacbd719..1bc97e669 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -22,17 +22,17 @@ use pyo3::Python; use super::{digraph, graph, StablePyGraph}; use rustworkx_core::generators as core_generators; -/// Generate a cycle graph +/// Generate a directed cycle graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the cycle graph. If both ``num_node`` and +/// will be the center node of the cycle graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool bidirectional: Adds edges in both directions between two nodes /// if set to ``True``. Default value is ``False`` -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -85,13 +85,13 @@ pub fn directed_cycle_graph( /// Generate an undirected cycle graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the cycle graph. If both ``num_node`` and +/// will be the center node of the cycle graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -136,15 +136,15 @@ pub fn cycle_graph( /// Generate a directed path graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the path graph. If both ``num_node`` and +/// will be the center node of the path graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool bidirectional: Adds edges in both directions between two nodes /// if set to ``True``. Default value is ``False`` -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -197,13 +197,13 @@ pub fn directed_path_graph( /// Generate an undirected path graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the path graph. If both ``num_node`` and +/// will be the center node of the path graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -248,18 +248,18 @@ pub fn path_graph( /// Generate a directed star graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the star graph. If both ``num_node`` and +/// will be the center node of the star graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool inward: If set ``True`` the nodes will be directed towards the /// center node. This parameter is ignored if ``bidirectional`` is set to /// ``True``. /// :param bool bidirectional: Adds edges in both directions between two nodes /// if set to ``True``. Default value is ``False``. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -324,13 +324,13 @@ pub fn directed_star_graph( /// Generate an undirected star graph /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the star graph. If both ``num_node`` and +/// will be the center node of the star graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -375,14 +375,14 @@ pub fn star_graph( }) } -/// Generate an undirected mesh graph where every node is connected to every other +/// Generate an undirected mesh (complete) graph where every node is connected to every other /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param list weights: A list of node weights. If both ``num_node`` and +/// :param list weights: A list of node weights. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -410,14 +410,14 @@ pub fn mesh_graph( complete_graph(py, num_nodes, weights, multigraph) } -/// Generate a directed mesh graph where every node is connected to every other +/// Generate a directed mesh (complete) graph where every node is connected to every other /// -/// :param int num_node: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_node`` and +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param list weights: A list of node weights. If both ``num_node`` and +/// :param list weights: A list of node weights. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -448,9 +448,9 @@ pub fn directed_mesh_graph( /// Generate an undirected grid graph. /// /// :param int rows: The number of rows to generate the graph with. -/// If specified, cols also need to be specified +/// If specified, ``cols`` also need to be specified /// :param int cols: The number of cols to generate the graph with. -/// If specified, rows also need to be specified. rows*cols +/// If specified, ``rows`` also need to be specified. rows*cols /// defines the number of nodes in the graph /// :param list weights: A list of node weights. Nodes are filled row wise. /// If rows and cols are not specified, then a linear graph containing @@ -459,7 +459,7 @@ pub fn directed_mesh_graph( /// weights list, the trailing weights are ignored. /// If number of nodes(rows*cols) is greater than length of /// weights list, extra nodes with None weight are appended. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -501,12 +501,12 @@ pub fn grid_graph( } /// Generate a directed grid graph. The edges propagate towards right and -/// bottom direction if ``bidirectional`` is ``false`` +/// bottom direction if ``bidirectional`` is ``False`` /// /// :param int rows: The number of rows to generate the graph with. -/// If specified, cols also need to be specified. +/// If specified, ``cols`` also need to be specified. /// :param int cols: The number of cols to generate the graph with. -/// If specified, rows also need to be specified. rows*cols +/// If specified, ``rows`` also need to be specified. rows*cols /// defines the number of nodes in the graph. /// :param list weights: A list of node weights. Nodes are filled row wise. /// If rows and cols are not specified, then a linear graph containing @@ -516,8 +516,8 @@ pub fn grid_graph( /// If number of nodes(rows*cols) is greater than length of /// weights list, extra nodes with None weight are appended. /// :param bidirectional: A parameter to indicate if edges should exist in -/// both directions between nodes -/// :param bool multigraph: When set to False the output +/// both directions between nodes. Defaults to ``False``. +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -579,14 +579,14 @@ const MAX_ORDER: u32 = 29; /// /// :param int order: Order of the binomial tree. The maximum allowed value /// for order on the platform your running on. If it's a 64bit platform -/// the max value is 59 and on 32bit systems the max value is 29. Any order -/// value above these will raise a ``OverflowError``. +/// the max value is 60 and on 32bit systems the max value is 29. Any order +/// value above these will raise an ``OverflowError``. /// :param list weights: A list of node weights. If the number of weights is -/// less than 2**order extra nodes with with None will be appended. -/// :param bool multigraph: When set to False the output +/// less than 2**order, extra nodes with None will be appended. +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. +/// won't allow parallel edges to be added. Instead calls which would +/// create a parallel edge will update the existing edge. /// /// :returns: A binomial tree with 2^n vertices and 2^n - 1 edges. /// :rtype: PyGraph @@ -635,17 +635,17 @@ pub fn binomial_tree_graph( } /// Generate a directed binomial tree of order n recursively. -/// The edges propagate towards right and bottom direction if ``bidirectional`` is ``false`` +/// The edges propagate towards right and bottom direction if ``bidirectional`` is ``False`` /// /// :param int order: Order of the binomial tree. The maximum allowed value /// for order on the platform your running on. If it's a 64bit platform -/// the max value is 59 and on 32bit systems the max value is 29. Any order -/// value above these will raise a ``OverflowError``. +/// the max value is 60 and on 32bit systems the max value is 29. Any order +/// value above these will raise an ``OverflowError``. /// :param list weights: A list of node weights. If the number of weights is -/// less than 2**order extra nodes with None will be appended. +/// less than 2**order, extra nodes with None will be appended. /// :param bidirectional: A parameter to indicate if edges should exist in -/// both directions between nodes -/// :param bool multigraph: When set to False the output +/// both directions between nodes. Defaults to ``False``. +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -710,9 +710,9 @@ pub fn directed_binomial_tree_graph( /// :param int branching factor: The number of children at each node. /// :param int num_nodes: The number of nodes in the graph. /// :param list weights: A list of node weights. If the number of weights is -/// less than num_nodes, extra nodes with with None will be appended. The +/// less than ``num_nodes``, extra nodes with None will be appended. The /// number of weights cannot exceed num_nodes. -/// :param bool multigraph: When set to False the output +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -791,8 +791,9 @@ pub fn full_rary_tree( /// single node will be returned. /// /// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyGraph` with a single node will be returned. -/// :param bool multigraph: When set to False the output +/// :class:`~rustworkx.PyGraph` with a single node will be returned. ``d`` must be +/// an odd number. +/// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. @@ -854,8 +855,9 @@ pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult PyResult Date: Sat, 14 Jan 2023 10:06:57 -0800 Subject: [PATCH 07/15] Reorder graphs in generators.rs --- src/generators.rs | 900 +++++++++++++++++++++++----------------------- 1 file changed, 450 insertions(+), 450 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 1bc97e669..8e695fa8c 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -22,6 +22,57 @@ use pyo3::Python; use super::{digraph, graph, StablePyGraph}; use rustworkx_core::generators as core_generators; +/// Generate an undirected cycle graph +/// +/// :param int num_nodes: The number of nodes to generate the graph with. Node +/// weights will be None if this is specified. If both ``num_nodes`` and +/// ``weights`` are set this will be ignored and ``weights`` will be used. +/// :param list weights: A list of node weights, the first element in the list +/// will be the center node of the cycle graph. If both ``num_nodes`` and +/// ``weights`` are set this will be ignored and ``weights`` will be used. +/// :param bool multigraph: When set to ``False`` the output +/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and +/// won't allow parallel edges to be added. Instead +/// calls which would create a parallel edge will update the existing edge. +/// +/// :returns: The generated cycle graph +/// :rtype: PyGraph +/// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified +/// +/// .. jupyter-execute:: +/// +/// import rustworkx.generators +/// from rustworkx.visualization import mpl_draw +/// +/// graph = rustworkx.generators.cycle_graph(5) +/// mpl_draw(graph) +/// +#[pyfunction(multigraph = true)] +#[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True)")] +pub fn cycle_graph( + py: Python, + num_nodes: Option, + weights: Option>, + multigraph: bool, +) -> PyResult { + let default_fn = || py.None(); + let graph: StablePyGraph = + match core_generators::cycle_graph(num_nodes, weights, default_fn, default_fn, false) { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "num_nodes and weights list not specified", + )) + } + }; + Ok(graph::PyGraph { + graph, + node_removed: false, + multigraph, + attrs: py.None(), + }) +} + /// Generate a directed cycle graph /// /// :param int num_nodes: The number of nodes to generate the graph with. Node @@ -83,20 +134,20 @@ pub fn directed_cycle_graph( }) } -/// Generate an undirected cycle graph +/// Generate an undirected path graph /// /// :param int num_nodes: The number of nodes to generate the graph with. Node /// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the cycle graph. If both ``num_nodes`` and +/// will be the center node of the path graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated cycle graph +/// :returns: The generated path graph /// :rtype: PyGraph /// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified /// @@ -105,12 +156,12 @@ pub fn directed_cycle_graph( /// import rustworkx.generators /// from rustworkx.visualization import mpl_draw /// -/// graph = rustworkx.generators.cycle_graph(5) +/// graph = rustworkx.generators.path_graph(10) /// mpl_draw(graph) /// #[pyfunction(multigraph = true)] #[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True)")] -pub fn cycle_graph( +pub fn path_graph( py: Python, num_nodes: Option, weights: Option>, @@ -118,7 +169,7 @@ pub fn cycle_graph( ) -> PyResult { let default_fn = || py.None(); let graph: StablePyGraph = - match core_generators::cycle_graph(num_nodes, weights, default_fn, default_fn, false) { + match core_generators::path_graph(num_nodes, weights, default_fn, default_fn, false) { Ok(graph) => graph, Err(_) => { return Err(PyIndexError::new_err( @@ -195,20 +246,21 @@ pub fn directed_path_graph( }) } -/// Generate an undirected path graph +/// Generate an undirected star graph /// /// :param int num_nodes: The number of nodes to generate the graph with. Node /// weights will be None if this is specified. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the path graph. If both ``num_nodes`` and +/// will be the center node of the star graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated path graph +/// +/// :returns: The generated star graph /// :rtype: PyGraph /// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified /// @@ -217,12 +269,12 @@ pub fn directed_path_graph( /// import rustworkx.generators /// from rustworkx.visualization import mpl_draw /// -/// graph = rustworkx.generators.path_graph(10) +/// graph = rustworkx.generators.star_graph(10) /// mpl_draw(graph) /// #[pyfunction(multigraph = true)] #[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True)")] -pub fn path_graph( +pub fn star_graph( py: Python, num_nodes: Option, weights: Option>, @@ -230,7 +282,8 @@ pub fn path_graph( ) -> PyResult { let default_fn = || py.None(); let graph: StablePyGraph = - match core_generators::path_graph(num_nodes, weights, default_fn, default_fn, false) { + match core_generators::star_graph(num_nodes, weights, default_fn, default_fn, false, false) + { Ok(graph) => graph, Err(_) => { return Err(PyIndexError::new_err( @@ -322,59 +375,6 @@ pub fn directed_star_graph( }) } -/// Generate an undirected star graph -/// -/// :param int num_nodes: The number of nodes to generate the graph with. Node -/// weights will be None if this is specified. If both ``num_nodes`` and -/// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param list weights: A list of node weights, the first element in the list -/// will be the center node of the star graph. If both ``num_nodes`` and -/// ``weights`` are set this will be ignored and ``weights`` will be used. -/// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. -/// -/// -/// :returns: The generated star graph -/// :rtype: PyGraph -/// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified -/// -/// .. jupyter-execute:: -/// -/// import rustworkx.generators -/// from rustworkx.visualization import mpl_draw -/// -/// graph = rustworkx.generators.star_graph(10) -/// mpl_draw(graph) -/// -#[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True)")] -pub fn star_graph( - py: Python, - num_nodes: Option, - weights: Option>, - multigraph: bool, -) -> PyResult { - let default_fn = || py.None(); - let graph: StablePyGraph = - match core_generators::star_graph(num_nodes, weights, default_fn, default_fn, false, false) - { - Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "num_nodes and weights list not specified", - )) - } - }; - Ok(graph::PyGraph { - graph, - node_removed: false, - multigraph, - attrs: py.None(), - }) -} - /// Generate an undirected mesh (complete) graph where every node is connected to every other /// /// :param int num_nodes: The number of nodes to generate the graph with. Node @@ -569,62 +569,64 @@ pub fn directed_grid_graph( }) } -// MAX_ORDER is determined based on the pointer width of the target platform -#[cfg(target_pointer_width = "64")] -const MAX_ORDER: u32 = 60; -#[cfg(not(target_pointer_width = "64"))] -const MAX_ORDER: u32 = 29; - -/// Generate an undirected binomial tree of order n recursively. +/// Generate an undirected heavy square graph. Fig. 6 of +/// https://arxiv.org/abs/1907.09528. +/// An ASCII diagram of the graph is given by: /// -/// :param int order: Order of the binomial tree. The maximum allowed value -/// for order on the platform your running on. If it's a 64bit platform -/// the max value is 60 and on 32bit systems the max value is 29. Any order -/// value above these will raise an ``OverflowError``. -/// :param list weights: A list of node weights. If the number of weights is -/// less than 2**order, extra nodes with None will be appended. +/// .. code-block:: console +/// +/// ... S ... +/// \ / \ +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// \ / \ +/// ... S ... +/// +/// NOTE: This function generates the four-frequency variant of the heavy square code. +/// This function implements Fig 10.b left of the `paper `_. +/// This function doesn't support the variant Fig 10.b right. +/// +/// Note that if ``d`` is set to ``1`` a :class:`~rustworkx.PyGraph` with a +/// single node will be returned. +/// +/// :param int d: distance of the code. If ``d`` is set to ``1`` a +/// :class:`~rustworkx.PyGraph` with a single node will be returned. ``d`` must be +/// an odd number. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead calls which would -/// create a parallel edge will update the existing edge. +/// won't allow parallel edges to be added. Instead +/// calls which would create a parallel edge will update the existing edge. /// -/// :returns: A binomial tree with 2^n vertices and 2^n - 1 edges. +/// :returns: The generated heavy square graph /// :rtype: PyGraph -/// :raises IndexError: If the length of ``weights`` is greater that 2^n -/// :raises OverflowError: If the input order exceeds the maximum value for the -/// current platform. +/// :raises IndexError: If d is even. /// /// .. jupyter-execute:: /// /// import rustworkx.generators -/// from rustworkx.visualization import mpl_draw +/// from rustworkx.visualization import graphviz_draw /// -/// graph = rustworkx.generators.binomial_tree_graph(4) -/// mpl_draw(graph) +/// graph = rustworkx.generators.heavy_square_graph(3) +/// graphviz_draw(graph, lambda node: dict( +/// color='black', fillcolor='lightblue', style='filled')) /// #[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(order, /, weights=None, multigraph=True)")] -pub fn binomial_tree_graph( - py: Python, - order: u32, - weights: Option>, - multigraph: bool, -) -> PyResult { - if order >= MAX_ORDER { - return Err(PyOverflowError::new_err(format!( - "An order of {} exceeds the max allowable size", - order - ))); - } +#[pyo3(text_signature = "(d, /, multigraph=True)")] +pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult { let default_fn = || py.None(); let graph: StablePyGraph = - match core_generators::binomial_tree_graph(order, weights, default_fn, default_fn, false) { + match core_generators::heavy_square_graph(d, default_fn, default_fn, false) { Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "num_nodes and weights list not specified", - )) - } + Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), }; Ok(graph::PyGraph { graph, @@ -634,172 +636,42 @@ pub fn binomial_tree_graph( }) } -/// Generate a directed binomial tree of order n recursively. -/// The edges propagate towards right and bottom direction if ``bidirectional`` is ``False`` +/// Generate an directed heavy square graph. Fig. 6 of +/// https://arxiv.org/abs/1907.09528. +/// An ASCII diagram of the graph is given by: /// -/// :param int order: Order of the binomial tree. The maximum allowed value -/// for order on the platform your running on. If it's a 64bit platform -/// the max value is 60 and on 32bit systems the max value is 29. Any order -/// value above these will raise an ``OverflowError``. -/// :param list weights: A list of node weights. If the number of weights is -/// less than 2**order, extra nodes with None will be appended. -/// :param bidirectional: A parameter to indicate if edges should exist in -/// both directions between nodes. Defaults to ``False``. -/// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. +/// .. code-block:: console /// -/// :returns: A directed binomial tree with 2^n vertices and 2^n - 1 edges. -/// :rtype: PyDiGraph -/// :raises IndexError: If the lenght of ``weights`` is greater that 2^n -/// :raises OverflowError: If the input order exceeds the maximum value for the -/// current platform. -/// -/// .. jupyter-execute:: -/// -/// import rustworkx.generators -/// from rustworkx.visualization import mpl_draw -/// -/// graph = rustworkx.generators.directed_binomial_tree_graph(4) -/// mpl_draw(graph) -/// -#[pyfunction(bidirectional = "false", multigraph = "true")] -#[pyo3(text_signature = "(order, /, weights=None, bidirectional=False, multigraph=True)")] -pub fn directed_binomial_tree_graph( - py: Python, - order: u32, - weights: Option>, - bidirectional: bool, - multigraph: bool, -) -> PyResult { - if order >= MAX_ORDER { - return Err(PyOverflowError::new_err(format!( - "An order of {} exceeds the max allowable size", - order - ))); - } - let default_fn = || py.None(); - let graph: StablePyGraph = match core_generators::binomial_tree_graph( - order, - weights, - default_fn, - default_fn, - bidirectional, - ) { - Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "order and weights list not specified", - )) - } - }; - Ok(digraph::PyDiGraph { - graph, - node_removed: false, - check_cycle: false, - cycle_state: algo::DfsSpace::default(), - multigraph, - attrs: py.None(), - }) -} - -/// Creates a full r-ary tree of `n` nodes. -/// Sometimes called a k-ary, n-ary, or m-ary tree. -/// -/// :param int branching factor: The number of children at each node. -/// :param int num_nodes: The number of nodes in the graph. -/// :param list weights: A list of node weights. If the number of weights is -/// less than ``num_nodes``, extra nodes with None will be appended. The -/// number of weights cannot exceed num_nodes. -/// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. -/// -/// :returns: A r-ary tree. -/// :rtype: PyGraph -/// :raises IndexError: If the lenght of ``weights`` is greater that n -/// -/// .. jupyter-execute:: -/// -/// import rustworkx.generators -/// from rustworkx.visualization import mpl_draw -/// -/// graph = rustworkx.generators.full_rary_tree(5, 15) -/// mpl_draw(graph) -/// -#[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(branching_factor, num_nodes, /, weights=None, multigraph=True)")] -pub fn full_rary_tree( - py: Python, - branching_factor: usize, - num_nodes: usize, - weights: Option>, - multigraph: bool, -) -> PyResult { - let default_fn = || py.None(); - let graph: StablePyGraph = match core_generators::full_rary_tree_graph( - branching_factor, - num_nodes, - weights, - default_fn, - default_fn, - ) { - Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "The number of weights cannot exceed num_nodes.", - )) - } - }; - Ok(graph::PyGraph { - graph, - node_removed: false, - multigraph, - attrs: py.None(), - }) -} - -/// Generate an undirected heavy square graph. Fig. 6 of -/// https://arxiv.org/abs/1907.09528. -/// An ASCII diagram of the graph is given by: -/// -/// .. code-block:: console -/// -/// ... S ... -/// \ / \ -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ......... -/// | | | -/// ... D D D ... -/// \ / \ -/// ... S ... +/// ... S ... +/// \ / \ +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// \ / \ +/// ... S ... /// /// NOTE: This function generates the four-frequency variant of the heavy square code. /// This function implements Fig 10.b left of the `paper `_. /// This function doesn't support the variant Fig 10.b right. /// -/// Note that if ``d`` is set to ``1`` a :class:`~rustworkx.PyGraph` with a -/// single node will be returned. -/// /// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyGraph` with a single node will be returned. ``d`` must be +/// :class:`~rustworkx.PyDiGraph` with a single node will be returned. ``d`` must be /// an odd number. /// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and +/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated heavy square graph -/// :rtype: PyGraph +/// :returns: The generated directed heavy square graph +/// :rtype: PyDiGraph /// :raises IndexError: If d is even. /// /// .. jupyter-execute:: @@ -807,63 +679,81 @@ pub fn full_rary_tree( /// import rustworkx.generators /// from rustworkx.visualization import graphviz_draw /// -/// graph = rustworkx.generators.heavy_square_graph(3) +/// graph = rustworkx.generators.directed_heavy_square_graph(3) /// graphviz_draw(graph, lambda node: dict( /// color='black', fillcolor='lightblue', style='filled')) /// -#[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(d, /, multigraph=True)")] -pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult { +#[pyfunction(bidirectional = false, multigraph = true)] +#[pyo3(text_signature = "(d, /, bidirectional=False, multigraph=True)")] +pub fn directed_heavy_square_graph( + py: Python, + d: usize, + bidirectional: bool, + multigraph: bool, +) -> PyResult { let default_fn = || py.None(); - let graph: StablePyGraph = - match core_generators::heavy_square_graph(d, default_fn, default_fn, false) { + let graph: StablePyGraph = + match core_generators::heavy_square_graph(d, default_fn, default_fn, bidirectional) { Ok(graph) => graph, Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), }; - Ok(graph::PyGraph { + Ok(digraph::PyDiGraph { graph, node_removed: false, + check_cycle: false, + cycle_state: algo::DfsSpace::default(), multigraph, attrs: py.None(), }) } -/// Generate an directed heavy square graph. Fig. 6 of -/// https://arxiv.org/abs/1907.09528. +/// Generate an undirected heavy hex graph. Fig. 2 of +/// https://arxiv.org/abs/1907.09528 /// An ASCII diagram of the graph is given by: /// -/// .. code-block:: console +/// .. code-block:: text /// -/// ... S ... -/// \ / \ -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ......... -/// | | | -/// ... D D D ... -/// \ / \ -/// ... S ... +/// ... D-S-D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ... D D-S-D ... /// -/// NOTE: This function generates the four-frequency variant of the heavy square code. -/// This function implements Fig 10.b left of the `paper `_. -/// This function doesn't support the variant Fig 10.b right. /// /// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyDiGraph` with a single node will be returned. ``d`` must be -/// an odd number. +/// :class:`~rustworkx.PyGraph` with a single node will be returned. +/// ``d`` must be an odd number. /// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and +/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated directed heavy square graph -/// :rtype: PyDiGraph +/// :returns: The generated heavy hex graph +/// :rtype: PyGraph /// :raises IndexError: If d is even. /// /// .. jupyter-execute:: @@ -871,35 +761,28 @@ pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult PyResult { +#[pyfunction(multigraph = true)] +#[pyo3(text_signature = "(d, /, multigraph=True)")] +pub fn heavy_hex_graph(py: Python, d: usize, multigraph: bool) -> PyResult { let default_fn = || py.None(); - let graph: StablePyGraph = - match core_generators::heavy_square_graph(d, default_fn, default_fn, bidirectional) { + let graph: StablePyGraph = + match core_generators::heavy_hex_graph(d, default_fn, default_fn, false) { Ok(graph) => graph, Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), }; - Ok(digraph::PyDiGraph { + Ok(graph::PyGraph { graph, node_removed: false, - check_cycle: false, - cycle_state: algo::DfsSpace::default(), multigraph, attrs: py.None(), }) } -/// Generate an undirected heavy hex graph. Fig. 2 of +/// Generate a directed heavy hex graph. Fig. 2 of /// https://arxiv.org/abs/1907.09528 /// An ASCII diagram of the graph is given by: /// @@ -937,15 +820,15 @@ pub fn directed_heavy_square_graph( /// /// /// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyGraph` with a single node will be returned. +/// :class:`~rustworkx.PyDiGraph` with a single node will be returned. /// ``d`` must be an odd number. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated heavy hex graph -/// :rtype: PyGraph +/// :returns: The generated heavy hex directed graph +/// :rtype: PyDiGraph /// :raises IndexError: If d is even. /// /// .. jupyter-execute:: @@ -953,18 +836,90 @@ pub fn directed_heavy_square_graph( /// import rustworkx.generators /// from rustworkx.visualization import graphviz_draw /// -/// graph = rustworkx.generators.heavy_hex_graph(3) +/// graph = rustworkx.generators.directed_heavy_hex_graph(3) /// graphviz_draw(graph, lambda node: dict( /// color='black', fillcolor='lightblue', style='filled')) /// +#[pyfunction(bidirectional = false, multigraph = true)] +#[pyo3(text_signature = "(d, /, bidirectional=False, multigraph=True)")] +pub fn directed_heavy_hex_graph( + py: Python, + d: usize, + bidirectional: bool, + multigraph: bool, +) -> PyResult { + let default_fn = || py.None(); + let graph: StablePyGraph = + match core_generators::heavy_hex_graph(d, default_fn, default_fn, bidirectional) { + Ok(graph) => graph, + Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), + }; + Ok(digraph::PyDiGraph { + graph, + node_removed: false, + check_cycle: false, + cycle_state: algo::DfsSpace::default(), + multigraph, + attrs: py.None(), + }) +} + +// MAX_ORDER is determined based on the pointer width of the target platform +#[cfg(target_pointer_width = "64")] +const MAX_ORDER: u32 = 60; +#[cfg(not(target_pointer_width = "64"))] +const MAX_ORDER: u32 = 29; + +/// Generate an undirected binomial tree of order n recursively. +/// +/// :param int order: Order of the binomial tree. The maximum allowed value +/// for order on the platform your running on. If it's a 64bit platform +/// the max value is 60 and on 32bit systems the max value is 29. Any order +/// value above these will raise an ``OverflowError``. +/// :param list weights: A list of node weights. If the number of weights is +/// less than 2**order, extra nodes with None will be appended. +/// :param bool multigraph: When set to ``False`` the output +/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and +/// won't allow parallel edges to be added. Instead calls which would +/// create a parallel edge will update the existing edge. +/// +/// :returns: A binomial tree with 2^n vertices and 2^n - 1 edges. +/// :rtype: PyGraph +/// :raises IndexError: If the length of ``weights`` is greater that 2^n +/// :raises OverflowError: If the input order exceeds the maximum value for the +/// current platform. +/// +/// .. jupyter-execute:: +/// +/// import rustworkx.generators +/// from rustworkx.visualization import mpl_draw +/// +/// graph = rustworkx.generators.binomial_tree_graph(4) +/// mpl_draw(graph) +/// #[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(d, /, multigraph=True)")] -pub fn heavy_hex_graph(py: Python, d: usize, multigraph: bool) -> PyResult { +#[pyo3(text_signature = "(order, /, weights=None, multigraph=True)")] +pub fn binomial_tree_graph( + py: Python, + order: u32, + weights: Option>, + multigraph: bool, +) -> PyResult { + if order >= MAX_ORDER { + return Err(PyOverflowError::new_err(format!( + "An order of {} exceeds the max allowable size", + order + ))); + } let default_fn = || py.None(); let graph: StablePyGraph = - match core_generators::heavy_hex_graph(d, default_fn, default_fn, false) { + match core_generators::binomial_tree_graph(order, weights, default_fn, default_fn, false) { Ok(graph) => graph, - Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), + Err(_) => { + return Err(PyIndexError::new_err( + "num_nodes and weights list not specified", + )) + } }; Ok(graph::PyGraph { graph, @@ -974,83 +929,128 @@ pub fn heavy_hex_graph(py: Python, d: usize, multigraph: bool) -> PyResult>, + bidirectional: bool, + multigraph: bool, +) -> PyResult { + if order >= MAX_ORDER { + return Err(PyOverflowError::new_err(format!( + "An order of {} exceeds the max allowable size", + order + ))); + } + let default_fn = || py.None(); + let graph: StablePyGraph = match core_generators::binomial_tree_graph( + order, + weights, + default_fn, + default_fn, + bidirectional, + ) { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "order and weights list not specified", + )) + } + }; + Ok(digraph::PyDiGraph { + graph, + node_removed: false, + check_cycle: false, + cycle_state: algo::DfsSpace::default(), + multigraph, + attrs: py.None(), + }) +} + +/// Creates a full r-ary tree of `n` nodes. +/// Sometimes called a k-ary, n-ary, or m-ary tree. /// -/// :param int d: distance of the code. If ``d`` is set to ``1`` a -/// :class:`~rustworkx.PyDiGraph` with a single node will be returned. -/// ``d`` must be an odd number. +/// :param int branching factor: The number of children at each node. +/// :param int num_nodes: The number of nodes in the graph. +/// :param list weights: A list of node weights. If the number of weights is +/// less than ``num_nodes``, extra nodes with None will be appended. The +/// number of weights cannot exceed num_nodes. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: The generated heavy hex directed graph -/// :rtype: PyDiGraph -/// :raises IndexError: If d is even. +/// :returns: A r-ary tree. +/// :rtype: PyGraph +/// :raises IndexError: If the lenght of ``weights`` is greater that n /// /// .. jupyter-execute:: /// /// import rustworkx.generators -/// from rustworkx.visualization import graphviz_draw +/// from rustworkx.visualization import mpl_draw /// -/// graph = rustworkx.generators.directed_heavy_hex_graph(3) -/// graphviz_draw(graph, lambda node: dict( -/// color='black', fillcolor='lightblue', style='filled')) +/// graph = rustworkx.generators.full_rary_tree(5, 15) +/// mpl_draw(graph) /// -#[pyfunction(bidirectional = false, multigraph = true)] -#[pyo3(text_signature = "(d, /, bidirectional=False, multigraph=True)")] -pub fn directed_heavy_hex_graph( +#[pyfunction(multigraph = true)] +#[pyo3(text_signature = "(branching_factor, num_nodes, /, weights=None, multigraph=True)")] +pub fn full_rary_tree( py: Python, - d: usize, - bidirectional: bool, + branching_factor: usize, + num_nodes: usize, + weights: Option>, multigraph: bool, -) -> PyResult { +) -> PyResult { let default_fn = || py.None(); - let graph: StablePyGraph = - match core_generators::heavy_hex_graph(d, default_fn, default_fn, bidirectional) { - Ok(graph) => graph, - Err(_) => return Err(PyIndexError::new_err("d must be an odd number.")), - }; - Ok(digraph::PyDiGraph { + let graph: StablePyGraph = match core_generators::full_rary_tree_graph( + branching_factor, + num_nodes, + weights, + default_fn, + default_fn, + ) { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "The number of weights cannot exceed num_nodes.", + )) + } + }; + Ok(graph::PyGraph { graph, node_removed: false, - check_cycle: false, - cycle_state: algo::DfsSpace::default(), multigraph, attrs: py.None(), }) @@ -1231,6 +1231,77 @@ pub fn lollipop_graph( }) } +/// Generate an undirected barbell graph where two identical complete graphs are +/// connected by a path. +/// +/// If ``num_path_nodes`` (described below) is not specified then this is +/// equivalent to two complete graphs joined together. +/// +/// :param int num_mesh_nodes: The number of nodes to generate the mesh graphs +/// with. Node weights will be None if this is specified. If both +/// ``num_mesh_nodes`` and ``mesh_weights`` are set this will be ignored and +/// ``mesh_weights`` will be used. +/// :param int num_path_nodes: The number of nodes to generate the path +/// with. Node weights will be None if this is specified. If both +/// ``num_path_nodes`` and ``path_weights`` are set this will be ignored and +/// ``path_weights`` will be used. +/// :param bool multigraph: When set to ``False`` the output +/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and +/// won't allow parallel edges to be added. Instead +/// calls which would create a parallel edge will update the existing edge. +/// :param list mesh_weights: A list of node weights for the mesh graph. If both +/// ``num_mesh_nodes`` and ``mesh_weights`` are set ``num_mesh_nodes`` will +/// be ignored and ``mesh_weights`` will be used. +/// :param list path_weights: A list of node weights for the path. If both +/// ``num_path_nodes`` and ``path_weights`` are set ``num_path_nodes`` will +/// be ignored and ``path_weights`` will be used. +/// +/// :returns: The generated barbell graph +/// :rtype: PyGraph +/// :raises IndexError: If ``num_mesh_nodes`` is not specified +/// +/// .. jupyter-execute:: +/// +/// import rustworkx.generators +/// from rustworkx.visualization import mpl_draw +/// +/// graph = rustworkx.generators.barbell_graph(4, 2) +/// mpl_draw(graph) +/// +#[pyfunction(multigraph = true)] +#[pyo3(text_signature = "(/, num_mesh_nodes=None, num_path_nodes=None, multigraph=True)")] +pub fn barbell_graph( + py: Python, + num_mesh_nodes: Option, + num_path_nodes: Option, + multigraph: bool, + mesh_weights: Option>, + path_weights: Option>, +) -> PyResult { + let default_fn = || py.None(); + let graph: StablePyGraph = match core_generators::barbell_graph( + num_mesh_nodes, + num_path_nodes, + mesh_weights, + path_weights, + default_fn, + default_fn, + ) { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "num_nodes and weights list not specified", + )) + } + }; + Ok(graph::PyGraph { + graph, + node_removed: false, + multigraph, + attrs: py.None(), + }) +} + /// Generate a generalized Petersen graph :math:`G(n, k)` with :math:`2n` /// nodes and :math:`3n` edges. See Watkins [1]_ for more details. /// @@ -1303,77 +1374,6 @@ pub fn generalized_petersen_graph( }) } -/// Generate an undirected barbell graph where two identical complete graphs are -/// connected by a path. -/// -/// If ``num_path_nodes`` (described below) is not specified then this is -/// equivalent to two complete graphs joined together. -/// -/// :param int num_mesh_nodes: The number of nodes to generate the mesh graphs -/// with. Node weights will be None if this is specified. If both -/// ``num_mesh_nodes`` and ``mesh_weights`` are set this will be ignored and -/// ``mesh_weights`` will be used. -/// :param int num_path_nodes: The number of nodes to generate the path -/// with. Node weights will be None if this is specified. If both -/// ``num_path_nodes`` and ``path_weights`` are set this will be ignored and -/// ``path_weights`` will be used. -/// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead -/// calls which would create a parallel edge will update the existing edge. -/// :param list mesh_weights: A list of node weights for the mesh graph. If both -/// ``num_mesh_nodes`` and ``mesh_weights`` are set ``num_mesh_nodes`` will -/// be ignored and ``mesh_weights`` will be used. -/// :param list path_weights: A list of node weights for the path. If both -/// ``num_path_nodes`` and ``path_weights`` are set ``num_path_nodes`` will -/// be ignored and ``path_weights`` will be used. -/// -/// :returns: The generated barbell graph -/// :rtype: PyGraph -/// :raises IndexError: If ``num_mesh_nodes`` is not specified -/// -/// .. jupyter-execute:: -/// -/// import rustworkx.generators -/// from rustworkx.visualization import mpl_draw -/// -/// graph = rustworkx.generators.barbell_graph(4, 2) -/// mpl_draw(graph) -/// -#[pyfunction(multigraph = true)] -#[pyo3(text_signature = "(/, num_mesh_nodes=None, num_path_nodes=None, multigraph=True)")] -pub fn barbell_graph( - py: Python, - num_mesh_nodes: Option, - num_path_nodes: Option, - multigraph: bool, - mesh_weights: Option>, - path_weights: Option>, -) -> PyResult { - let default_fn = || py.None(); - let graph: StablePyGraph = match core_generators::barbell_graph( - num_mesh_nodes, - num_path_nodes, - mesh_weights, - path_weights, - default_fn, - default_fn, - ) { - Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "num_nodes and weights list not specified", - )) - } - }; - Ok(graph::PyGraph { - graph, - node_removed: false, - multigraph, - attrs: py.None(), - }) -} - /// Generate an undirected empty graph with ``n`` nodes and no edges. /// /// :param int n: The number of nodes to generate the graph with. @@ -1572,12 +1572,12 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(directed_heavy_hex_graph))?; m.add_wrapped(wrap_pyfunction!(binomial_tree_graph))?; m.add_wrapped(wrap_pyfunction!(directed_binomial_tree_graph))?; + m.add_wrapped(wrap_pyfunction!(full_rary_tree))?; m.add_wrapped(wrap_pyfunction!(hexagonal_lattice_graph))?; m.add_wrapped(wrap_pyfunction!(directed_hexagonal_lattice_graph))?; m.add_wrapped(wrap_pyfunction!(lollipop_graph))?; - m.add_wrapped(wrap_pyfunction!(full_rary_tree))?; - m.add_wrapped(wrap_pyfunction!(generalized_petersen_graph))?; m.add_wrapped(wrap_pyfunction!(barbell_graph))?; + m.add_wrapped(wrap_pyfunction!(generalized_petersen_graph))?; m.add_wrapped(wrap_pyfunction!(empty_graph))?; m.add_wrapped(wrap_pyfunction!(directed_empty_graph))?; m.add_wrapped(wrap_pyfunction!(complete_graph))?; From 52a2e9c85a535d4ed7e8b5d05d3abdc69cb5115b Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Sun, 15 Jan 2023 13:53:32 -0800 Subject: [PATCH 08/15] Switch binomial tree to update_edge --- .../src/generators/binomial_tree_graph.rs | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/rustworkx-core/src/generators/binomial_tree_graph.rs b/rustworkx-core/src/generators/binomial_tree_graph.rs index 4ee04b47d..af93ee9a8 100644 --- a/rustworkx-core/src/generators/binomial_tree_graph.rs +++ b/rustworkx-core/src/generators/binomial_tree_graph.rs @@ -103,22 +103,6 @@ where None => graph.add_node(default_node_weight()), }; } - - fn find_edge(graph: &mut G, source: usize, target: usize) -> bool - where - G: NodeIndexable, - for<'b> &'b G: GraphBase + IntoEdgeReferences, - { - let mut found = false; - for edge in graph.edge_references() { - if graph.to_index(edge.source()) == source && graph.to_index(edge.target()) == target { - found = true; - break; - } - } - found - } - let mut n = 1; let zero_index = 0; for _ in 0..order { @@ -131,30 +115,26 @@ where let source_index = source + n; let target_index = target + n; - if !find_edge(&mut graph, source_index, target_index) { - graph.add_edge( - graph.from_index(source_index), - graph.from_index(target_index), - default_edge_weight(), - ); - } - if bidirectional && !find_edge(&mut graph, target_index, source_index) { - graph.add_edge( + graph.update_edge( + graph.from_index(source_index), + graph.from_index(target_index), + default_edge_weight(), + ); + if bidirectional { + graph.update_edge( graph.from_index(target_index), graph.from_index(source_index), default_edge_weight(), ); } } - if !find_edge(&mut graph, zero_index, n) { - graph.add_edge( - graph.from_index(zero_index), - graph.from_index(n), - default_edge_weight(), - ); - } - if bidirectional && !find_edge(&mut graph, n, zero_index) { - graph.add_edge( + graph.update_edge( + graph.from_index(zero_index), + graph.from_index(n), + default_edge_weight(), + ); + if bidirectional { + graph.update_edge( graph.from_index(n), graph.from_index(zero_index), default_edge_weight(), From 12fb467de782a116a42dba57ab1b4bc7c2c0fb47 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Mon, 16 Jan 2023 15:11:24 -0800 Subject: [PATCH 09/15] Update bidirectional docs --- src/generators.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/generators.rs b/src/generators.rs index 8e695fa8c..abf27c7a4 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -665,6 +665,8 @@ pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult Date: Wed, 18 Jan 2023 15:43:32 -0800 Subject: [PATCH 10/15] Cleanup rest of docs and return find_edge in binomial tree --- .../src/generators/barbell_graph.rs | 4 +- .../src/generators/binomial_tree_graph.rs | 48 +++++++++++++------ .../src/generators/heavy_hex_graph.rs | 9 ++-- .../src/generators/heavy_square_graph.rs | 17 ++++--- .../src/generators/lollipop_graph.rs | 5 +- .../src/generators/petersen_graph.rs | 8 ++-- 6 files changed, 51 insertions(+), 40 deletions(-) diff --git a/rustworkx-core/src/generators/barbell_graph.rs b/rustworkx-core/src/generators/barbell_graph.rs index 85d91ddad..aaa7a7b70 100644 --- a/rustworkx-core/src/generators/barbell_graph.rs +++ b/rustworkx-core/src/generators/barbell_graph.rs @@ -19,11 +19,9 @@ use super::utils::get_num_nodes; use super::utils::pairwise; use super::InvalidInputError; -/// Generate an undirected barbell graph where two identical complete graphs are +/// Generate a barbell graph where two identical complete graphs are /// connected by a path. /// -/// .. note:: -/// /// If neither `num_path_nodes` nor `path_weights` (described below) are /// specified, then this is equivalent to two complete graphs joined together. /// diff --git a/rustworkx-core/src/generators/binomial_tree_graph.rs b/rustworkx-core/src/generators/binomial_tree_graph.rs index af93ee9a8..4ee04b47d 100644 --- a/rustworkx-core/src/generators/binomial_tree_graph.rs +++ b/rustworkx-core/src/generators/binomial_tree_graph.rs @@ -103,6 +103,22 @@ where None => graph.add_node(default_node_weight()), }; } + + fn find_edge(graph: &mut G, source: usize, target: usize) -> bool + where + G: NodeIndexable, + for<'b> &'b G: GraphBase + IntoEdgeReferences, + { + let mut found = false; + for edge in graph.edge_references() { + if graph.to_index(edge.source()) == source && graph.to_index(edge.target()) == target { + found = true; + break; + } + } + found + } + let mut n = 1; let zero_index = 0; for _ in 0..order { @@ -115,26 +131,30 @@ where let source_index = source + n; let target_index = target + n; - graph.update_edge( - graph.from_index(source_index), - graph.from_index(target_index), - default_edge_weight(), - ); - if bidirectional { - graph.update_edge( + if !find_edge(&mut graph, source_index, target_index) { + graph.add_edge( + graph.from_index(source_index), + graph.from_index(target_index), + default_edge_weight(), + ); + } + if bidirectional && !find_edge(&mut graph, target_index, source_index) { + graph.add_edge( graph.from_index(target_index), graph.from_index(source_index), default_edge_weight(), ); } } - graph.update_edge( - graph.from_index(zero_index), - graph.from_index(n), - default_edge_weight(), - ); - if bidirectional { - graph.update_edge( + if !find_edge(&mut graph, zero_index, n) { + graph.add_edge( + graph.from_index(zero_index), + graph.from_index(n), + default_edge_weight(), + ); + } + if bidirectional && !find_edge(&mut graph, n, zero_index) { + graph.add_edge( graph.from_index(n), graph.from_index(zero_index), default_edge_weight(), diff --git a/rustworkx-core/src/generators/heavy_hex_graph.rs b/rustworkx-core/src/generators/heavy_hex_graph.rs index 0a6b9c5cd..6dcfc04f5 100644 --- a/rustworkx-core/src/generators/heavy_hex_graph.rs +++ b/rustworkx-core/src/generators/heavy_hex_graph.rs @@ -17,13 +17,12 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -/// Generate an undirected heavy hex graph. Fig. 2 of -/// https://arxiv.org/abs/1907.09528 -/// An ASCII diagram of the graph is given by: +/// Generate a heavy hex graph. /// -/// .. note:: +/// Fig. 2 of +/// An ASCII diagram of the graph is given by: /// -/// ... D-S-D D ... +/// ... D-S-D D ... /// | | | /// ...-F F-S-F ... /// | | | diff --git a/rustworkx-core/src/generators/heavy_square_graph.rs b/rustworkx-core/src/generators/heavy_square_graph.rs index 9dfa86171..178119862 100644 --- a/rustworkx-core/src/generators/heavy_square_graph.rs +++ b/rustworkx-core/src/generators/heavy_square_graph.rs @@ -17,14 +17,13 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -/// Generate an directed heavy square graph. Fig. 6 of -/// https://arxiv.org/abs/1907.09528. -/// An ASCII diagram of the graph is given by: +/// Generate a heavy square graph. /// -/// .. note:: +/// Fig. 6 of +/// An ASCII diagram of the graph is given by: /// -/// ... S ... -/// \ / \ +/// ... S ... +/// | / | /// ... D D D ... /// | | | /// ... F-S-F-S-F-... @@ -36,11 +35,11 @@ use super::InvalidInputError; /// ......... /// | | | /// ... D D D ... -/// \ / \ -/// ... S ... +/// | / | +/// ... S ... /// /// NOTE: This function generates the four-frequency variant of the heavy square code. -/// This function implements Fig 10.b left of the `paper `_. +/// This function implements Fig 10.b left of the paper . /// This function doesn't support the variant Fig 10.b right. /// /// Arguments: diff --git a/rustworkx-core/src/generators/lollipop_graph.rs b/rustworkx-core/src/generators/lollipop_graph.rs index ce32d6e8e..e47463a1f 100644 --- a/rustworkx-core/src/generators/lollipop_graph.rs +++ b/rustworkx-core/src/generators/lollipop_graph.rs @@ -18,10 +18,7 @@ use petgraph::visit::{Data, GraphProp, NodeIndexable}; use super::utils::{get_num_nodes, pairwise}; use super::InvalidInputError; -/// Generate an undirected lollipop graph where a complete graph is connected to a -/// path. -/// -/// .. note:: +/// Generate a lollipop graph where a complete graph is connected to a path. /// /// If neither `num_path_nodes` nor `path_weights` (described below) are /// specified, then this is equivalent to a complete graph. diff --git a/rustworkx-core/src/generators/petersen_graph.rs b/rustworkx-core/src/generators/petersen_graph.rs index 546c93f64..170894e30 100644 --- a/rustworkx-core/src/generators/petersen_graph.rs +++ b/rustworkx-core/src/generators/petersen_graph.rs @@ -17,12 +17,10 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -/// Generate a generalized Petersen graph :math:`G(n, k)` with :math:`2n` -/// nodes and :math:`3n` edges. +/// Generate a generalized Petersen graph `G(n, k)` with `2n` +/// nodes and `3n` edges. /// -/// .. note:: -/// -/// The Petersen graph itself is denoted :math:`G(5, 2)` +/// The Petersen graph itself is denoted `G(5, 2)` /// /// * `n` - Number of nodes in the internal star and external regular polygon. /// n > 2. From b0e4dfc044c1db120755be7d4a4c82b6c574b412 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Wed, 18 Jan 2023 16:19:22 -0800 Subject: [PATCH 11/15] Second round on heavy docs --- .../src/generators/heavy_hex_graph.rs | 62 +++++++++---------- .../src/generators/heavy_square_graph.rs | 34 +++++----- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/rustworkx-core/src/generators/heavy_hex_graph.rs b/rustworkx-core/src/generators/heavy_hex_graph.rs index 6dcfc04f5..abe3a3203 100644 --- a/rustworkx-core/src/generators/heavy_hex_graph.rs +++ b/rustworkx-core/src/generators/heavy_hex_graph.rs @@ -21,37 +21,37 @@ use super::InvalidInputError; /// /// Fig. 2 of /// An ASCII diagram of the graph is given by: -/// -/// ... D-S-D D ... -/// | | | -/// ...-F F-S-F ... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F F-... -/// | | | -/// ......... -/// | | | -/// ... D D D ... -/// | | | -/// ...-F F-S-F ... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F F-... -/// | | | -/// ......... -/// | | | -/// ... D D D ... -/// | | | -/// ...-F F-S-F ... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F F-... -/// | | | -/// ... D D-S-D ... -/// +/// ```text +/// ... D-S-D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// | | | +/// ...-F F-S-F ... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F F-... +/// | | | +/// ... D D-S-D ... +///``` /// /// Arguments: /// diff --git a/rustworkx-core/src/generators/heavy_square_graph.rs b/rustworkx-core/src/generators/heavy_square_graph.rs index 178119862..52777f8ea 100644 --- a/rustworkx-core/src/generators/heavy_square_graph.rs +++ b/rustworkx-core/src/generators/heavy_square_graph.rs @@ -21,23 +21,23 @@ use super::InvalidInputError; /// /// Fig. 6 of /// An ASCII diagram of the graph is given by: -/// -/// ... S ... -/// | / | -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ... D D D ... -/// | | | -/// ... F-S-F-S-F-... -/// | | | -/// ......... -/// | | | -/// ... D D D ... -/// | / | -/// ... S ... -/// +/// ```text +/// ... S ... +/// \ / \ +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ... D D D ... +/// | | | +/// ... F-S-F-S-F-... +/// | | | +/// ......... +/// | | | +/// ... D D D ... +/// \ / \ +/// ... S ... +/// ``` /// NOTE: This function generates the four-frequency variant of the heavy square code. /// This function implements Fig 10.b left of the paper . /// This function doesn't support the variant Fig 10.b right. From 4b8f1ae71ebe06603d157cbee1d781bb714b1f81 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Sun, 22 Jan 2023 14:39:39 -0800 Subject: [PATCH 12/15] Minor doc change --- rustworkx-core/src/generators/full_rary_tree_graph.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustworkx-core/src/generators/full_rary_tree_graph.rs b/rustworkx-core/src/generators/full_rary_tree_graph.rs index f8910d33d..932038ea7 100644 --- a/rustworkx-core/src/generators/full_rary_tree_graph.rs +++ b/rustworkx-core/src/generators/full_rary_tree_graph.rs @@ -18,7 +18,7 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -/// Creates a full r-ary tree of `n` nodes. +/// Generate a full r-ary tree of `n` nodes. /// Sometimes called a k-ary, n-ary, or m-ary tree. /// /// Arguments: From 5c3ea62972b3d9adcf62367ae55c14c030a8a270 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Wed, 1 Feb 2023 08:57:27 -0800 Subject: [PATCH 13/15] Make core utils and cleanup docs --- .../src/generators/barbell_graph.rs | 2 +- .../src/generators/lollipop_graph.rs | 3 +- rustworkx-core/src/generators/mod.rs | 2 +- rustworkx-core/src/generators/utils.rs | 10 ---- rustworkx-core/src/lib.rs | 1 + rustworkx-core/src/utils.rs | 21 ++++++++ src/generators.rs | 50 ++++++++++++------- src/steiner_tree.rs | 2 +- 8 files changed, 59 insertions(+), 32 deletions(-) create mode 100644 rustworkx-core/src/utils.rs diff --git a/rustworkx-core/src/generators/barbell_graph.rs b/rustworkx-core/src/generators/barbell_graph.rs index aaa7a7b70..843c7ca7a 100644 --- a/rustworkx-core/src/generators/barbell_graph.rs +++ b/rustworkx-core/src/generators/barbell_graph.rs @@ -15,8 +15,8 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, NodeIndexable, NodeRef}; +use crate::utils::pairwise; use super::utils::get_num_nodes; -use super::utils::pairwise; use super::InvalidInputError; /// Generate a barbell graph where two identical complete graphs are diff --git a/rustworkx-core/src/generators/lollipop_graph.rs b/rustworkx-core/src/generators/lollipop_graph.rs index e47463a1f..4972593af 100644 --- a/rustworkx-core/src/generators/lollipop_graph.rs +++ b/rustworkx-core/src/generators/lollipop_graph.rs @@ -15,7 +15,8 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, GraphProp, NodeIndexable}; -use super::utils::{get_num_nodes, pairwise}; +use crate::utils::pairwise; +use super::utils::get_num_nodes; use super::InvalidInputError; /// Generate a lollipop graph where a complete graph is connected to a path. diff --git a/rustworkx-core/src/generators/mod.rs b/rustworkx-core/src/generators/mod.rs index a5e3b9f3d..40237685d 100644 --- a/rustworkx-core/src/generators/mod.rs +++ b/rustworkx-core/src/generators/mod.rs @@ -26,7 +26,7 @@ mod path_graph; mod petersen_graph; mod star_graph; -pub mod utils; +mod utils; use std::{error::Error, fmt}; diff --git a/rustworkx-core/src/generators/utils.rs b/rustworkx-core/src/generators/utils.rs index 3eb178fb5..b63ab7043 100644 --- a/rustworkx-core/src/generators/utils.rs +++ b/rustworkx-core/src/generators/utils.rs @@ -10,8 +10,6 @@ // License for the specific language governing permissions and limitations // under the License. -use std::iter; - #[inline] pub fn get_num_nodes(num_nodes: &Option, weights: &Option>) -> usize { if weights.is_some() { @@ -20,11 +18,3 @@ pub fn get_num_nodes(num_nodes: &Option, weights: &Option>) -> num_nodes.unwrap() } } - -pub fn pairwise(right: I) -> impl Iterator, I::Item)> -where - I: IntoIterator + Clone, -{ - let left = iter::once(None).chain(right.clone().into_iter().map(Some)); - left.zip(right) -} diff --git a/rustworkx-core/src/lib.rs b/rustworkx-core/src/lib.rs index 2dc7f7b8c..ea21d2a61 100644 --- a/rustworkx-core/src/lib.rs +++ b/rustworkx-core/src/lib.rs @@ -81,6 +81,7 @@ pub mod traversal; // These modules define additional data structures pub mod dictmap; pub mod distancemap; +pub mod utils; mod min_scored; // re-export petgraph so there is a consistent version available to users and diff --git a/rustworkx-core/src/utils.rs b/rustworkx-core/src/utils.rs new file mode 100644 index 000000000..d8a4f300d --- /dev/null +++ b/rustworkx-core/src/utils.rs @@ -0,0 +1,21 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +use std::iter; + +pub fn pairwise(right: I) -> impl Iterator, I::Item)> +where + I: IntoIterator + Clone, +{ + let left = iter::once(None).chain(right.clone().into_iter().map(Some)); + left.zip(right) +} diff --git a/src/generators.rs b/src/generators.rs index abf27c7a4..0a5afefc8 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -500,8 +500,9 @@ pub fn grid_graph( }) } -/// Generate a directed grid graph. The edges propagate towards right and -/// bottom direction if ``bidirectional`` is ``False`` +/// Generate a directed grid graph. +/// +/// The edges propagate towards right and bottom direction if ``bidirectional`` is ``False`` /// /// :param int rows: The number of rows to generate the graph with. /// If specified, ``cols`` also need to be specified. @@ -569,8 +570,9 @@ pub fn directed_grid_graph( }) } -/// Generate an undirected heavy square graph. Fig. 6 of -/// https://arxiv.org/abs/1907.09528. +/// Generate an undirected heavy square graph. +/// +/// Fig. 6 of https://arxiv.org/abs/1907.09528. /// An ASCII diagram of the graph is given by: /// /// .. code-block:: console @@ -591,9 +593,12 @@ pub fn directed_grid_graph( /// \ / \ /// ... S ... /// -/// NOTE: This function generates the four-frequency variant of the heavy square code. -/// This function implements Fig 10.b left of the `paper `_. -/// This function doesn't support the variant Fig 10.b right. +/// +/// .. note:: +/// +/// This function generates the four-frequency variant of the heavy square code. +/// This function implements Fig 10.b left of the `paper `_. +/// This function doesn't support the variant Fig 10.b right. /// /// Note that if ``d`` is set to ``1`` a :class:`~rustworkx.PyGraph` with a /// single node will be returned. @@ -636,8 +641,9 @@ pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult PyResult`_. -/// This function doesn't support the variant Fig 10.b right. +/// +/// .. note:: +/// +/// This function generates the four-frequency variant of the heavy square code. +/// This function implements Fig 10.b left of the `paper `_. +/// This function doesn't support the variant Fig 10.b right. /// /// :param int d: distance of the code. If ``d`` is set to ``1`` a /// :class:`~rustworkx.PyDiGraph` with a single node will be returned. ``d`` must be @@ -709,8 +718,9 @@ pub fn directed_heavy_square_graph( }) } -/// Generate an undirected heavy hex graph. Fig. 2 of -/// https://arxiv.org/abs/1907.09528 +/// Generate an undirected heavy hex graph. +/// +/// Fig. 2 of https://arxiv.org/abs/1907.09528 /// An ASCII diagram of the graph is given by: /// /// .. code-block:: text @@ -786,8 +796,9 @@ pub fn heavy_hex_graph(py: Python, d: usize, multigraph: bool) -> PyResult Date: Wed, 1 Feb 2023 09:04:43 -0800 Subject: [PATCH 14/15] Fmt --- rustworkx-core/src/generators/barbell_graph.rs | 2 +- rustworkx-core/src/generators/lollipop_graph.rs | 2 +- rustworkx-core/src/lib.rs | 2 +- src/steiner_tree.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rustworkx-core/src/generators/barbell_graph.rs b/rustworkx-core/src/generators/barbell_graph.rs index 843c7ca7a..74d6f56f1 100644 --- a/rustworkx-core/src/generators/barbell_graph.rs +++ b/rustworkx-core/src/generators/barbell_graph.rs @@ -15,9 +15,9 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, NodeIndexable, NodeRef}; -use crate::utils::pairwise; use super::utils::get_num_nodes; use super::InvalidInputError; +use crate::utils::pairwise; /// Generate a barbell graph where two identical complete graphs are /// connected by a path. diff --git a/rustworkx-core/src/generators/lollipop_graph.rs b/rustworkx-core/src/generators/lollipop_graph.rs index 4972593af..dee8a7a7f 100644 --- a/rustworkx-core/src/generators/lollipop_graph.rs +++ b/rustworkx-core/src/generators/lollipop_graph.rs @@ -15,9 +15,9 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, GraphProp, NodeIndexable}; -use crate::utils::pairwise; use super::utils::get_num_nodes; use super::InvalidInputError; +use crate::utils::pairwise; /// Generate a lollipop graph where a complete graph is connected to a path. /// diff --git a/rustworkx-core/src/lib.rs b/rustworkx-core/src/lib.rs index ea21d2a61..4da244f5c 100644 --- a/rustworkx-core/src/lib.rs +++ b/rustworkx-core/src/lib.rs @@ -81,8 +81,8 @@ pub mod traversal; // These modules define additional data structures pub mod dictmap; pub mod distancemap; -pub mod utils; mod min_scored; +pub mod utils; // re-export petgraph so there is a consistent version available to users and // then only need to require rustworkx-core in their dependencies diff --git a/src/steiner_tree.rs b/src/steiner_tree.rs index 75d7e1309..4c3fde3ff 100644 --- a/src/steiner_tree.rs +++ b/src/steiner_tree.rs @@ -28,8 +28,8 @@ use crate::is_valid_weight; use crate::shortest_path::all_pairs_dijkstra::all_pairs_dijkstra_shortest_paths; use rustworkx_core::dictmap::*; -use rustworkx_core::utils::pairwise; use rustworkx_core::shortest_path::dijkstra; +use rustworkx_core::utils::pairwise; struct MetricClosureEdge { source: usize, From cc8be5068634deba5c1cf6685594abb30f6c206b Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Sat, 4 Feb 2023 07:33:05 -0800 Subject: [PATCH 15/15] Text and PyGraph fixes --- src/generators.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index ee63f1211..f8168d0c7 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -32,7 +32,7 @@ use rustworkx_core::generators as core_generators; /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// /// :returns: The generated cycle graph @@ -150,7 +150,7 @@ pub fn directed_cycle_graph( /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// /// :returns: The generated path graph @@ -267,7 +267,7 @@ pub fn directed_path_graph( /// will be the center node of the star graph. If both ``num_nodes`` and /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output -/// :class:`~rustworkx.PyDiGraph` object will not be not be a multigraph and +/// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// @@ -400,7 +400,7 @@ pub fn directed_star_graph( /// ``weights`` are set this will be ignored and ``weights`` will be used. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// /// :returns: The generated mesh graph @@ -483,7 +483,7 @@ pub fn directed_mesh_graph( /// weights list, extra nodes with None weight are appended. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// /// :returns: The generated grid graph @@ -634,7 +634,7 @@ pub fn directed_grid_graph( /// an odd number. /// :param bool multigraph: When set to ``False`` the output /// :class:`~rustworkx.PyGraph` object will not be not be a multigraph and -/// won't allow parallel edges to be added. Instead +/// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// /// :returns: The generated heavy square graph @@ -707,7 +707,7 @@ pub fn heavy_square_graph(py: Python, d: usize, multigraph: bool) -> PyResult PyResult