From f21aef61dacc124ae4663e15d24ac80246d614df Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 17:45:00 -0400 Subject: [PATCH 01/19] Karate club draft --- rustworkx-core/src/generators/karate_club.rs | 30 ++++++++++++++++++++ rustworkx-core/src/generators/mod.rs | 2 ++ src/generators.rs | 22 ++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 rustworkx-core/src/generators/karate_club.rs diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs new file mode 100644 index 0000000000..73642629cc --- /dev/null +++ b/rustworkx-core/src/generators/karate_club.rs @@ -0,0 +1,30 @@ +// 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 petgraph::data::{Build, Create}; +use petgraph::visit::{Data, NodeIndexable}; + +use super::InvalidInputError; + +pub fn karate_club( +) -> Result +where + G: Build + Create + Data + NodeIndexable, + G::NodeId: Eq + Hash, +{ + let n = 34; + let m = 78; + let graph = G::with_capacity(n, m); + Ok(graph) +} \ No newline at end of file diff --git a/rustworkx-core/src/generators/mod.rs b/rustworkx-core/src/generators/mod.rs index 6c0af1ace3..7dbc045494 100644 --- a/rustworkx-core/src/generators/mod.rs +++ b/rustworkx-core/src/generators/mod.rs @@ -22,6 +22,7 @@ mod grid_graph; mod heavy_hex_graph; mod heavy_square_graph; mod hexagonal_lattice_graph; +mod karate_club; mod lollipop_graph; mod path_graph; mod petersen_graph; @@ -55,6 +56,7 @@ pub use grid_graph::grid_graph; pub use heavy_hex_graph::heavy_hex_graph; pub use heavy_square_graph::heavy_square_graph; pub use hexagonal_lattice_graph::{hexagonal_lattice_graph, hexagonal_lattice_graph_weighted}; +pub use karate_club::karate_club; pub use lollipop_graph::lollipop_graph; pub use path_graph::path_graph; pub use petersen_graph::petersen_graph; diff --git a/src/generators.rs b/src/generators.rs index ac8088d12b..d98d93bc5f 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1715,6 +1715,27 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult PyResult { + let graph: StablePyGraph = match core_generators::karate_club() { + Ok(graph) => graph, + Err(_) => { + return Err(PyIndexError::new_err( + "error generating Karate club graph", + )) + } + }; + Ok(graph::PyGraph { + graph, + node_removed: false, + multigraph: multigraph, + attrs: py.None(), + }) +} + #[pymodule] pub fn generators(_py: Python, m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(cycle_graph))?; @@ -1744,5 +1765,6 @@ pub fn generators(_py: Python, m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(complete_graph))?; m.add_wrapped(wrap_pyfunction!(directed_complete_graph))?; m.add_wrapped(wrap_pyfunction!(dorogovtsev_goltsev_mendes_graph))?; + m.add_wrapped(wrap_pyfunction!(karate_club))?; Ok(()) } From 559844aff45bc035fa8e380f7b838654676a2e21 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 20:32:29 -0400 Subject: [PATCH 02/19] Add Zachary's data --- rustworkx-core/src/generators/karate_club.rs | 63 ++++++++++++++++++-- rustworkx-core/src/generators/mod.rs | 2 +- src/generators.rs | 18 +++--- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 73642629cc..126c0bc0ed 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -17,14 +17,67 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -pub fn karate_club( +const ZACHARY: &str = "\ +0 4 5 3 3 3 3 2 2 0 2 3 2 3 0 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 2 0 0\n\ +4 0 6 3 0 0 0 4 0 0 0 0 0 5 0 0 0 1 0 2 0 2 0 0 0 0 0 0 0 0 2 0 0 0\n\ +5 6 0 3 0 0 0 4 5 1 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 3 0\n\ +3 3 3 0 0 0 0 3 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +3 0 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +3 0 0 0 0 0 5 0 0 0 3 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +3 0 0 0 2 5 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +2 4 4 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +2 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 4 3\n\ +0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2\n\ +2 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +3 5 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 4\n\ +0 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2\n\ +2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 1\n\ +2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 4 0 2 0 0 5 4\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 3 0 0 0 2 0 0\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 2 0 0 0 0 0 0 7 0 0\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 2\n\ +0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 3 0 0 0 0 0 0 0 0 4\n\ +0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2\n\ +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 3 2\n\ +0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3\n\ +2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 7 0 0 2 0 0 0 4 4\n\ +0 0 2 0 0 0 0 0 3 0 0 0 0 0 3 3 0 0 1 0 3 0 2 5 0 0 0 0 0 4 3 4 0 5\n\ +0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0\n"; + +pub fn karate_club_graph( + 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, { - let n = 34; - let m = 78; - let graph = G::with_capacity(n, m); + let mut graph = G::with_capacity(0, 0); + let mut node_indices = Vec::new(); + for (row, line) in ZACHARY.split('\n').enumerate() { + let node_id = graph.add_node(default_node_weight()); + node_indices.push(node_id); + let this_row: Vec = line + .split_whitespace() + .map(|b| b.parse::().unwrap()) + .collect(); + + for (col, entry) in this_row.iter().enumerate() { + if *entry >= 1 && row > col { + graph.add_edge(node_indices[row], node_indices[col], default_edge_weight()); + } + } + } Ok(graph) -} \ No newline at end of file +} diff --git a/rustworkx-core/src/generators/mod.rs b/rustworkx-core/src/generators/mod.rs index 7dbc045494..d7a5ddd837 100644 --- a/rustworkx-core/src/generators/mod.rs +++ b/rustworkx-core/src/generators/mod.rs @@ -56,7 +56,7 @@ pub use grid_graph::grid_graph; pub use heavy_hex_graph::heavy_hex_graph; pub use heavy_square_graph::heavy_square_graph; pub use hexagonal_lattice_graph::{hexagonal_lattice_graph, hexagonal_lattice_graph_weighted}; -pub use karate_club::karate_club; +pub use karate_club::karate_club_graph; pub use lollipop_graph::lollipop_graph; pub use path_graph::path_graph; pub use petersen_graph::petersen_graph; diff --git a/src/generators.rs b/src/generators.rs index d98d93bc5f..2f11b4cfba 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1719,15 +1719,13 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult PyResult { - let graph: StablePyGraph = match core_generators::karate_club() { - Ok(graph) => graph, - Err(_) => { - return Err(PyIndexError::new_err( - "error generating Karate club graph", - )) - } - }; +pub fn karate_club_graph(py: Python, multigraph: bool) -> PyResult { + let default_node_fn = || py.None(); + let graph: StablePyGraph = + match core_generators::karate_club_graph(default_node_fn, default_node_fn) { + Ok(graph) => graph, + Err(_) => return Err(PyIndexError::new_err("error generating Karate club graph")), + }; Ok(graph::PyGraph { graph, node_removed: false, @@ -1765,6 +1763,6 @@ pub fn generators(_py: Python, m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(complete_graph))?; m.add_wrapped(wrap_pyfunction!(directed_complete_graph))?; m.add_wrapped(wrap_pyfunction!(dorogovtsev_goltsev_mendes_graph))?; - m.add_wrapped(wrap_pyfunction!(karate_club))?; + m.add_wrapped(wrap_pyfunction!(karate_club_graph))?; Ok(()) } From 8c75e64b736493d39d5e0703075adb2f581d4039 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 20:37:02 -0400 Subject: [PATCH 03/19] Consider weight for Karate Club --- rustworkx-core/src/generators/karate_club.rs | 8 ++++++-- src/generators.rs | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 126c0bc0ed..b226c958a9 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -60,7 +60,7 @@ pub fn karate_club_graph( where G: Build + Create + Data + NodeIndexable, F: FnMut() -> T, - H: FnMut() -> M, + H: FnMut(usize) -> M, G::NodeId: Eq + Hash, { let mut graph = G::with_capacity(0, 0); @@ -75,7 +75,11 @@ where for (col, entry) in this_row.iter().enumerate() { if *entry >= 1 && row > col { - graph.add_edge(node_indices[row], node_indices[col], default_edge_weight()); + graph.add_edge( + node_indices[row], + node_indices[col], + default_edge_weight(*entry), + ); } } } diff --git a/src/generators.rs b/src/generators.rs index 2f11b4cfba..ab149409eb 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1721,8 +1721,9 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult PyResult { let default_node_fn = || py.None(); + let default_edge_fn = |w: usize| w.to_object(py); let graph: StablePyGraph = - match core_generators::karate_club_graph(default_node_fn, default_node_fn) { + match core_generators::karate_club_graph(default_node_fn, default_edge_fn) { Ok(graph) => graph, Err(_) => return Err(PyIndexError::new_err("error generating Karate club graph")), }; From 5a340da3190f7e038d7367ca8710d1f953ad4098 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 22:17:14 -0400 Subject: [PATCH 04/19] Add tests --- rustworkx-core/src/generators/karate_club.rs | 6 ++-- src/generators.rs | 4 +-- tests/graph/test_karate.py | 34 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/graph/test_karate.py diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index b226c958a9..829f420670 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -17,6 +17,8 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; +// Adapted from NetworkX, licensend under the MIT license +// https://github.com/networkx/networkx/blob/409979eff35f02eff54f4eea3731736bd431dc2e/networkx/generators/social.py#L49 const ZACHARY: &str = "\ 0 4 5 3 3 3 3 2 2 0 2 3 2 3 0 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 2 0 0\n\ 4 0 6 3 0 0 0 4 0 0 0 0 0 5 0 0 0 1 0 2 0 2 0 0 0 0 0 0 0 0 2 0 0 0\n\ @@ -51,7 +53,7 @@ const ZACHARY: &str = "\ 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3\n\ 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 7 0 0 2 0 0 0 4 4\n\ 0 0 2 0 0 0 0 0 3 0 0 0 0 0 3 3 0 0 1 0 3 0 2 5 0 0 0 0 0 4 3 4 0 5\n\ -0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0\n"; +0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0"; pub fn karate_club_graph( mut default_node_weight: F, @@ -76,8 +78,8 @@ where for (col, entry) in this_row.iter().enumerate() { if *entry >= 1 && row > col { graph.add_edge( - node_indices[row], node_indices[col], + node_indices[row], default_edge_weight(*entry), ); } diff --git a/src/generators.rs b/src/generators.rs index ab149409eb..7baeeb66ba 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1721,11 +1721,11 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult PyResult { let default_node_fn = || py.None(); - let default_edge_fn = |w: usize| w.to_object(py); + let default_edge_fn = |w: usize| (w as f64).to_object(py); let graph: StablePyGraph = match core_generators::karate_club_graph(default_node_fn, default_edge_fn) { Ok(graph) => graph, - Err(_) => return Err(PyIndexError::new_err("error generating Karate club graph")), + Err(_) => return Err(PyValueError::new_err("error generating Karate club graph")), }; Ok(graph::PyGraph { graph, diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py new file mode 100644 index 0000000000..a61d8b76bf --- /dev/null +++ b/tests/graph/test_karate.py @@ -0,0 +1,34 @@ +# 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. + +import unittest + +import rustworkx as rx +import networkx as nx + + +class TestKarate(unittest.TestCase): + def test_isomorphic_to_networkx(self): + graph = rx.generators.karate_club_graph() + nx_graph = rx.networkx_converter(nx.karate_club_graph()) + + def edge_matcher(a, b): + if isinstance(a, dict): + a, b, = ( + b, + a, + ) + return a == b["weight"] + + self.assertTrue( + rx.is_isomorphic(graph, nx_graph, node_matcher=None, edge_matcher=edge_matcher) + ) From 592a2d1ef543666162d3cf0829eeac63ed08b9f7 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 22:18:52 -0400 Subject: [PATCH 05/19] Add karate_club_graph signature --- rustworkx/generators/__init__.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/rustworkx/generators/__init__.pyi b/rustworkx/generators/__init__.pyi index 99946bed87..758f907b60 100644 --- a/rustworkx/generators/__init__.pyi +++ b/rustworkx/generators/__init__.pyi @@ -131,3 +131,4 @@ def directed_complete_graph( multigraph: bool = ..., ) -> PyDiGraph: ... def dorogovtsev_goltsev_mendes_graph(n: int) -> PyGraph: ... +def karate_club_graph(multigraph: bool = ...) -> PyGraph: ... From a00a6458526077b018ab6968e9c011d4f98f6df2 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sun, 8 Sep 2024 22:32:48 -0400 Subject: [PATCH 06/19] Fix clippy --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 7baeeb66ba..507f4eb975 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1730,7 +1730,7 @@ pub fn karate_club_graph(py: Python, multigraph: bool) -> PyResult Date: Mon, 9 Sep 2024 07:34:35 -0400 Subject: [PATCH 07/19] Update rustworkx-core/src/generators/karate_club.rs Co-authored-by: Alexander Ivrii --- rustworkx-core/src/generators/karate_club.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 829f420670..9246eb8224 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -17,7 +17,7 @@ use petgraph::visit::{Data, NodeIndexable}; use super::InvalidInputError; -// Adapted from NetworkX, licensend under the MIT license +// Adapted from NetworkX, licensed under the MIT license // https://github.com/networkx/networkx/blob/409979eff35f02eff54f4eea3731736bd431dc2e/networkx/generators/social.py#L49 const ZACHARY: &str = "\ 0 4 5 3 3 3 3 2 2 0 2 3 2 3 0 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 2 0 0\n\ From 7554049eed656491f0a3d4c2362b91a8c08f6f80 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 14 Sep 2024 14:01:08 -0400 Subject: [PATCH 08/19] Add labels and documentation --- rustworkx-core/src/generators/karate_club.rs | 7 +++- src/generators.rs | 39 +++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 829f420670..e4ad922f58 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -55,20 +55,23 @@ const ZACHARY: &str = "\ 0 0 2 0 0 0 0 0 3 0 0 0 0 0 3 3 0 0 1 0 3 0 2 5 0 0 0 0 0 4 3 4 0 5\n\ 0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0"; +const MR_HI_MEMBERS: [usize; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; + pub fn karate_club_graph( mut default_node_weight: F, mut default_edge_weight: H, ) -> Result where G: Build + Create + Data + NodeIndexable, - F: FnMut() -> T, + F: FnMut(bool) -> T, H: FnMut(usize) -> M, G::NodeId: Eq + Hash, { let mut graph = G::with_capacity(0, 0); + let membership: std::collections::HashSet = MR_HI_MEMBERS.into_iter().collect(); let mut node_indices = Vec::new(); for (row, line) in ZACHARY.split('\n').enumerate() { - let node_id = graph.add_node(default_node_weight()); + let node_id = graph.add_node(default_node_weight(membership.contains(&row))); node_indices.push(node_id); let this_row: Vec = line .split_whitespace() diff --git a/src/generators.rs b/src/generators.rs index 507f4eb975..0e1e180338 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1715,12 +1715,49 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult PyResult { - let default_node_fn = || py.None(); + let default_node_fn = |w: bool| match w { + true => "Mr. Hi".to_object(py), + false => "Officer".to_object(py), + }; let default_edge_fn = |w: usize| (w as f64).to_object(py); let graph: StablePyGraph = match core_generators::karate_club_graph(default_node_fn, default_edge_fn) { From f4e47ba347c95ac03111c36f12d5fc1607475d37 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 14 Sep 2024 14:12:48 -0400 Subject: [PATCH 09/19] Test node labels --- tests/graph/test_karate.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index a61d8b76bf..480783bd02 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -19,7 +19,15 @@ class TestKarate(unittest.TestCase): def test_isomorphic_to_networkx(self): graph = rx.generators.karate_club_graph() - nx_graph = rx.networkx_converter(nx.karate_club_graph()) + nx_graph = rx.networkx_converter(nx.karate_club_graph(), keep_attributes=True) + + def node_matcher(a, b): + if isinstance(a, dict): + a, b, = ( + b, + a, + ) + return a == b["club"] def edge_matcher(a, b): if isinstance(a, dict): @@ -30,5 +38,5 @@ def edge_matcher(a, b): return a == b["weight"] self.assertTrue( - rx.is_isomorphic(graph, nx_graph, node_matcher=None, edge_matcher=edge_matcher) + rx.is_isomorphic(graph, nx_graph, node_matcher=node_matcher, edge_matcher=edge_matcher) ) From d0ae8cb6d75cec8065ac3dd332be653f7fc44f68 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 14 Sep 2024 14:15:03 -0400 Subject: [PATCH 10/19] Add simple Rust docstring --- rustworkx-core/src/generators/karate_club.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index b80abc2791..e3866b6fcd 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -57,6 +57,10 @@ const ZACHARY: &str = "\ const MR_HI_MEMBERS: [usize; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; +/// Generates Zachary's Karate Club graph. +/// +/// Zachary's Karate Club graph is a well-known social network that represents +/// the relations between 34 members of a karate club. pub fn karate_club_graph( mut default_node_weight: F, mut default_edge_weight: H, From 90dc34c0f8fcf53b6694eca807bc647970416619 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 14 Sep 2024 14:18:58 -0400 Subject: [PATCH 11/19] Add release notes --- .../notes/karate-club-35708b3838689a0b.yaml | 14 ++++++++++++++ src/generators.rs | 1 - 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/karate-club-35708b3838689a0b.yaml diff --git a/releasenotes/notes/karate-club-35708b3838689a0b.yaml b/releasenotes/notes/karate-club-35708b3838689a0b.yaml new file mode 100644 index 0000000000..5d47a385a6 --- /dev/null +++ b/releasenotes/notes/karate-club-35708b3838689a0b.yaml @@ -0,0 +1,14 @@ +--- +features: + - | + Added a new function, :func:`~rustworkx.generators.karate_club_graph` that + returns Zachary's Karate Club graph, commonly found in social network examples. + + .. jupyter-execute:: + + import rustworkx.generators + from rustworkx.visualization import mpl_draw + + graph = rustworkx.generators.karate_club_graph() + layout = rustworkx.circular_layout(graph) + mpl_draw(graph, pos=layout) diff --git a/src/generators.rs b/src/generators.rs index 0e1e180338..cb3601126b 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1740,7 +1740,6 @@ pub fn dorogovtsev_goltsev_mendes_graph(py: Python, n: usize) -> PyResult Date: Fri, 4 Oct 2024 23:22:04 -0400 Subject: [PATCH 12/19] Black changes --- tests/graph/test_karate.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index 480783bd02..33d0fa4425 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -23,7 +23,10 @@ def test_isomorphic_to_networkx(self): def node_matcher(a, b): if isinstance(a, dict): - a, b, = ( + ( + a, + b, + ) = ( b, a, ) @@ -31,7 +34,10 @@ def node_matcher(a, b): def edge_matcher(a, b): if isinstance(a, dict): - a, b, = ( + ( + a, + b, + ) = ( b, a, ) From 268c0d67bdcb27135aa6825691a115b6f7cd2b0d Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 7 Oct 2024 17:47:47 -0400 Subject: [PATCH 13/19] Update test to be independent --- tests/graph/test_karate.py | 360 ++++++++++++++++++++++++++++++++++++- 1 file changed, 356 insertions(+), 4 deletions(-) diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index 33d0fa4425..6e6b91b830 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -11,16 +11,13 @@ # under the License. import unittest +import tempfile import rustworkx as rx -import networkx as nx class TestKarate(unittest.TestCase): def test_isomorphic_to_networkx(self): - graph = rx.generators.karate_club_graph() - nx_graph = rx.networkx_converter(nx.karate_club_graph(), keep_attributes=True) - def node_matcher(a, b): if isinstance(a, dict): ( @@ -43,6 +40,361 @@ def edge_matcher(a, b): ) return a == b["weight"] + with tempfile.NamedTemporaryFile("wt") as fd: + fd.write(karate_xml) + fd.flush() + nx_graph = rx.read_graphml(fd.name)[0] + + graph = rx.generators.karate_club_graph() + self.assertTrue( rx.is_isomorphic(graph, nx_graph, node_matcher=node_matcher, edge_matcher=edge_matcher) ) + +# Output of +# import networkx as nx +# nx.write_graphml_lxml(nx.karate_club_graph(), open("karate.xml", "w")) +karate_xml = """ + + + + +Zachary's Karate Club + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Officer + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Mr. Hi + + + Officer + + + Officer + + + Mr. Hi + + + Mr. Hi + + + Officer + + + Mr. Hi + + + Officer + + + Mr. Hi + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + Officer + + + 4 + + + 5 + + + 3 + + + 3 + + + 3 + + + 3 + + + 2 + + + 2 + + + 2 + + + 3 + + + 1 + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + 6 + + + 3 + + + 4 + + + 5 + + + 1 + + + 2 + + + 2 + + + 2 + + + 3 + + + 4 + + + 5 + + + 1 + + + 3 + + + 2 + + + 2 + + + 2 + + + 3 + + + 3 + + + 3 + + + 2 + + + 3 + + + 5 + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + 4 + + + 2 + + + 3 + + + 3 + + + 2 + + + 3 + + + 4 + + + 1 + + + 2 + + + 1 + + + 3 + + + 1 + + + 2 + + + 3 + + + 5 + + + 4 + + + 3 + + + 5 + + + 4 + + + 2 + + + 3 + + + 2 + + + 7 + + + 4 + + + 2 + + + 4 + + + 2 + + + 2 + + + 4 + + + 2 + + + 3 + + + 3 + + + 4 + + + 4 + + + 5 + + +""" From 8ed085f8475b51d6d387f72b9fc246cc247b20b0 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho <8753214+IvanIsCoding@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:49:34 -0400 Subject: [PATCH 14/19] Apply suggestions from code review Co-authored-by: Matthew Treinish --- rustworkx-core/src/generators/karate_club.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index e3866b6fcd..28e1f6581b 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -71,9 +71,9 @@ where H: FnMut(usize) -> M, G::NodeId: Eq + Hash, { - let mut graph = G::with_capacity(0, 0); + let mut graph = G::with_capacity(34, 78); let membership: std::collections::HashSet = MR_HI_MEMBERS.into_iter().collect(); - let mut node_indices = Vec::new(); + let mut node_indices = Vec::with_capacity(34); for (row, line) in ZACHARY.split('\n').enumerate() { let node_id = graph.add_node(default_node_weight(membership.contains(&row))); node_indices.push(node_id); From 9ccfe4a2ec084cbbce7283db52ec1f2f7589d892 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 7 Oct 2024 17:53:09 -0400 Subject: [PATCH 15/19] Format and u8 --- rustworkx-core/src/generators/karate_club.rs | 6 +++--- tests/graph/test_karate.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 28e1f6581b..665b50cd0f 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -55,7 +55,7 @@ const ZACHARY: &str = "\ 0 0 2 0 0 0 0 0 3 0 0 0 0 0 3 3 0 0 1 0 3 0 2 5 0 0 0 0 0 4 3 4 0 5\n\ 0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0"; -const MR_HI_MEMBERS: [usize; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; +const MR_HI_MEMBERS: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; /// Generates Zachary's Karate Club graph. /// @@ -72,10 +72,10 @@ where G::NodeId: Eq + Hash, { let mut graph = G::with_capacity(34, 78); - let membership: std::collections::HashSet = MR_HI_MEMBERS.into_iter().collect(); + let membership: std::collections::HashSet = MR_HI_MEMBERS.into_iter().collect(); let mut node_indices = Vec::with_capacity(34); for (row, line) in ZACHARY.split('\n').enumerate() { - let node_id = graph.add_node(default_node_weight(membership.contains(&row))); + let node_id = graph.add_node(default_node_weight(membership.contains(&(row as u8)))); node_indices.push(node_id); let this_row: Vec = line .split_whitespace() diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index 6e6b91b830..468727f313 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -51,7 +51,8 @@ def edge_matcher(a, b): rx.is_isomorphic(graph, nx_graph, node_matcher=node_matcher, edge_matcher=edge_matcher) ) -# Output of + +# Output of # import networkx as nx # nx.write_graphml_lxml(nx.karate_club_graph(), open("karate.xml", "w")) karate_xml = """ From 3c73a8b2011eb39d8552ec974ea51a14ed32defb Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 7 Oct 2024 17:58:39 -0400 Subject: [PATCH 16/19] Ignore ruff for that file --- tests/graph/test_karate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index 468727f313..feb99cfe86 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -52,6 +52,7 @@ def edge_matcher(a, b): ) +# ruff: noqa: E501 # Output of # import networkx as nx # nx.write_graphml_lxml(nx.karate_club_graph(), open("karate.xml", "w")) From 128008c0e2401c6ee57193f8fc90491e2317c167 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 7 Oct 2024 23:49:06 -0400 Subject: [PATCH 17/19] Use adjacency list --- rustworkx-core/src/generators/karate_club.rs | 147 +++++++++++-------- src/generators.rs | 5 +- 2 files changed, 85 insertions(+), 67 deletions(-) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 665b50cd0f..96b5390151 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -15,82 +15,103 @@ use std::hash::Hash; use petgraph::data::{Build, Create}; use petgraph::visit::{Data, NodeIndexable}; -use super::InvalidInputError; - -// Adapted from NetworkX, licensed under the MIT license -// https://github.com/networkx/networkx/blob/409979eff35f02eff54f4eea3731736bd431dc2e/networkx/generators/social.py#L49 -const ZACHARY: &str = "\ -0 4 5 3 3 3 3 2 2 0 2 3 2 3 0 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 2 0 0\n\ -4 0 6 3 0 0 0 4 0 0 0 0 0 5 0 0 0 1 0 2 0 2 0 0 0 0 0 0 0 0 2 0 0 0\n\ -5 6 0 3 0 0 0 4 5 1 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 3 0\n\ -3 3 3 0 0 0 0 3 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -3 0 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -3 0 0 0 0 0 5 0 0 0 3 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -3 0 0 0 2 5 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -2 4 4 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -2 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 4 3\n\ -0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2\n\ -2 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -3 5 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 4\n\ -0 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2\n\ -2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 1\n\ -2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 4 0 2 0 0 5 4\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 3 0 0 0 2 0 0\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 2 0 0 0 0 0 0 7 0 0\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 2\n\ -0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 3 0 0 0 0 0 0 0 0 4\n\ -0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2\n\ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 3 2\n\ -0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3\n\ -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 7 0 0 2 0 0 0 4 4\n\ -0 0 2 0 0 0 0 0 3 0 0 0 0 0 3 3 0 0 1 0 3 0 2 5 0 0 0 0 0 4 3 4 0 5\n\ -0 0 0 0 0 0 0 0 4 2 0 0 0 3 2 4 0 0 2 1 1 0 3 4 0 0 2 4 2 2 3 4 5 0"; - -const MR_HI_MEMBERS: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; - /// Generates Zachary's Karate Club graph. /// /// Zachary's Karate Club graph is a well-known social network that represents /// the relations between 34 members of a karate club. -pub fn karate_club_graph( - mut default_node_weight: F, - mut default_edge_weight: H, -) -> Result +pub fn karate_club_graph(mut default_node_weight: F, mut default_edge_weight: H) -> G where G: Build + Create + Data + NodeIndexable, F: FnMut(bool) -> T, H: FnMut(usize) -> M, G::NodeId: Eq + Hash, { - let mut graph = G::with_capacity(34, 78); - let membership: std::collections::HashSet = MR_HI_MEMBERS.into_iter().collect(); - let mut node_indices = Vec::with_capacity(34); - for (row, line) in ZACHARY.split('\n').enumerate() { + const N: usize = 34; + const M: usize = 78; + let mr_hi_members: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 21]; + let membership: std::collections::HashSet = mr_hi_members.into_iter().collect(); + + let adjacency_list: Vec> = vec![ + vec![], + vec![(0, 4)], + vec![(0, 5), (1, 6)], + vec![(0, 3), (1, 3), (2, 3)], + vec![(0, 3)], + vec![(0, 3)], + vec![(0, 3), (4, 2), (5, 5)], + vec![(0, 2), (1, 4), (2, 4), (3, 3)], + vec![(0, 2), (2, 5)], + vec![(2, 1)], + vec![(0, 2), (4, 3), (5, 3)], + vec![(0, 3)], + vec![(0, 1), (3, 3)], + vec![(0, 3), (1, 5), (2, 3), (3, 3)], + vec![], + vec![], + vec![(5, 3), (6, 3)], + vec![(0, 2), (1, 1)], + vec![], + vec![(0, 2), (1, 2)], + vec![], + vec![(0, 2), (1, 2)], + vec![], + vec![], + vec![], + vec![(23, 5), (24, 2)], + vec![], + vec![(2, 2), (23, 4), (24, 3)], + vec![(2, 2)], + vec![(23, 3), (26, 4)], + vec![(1, 2), (8, 3)], + vec![(0, 2), (24, 2), (25, 7), (28, 2)], + vec![ + (2, 2), + (8, 3), + (14, 3), + (15, 3), + (18, 1), + (20, 3), + (22, 2), + (23, 5), + (29, 4), + (30, 3), + (31, 4), + ], + vec![ + (8, 4), + (9, 2), + (13, 3), + (14, 2), + (15, 4), + (18, 2), + (19, 1), + (20, 1), + (23, 4), + (26, 2), + (27, 4), + (28, 2), + (29, 2), + (30, 3), + (31, 4), + (32, 5), + (22, 3), + ], + ]; + + let mut graph = G::with_capacity(N, M); + + let mut node_indices = Vec::with_capacity(N); + for (row, neighbors) in adjacency_list.into_iter().enumerate() { let node_id = graph.add_node(default_node_weight(membership.contains(&(row as u8)))); node_indices.push(node_id); - let this_row: Vec = line - .split_whitespace() - .map(|b| b.parse::().unwrap()) - .collect(); - for (col, entry) in this_row.iter().enumerate() { - if *entry >= 1 && row > col { - graph.add_edge( - node_indices[col], - node_indices[row], - default_edge_weight(*entry), - ); - } + for (neighbor, weight) in neighbors.into_iter() { + graph.add_edge( + node_indices[neighbor], + node_indices[row], + default_edge_weight(weight), + ); } } - Ok(graph) + graph } diff --git a/src/generators.rs b/src/generators.rs index cb3601126b..82b75b8a4d 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1759,10 +1759,7 @@ pub fn karate_club_graph(py: Python, multigraph: bool) -> PyResult = - match core_generators::karate_club_graph(default_node_fn, default_edge_fn) { - Ok(graph) => graph, - Err(_) => return Err(PyValueError::new_err("error generating Karate club graph")), - }; + core_generators::karate_club_graph(default_node_fn, default_edge_fn); Ok(graph::PyGraph { graph, node_removed: false, From a4c14927ced922432dcc172e21bfc8146b237589 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 7 Oct 2024 23:52:39 -0400 Subject: [PATCH 18/19] Add some documentation --- rustworkx-core/src/generators/karate_club.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rustworkx-core/src/generators/karate_club.rs b/rustworkx-core/src/generators/karate_club.rs index 96b5390151..d0e0ac495e 100644 --- a/rustworkx-core/src/generators/karate_club.rs +++ b/rustworkx-core/src/generators/karate_club.rs @@ -19,6 +19,15 @@ use petgraph::visit::{Data, NodeIndexable}; /// /// Zachary's Karate Club graph is a well-known social network that represents /// the relations between 34 members of a karate club. +/// Arguments: +/// +/// * `default_node_weight` - A callable that will receive a boolean, indicating +/// if a node is part of Mr Hi's faction (True) or the Officer's faction (false). +/// It shoudl return the node weight according to the desired type. +/// * `default_edge_weight` - A callable that will receive the integer representing +/// the strenght of the relation between two nodes. It should return the edge +/// weight according to the desired type. +/// pub fn karate_club_graph(mut default_node_weight: F, mut default_edge_weight: H) -> G where G: Build + Create + Data + NodeIndexable, From 911faff45ea03a71ac2342cb800cb3a43ad94358 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 15 Nov 2024 11:32:36 -0500 Subject: [PATCH 19/19] Update tests/graph/test_karate.py --- tests/graph/test_karate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/graph/test_karate.py b/tests/graph/test_karate.py index feb99cfe86..7bc7e4e3ee 100644 --- a/tests/graph/test_karate.py +++ b/tests/graph/test_karate.py @@ -43,12 +43,12 @@ def edge_matcher(a, b): with tempfile.NamedTemporaryFile("wt") as fd: fd.write(karate_xml) fd.flush() - nx_graph = rx.read_graphml(fd.name)[0] + expected = rx.read_graphml(fd.name)[0] graph = rx.generators.karate_club_graph() self.assertTrue( - rx.is_isomorphic(graph, nx_graph, node_matcher=node_matcher, edge_matcher=edge_matcher) + rx.is_isomorphic(graph, expected, node_matcher=node_matcher, edge_matcher=edge_matcher) )