From 75bc722b1efd5b0faf10c515950cc80f0b61d79d Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 11:23:26 -0300 Subject: [PATCH 01/32] Add binomial tree graph Add binomial tree graph for a given order. --- src/generators.rs | 102 +++++++++++++++++++++++++ tests/generators/test_binomial_tree.py | 34 +++++++++ 2 files changed, 136 insertions(+) create mode 100644 tests/generators/test_binomial_tree.py diff --git a/src/generators.rs b/src/generators.rs index 7141bf37ce..d049c30aa8 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -10,11 +10,13 @@ // License for the specific language governing permissions and limitations // under the License. +use std::convert::TryInto; use std::iter; use petgraph::algo; use petgraph::graph::NodeIndex; use petgraph::stable_graph::{StableDiGraph, StableUnGraph}; +use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use pyo3::exceptions::PyIndexError; use pyo3::prelude::*; @@ -985,6 +987,105 @@ pub fn directed_grid_graph( }) } +/// Generate an undirected binomial tree of order n recursively. +/// +/// :param int order: Order of the binomial tree. +/// :param list weights: A list of node weights. It must have 2**order values. +/// :param bool multigraph: When set to False the output +/// :class:`~retworkx.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 binomail tree with 2^n vertices and 2^n - 1 edges. +/// :rtype: PyGraph +/// :raises IndexError: If neither ``order`` or ``weights`` are specified +/// +/// .. jupyter-execute:: +/// +/// import os +/// import tempfile +/// +/// import pydot +/// from PIL import Image +/// +/// import retworkx.generators +/// +/// graph = retworkx.generators.binomial_tree(4) +/// dot_str = graph.to_dot( +/// lambda node: dict( +/// color='black', fillcolor='lightblue', style='filled')) +/// dot = pydot.graph_from_dot_data(dot_str)[0] +/// +/// with tempfile.TemporaryDirectory() as tmpdirname: +/// tmp_path = os.path.join(tmpdirname, 'dag.png') +/// dot.write_png(tmp_path) +/// image = Image.open(tmp_path) +/// os.remove(tmp_path) +/// image +/// +#[pyfunction(multigraph = true)] +#[text_signature = "(/, order=None, weights=None, multigraph=True)"] +pub fn binomial_tree_graph( + py: Python, + order: Option, + weights: Option>, + multigraph: bool, +) -> PyResult { + let mut graph = StableUnGraph::::default(); + + if order.is_none() { + return Err(PyIndexError::new_err("order should be specified")); + } + + // try_into is used to convert from usize to u32 + let num_nodes = usize::pow(2, order.unwrap().try_into().unwrap()); + + let nodes: Vec = match weights { + Some(weights) => { + let mut node_list: Vec = Vec::new(); + + for weight in weights { + let index = graph.add_node(weight); + node_list.push(index); + } + + node_list + } + + None => (0..num_nodes).map(|_| graph.add_node(py.None())).collect(), + }; + + let mut n = 1; + + for _ in 0..order.unwrap() { + let edges: Vec<(NodeIndex, NodeIndex)> = graph + .edge_references() + .map(|e| (e.source(), e.target())) + .collect(); + + for (source, target) in edges { + let source_index = source.index(); + let target_index = target.index(); + + graph.add_edge( + nodes[source_index + n], + nodes[target_index + n], + py.None(), + ); + } + + graph.add_edge(nodes[0], nodes[n], py.None()); + + n *= 2; + } + + Ok(graph::PyGraph { + graph, + node_removed: false, + multigraph, + }) +} + #[pymodule] pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(cycle_graph))?; @@ -997,5 +1098,6 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(directed_mesh_graph))?; m.add_wrapped(wrap_pyfunction!(grid_graph))?; m.add_wrapped(wrap_pyfunction!(directed_grid_graph))?; + m.add_wrapped(wrap_pyfunction!(binomial_tree_graph))?; Ok(()) } diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py new file mode 100644 index 0000000000..1847c0a934 --- /dev/null +++ b/tests/generators/test_binomial_tree.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 retworkx + + +class TestBinomailTreeGraph(unittest.TestCase): + + def test_binomial_tree_graph(self): + for n in range(10): + graph = retworkx.generators.binomial_tree_graph(n) + self.assertEqual(len(graph), 2**n) + self.assertEqual(len(graph.edges()), 2**n - 1) + + def test_binomial_tree_graph_weights(self): + graph = retworkx.generators.binomial_tree_graph(2, weights=list(range(4))) + self.assertEqual(len(graph), 4) + self.assertEqual([x for x in range(4)], graph.nodes()) + self.assertEqual(len(graph.edges()), 3) + + def test_binomial_tree_no_order(self): + with self.assertRaises(IndexError): + retworkx.generators.binomial_tree_graph(weights=list(range(4))) From 5ff3f4779c935971a5f51491f46e36ce3f9a2a73 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 11:25:28 -0300 Subject: [PATCH 02/32] update documentation --- docs/source/api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/api.rst b/docs/source/api.rst index 134350188b..a93f056541 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -30,6 +30,7 @@ Generators retworkx.generators.directed_mesh_graph retworkx.generators.grid_graph retworkx.generators.directed_grid_graph + retworkx.generators.binomial_tree_graph Random Circuit Functions ------------------------ From aff705d0dd2489749f5b51dff498dcd1e7e2af1a Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 11:30:41 -0300 Subject: [PATCH 03/32] add release notes --- .../add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml diff --git a/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml b/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml new file mode 100644 index 0000000000..5f0951a845 --- /dev/null +++ b/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added a new generator for constructing a binomial tree graph (:func:`retworkx.generators.binomial_tree_graph`). \ No newline at end of file From 0a6749cf7fe99a806eac4b80a0eb30069a9b6c2d Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 13:06:10 -0300 Subject: [PATCH 04/32] lint --- tests/generators/test_binomial_tree.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 1847c0a934..a9979390e9 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -24,7 +24,8 @@ def test_binomial_tree_graph(self): self.assertEqual(len(graph.edges()), 2**n - 1) def test_binomial_tree_graph_weights(self): - graph = retworkx.generators.binomial_tree_graph(2, weights=list(range(4))) + graph = retworkx.generators.binomial_tree_graph(2, + weights=list(range(4))) self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) From 4b5241fe88fc0e400d742efcdc13c7764b3db431 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 13:11:05 -0300 Subject: [PATCH 05/32] lint --- tests/generators/test_binomial_tree.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index a9979390e9..12456fe9f7 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -24,8 +24,8 @@ def test_binomial_tree_graph(self): self.assertEqual(len(graph.edges()), 2**n - 1) def test_binomial_tree_graph_weights(self): - graph = retworkx.generators.binomial_tree_graph(2, - weights=list(range(4))) + graph = retworkx.generators.binomial_tree_graph(2, + weights=list(range(4))) self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) From af129b10edcdbbc5840f020ee37ade926a73107c Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 13:14:17 -0300 Subject: [PATCH 06/32] lint --- tests/generators/test_binomial_tree.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 12456fe9f7..a7a761b1bb 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -24,8 +24,8 @@ def test_binomial_tree_graph(self): self.assertEqual(len(graph.edges()), 2**n - 1) def test_binomial_tree_graph_weights(self): - graph = retworkx.generators.binomial_tree_graph(2, - weights=list(range(4))) + graph = retworkx.generators.binomial_tree_graph( + 2, weights=list(range(4))) self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) From 5eb6b56c4be862beb409d18248854e3b6c8b6ced Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 14:54:38 -0300 Subject: [PATCH 07/32] fix docs --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index d049c30aa8..0fde9863d4 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1010,7 +1010,7 @@ pub fn directed_grid_graph( /// /// import retworkx.generators /// -/// graph = retworkx.generators.binomial_tree(4) +/// graph = retworkx.generators.binomial_tree_graph(4) /// dot_str = graph.to_dot( /// lambda node: dict( /// color='black', fillcolor='lightblue', style='filled')) From c7a689197889253cf56410e911e5b7e1a650c5da Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 1 Apr 2021 16:49:48 -0300 Subject: [PATCH 08/32] remove option for order --- src/generators.rs | 10 +++------- tests/generators/test_binomial_tree.py | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 0fde9863d4..d8928b4eb2 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1027,18 +1027,14 @@ pub fn directed_grid_graph( #[text_signature = "(/, order=None, weights=None, multigraph=True)"] pub fn binomial_tree_graph( py: Python, - order: Option, + order: usize, weights: Option>, multigraph: bool, ) -> PyResult { let mut graph = StableUnGraph::::default(); - if order.is_none() { - return Err(PyIndexError::new_err("order should be specified")); - } - // try_into is used to convert from usize to u32 - let num_nodes = usize::pow(2, order.unwrap().try_into().unwrap()); + let num_nodes = usize::pow(2, order.try_into().unwrap()); let nodes: Vec = match weights { Some(weights) => { @@ -1057,7 +1053,7 @@ pub fn binomial_tree_graph( let mut n = 1; - for _ in 0..order.unwrap() { + for _ in 0..order { let edges: Vec<(NodeIndex, NodeIndex)> = graph .edge_references() .map(|e| (e.source(), e.target())) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index a7a761b1bb..dee991e61f 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -31,5 +31,5 @@ def test_binomial_tree_graph_weights(self): self.assertEqual(len(graph.edges()), 3) def test_binomial_tree_no_order(self): - with self.assertRaises(IndexError): + with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) From 3a52c15f078e42e355ce3f0a44fccdea569144af Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 8 Apr 2021 17:35:33 -0300 Subject: [PATCH 09/32] change order to u32 This is done because that for `pow`method a u32 is needed. --- src/generators.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index d8928b4eb2..4d5e64cf50 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1027,14 +1027,13 @@ pub fn directed_grid_graph( #[text_signature = "(/, order=None, weights=None, multigraph=True)"] pub fn binomial_tree_graph( py: Python, - order: usize, + order: u32, weights: Option>, multigraph: bool, ) -> PyResult { let mut graph = StableUnGraph::::default(); - // try_into is used to convert from usize to u32 - let num_nodes = usize::pow(2, order.try_into().unwrap()); + let num_nodes = usize::pow(2, order); let nodes: Vec = match weights { Some(weights) => { From d9e9bb889d5534474c0116eb9551555a5a5628d5 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Thu, 8 Apr 2021 17:51:45 -0300 Subject: [PATCH 10/32] clippy --- src/generators.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 4d5e64cf50..2492fc11d1 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::convert::TryInto; use std::iter; use petgraph::algo; From 274105195c36e5e21e172de7462317e8f04835fe Mon Sep 17 00:00:00 2001 From: nahumsa Date: Mon, 26 Apr 2021 14:44:57 -0300 Subject: [PATCH 11/32] add directed binomial tree graph --- src/generators.rs | 107 ++++++++++++++++++++++++- tests/generators/test_binomial_tree.py | 17 ++++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 2492fc11d1..df3640331f 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -995,7 +995,7 @@ pub fn directed_grid_graph( /// won't allow parallel edges to be added. Instead /// calls which would create a parallel edge will update the existing edge. /// -/// :returns: A binomail tree with 2^n vertices and 2^n - 1 edges. +/// :returns: A binomial tree with 2^n vertices and 2^n - 1 edges. /// :rtype: PyGraph /// :raises IndexError: If neither ``order`` or ``weights`` are specified /// @@ -1080,6 +1080,110 @@ pub fn binomial_tree_graph( }) } +/// Generate an undirected binomial tree of order n recursively. +/// The edges propagate towards right and bottom direction if ``bidirectional`` is ``false`` +/// +/// :param int order: Order of the binomial tree. +/// :param list weights: A list of node weights. It must have 2**order values. +/// :param bidirectional: A parameter to indicate if edges should exist in +/// both directions between nodes +/// +/// :returns: A directed binomial tree with 2^n vertices and 2^n - 1 edges. +/// :rtype: PyDiGraph +/// :raises IndexError: If neither ``rows`` or ``cols`` and ``weights`` are +/// specified +/// +/// .. jupyter-execute:: +/// +/// import os +/// import tempfile +/// +/// import pydot +/// from PIL import Image +/// +/// import retworkx.generators +/// +/// graph = retworkx.generators.directed_binomial_tree_graph(4) +/// dot_str = graph.to_dot( +/// lambda node: dict( +/// color='black', fillcolor='lightblue', style='filled')) +/// dot = pydot.graph_from_dot_data(dot_str)[0] +/// +/// with tempfile.TemporaryDirectory() as tmpdirname: +/// tmp_path = os.path.join(tmpdirname, 'dag.png') +/// dot.write_png(tmp_path) +/// image = Image.open(tmp_path) +/// os.remove(tmp_path) +/// image +/// +#[pyfunction(bidirectional = "false")] +#[text_signature = "(/, order=None, weights=None, multigraph=True)"] +pub fn directed_binomial_tree_graph( + py: Python, + order: u32, + weights: Option>, + bidirectional: bool, +) -> PyResult { + let mut graph = StableDiGraph::::default(); + + let num_nodes = usize::pow(2, order); + + let nodes: Vec = match weights { + Some(weights) => { + let mut node_list: Vec = Vec::new(); + + for weight in weights { + let index = graph.add_node(weight); + node_list.push(index); + } + + node_list + } + + None => (0..num_nodes).map(|_| graph.add_node(py.None())).collect(), + }; + + let mut n = 1; + + for _ in 0..order { + let edges: Vec<(NodeIndex, NodeIndex)> = graph + .edge_references() + .map(|e| (e.source(), e.target())) + .collect(); + + for (source, target) in edges { + let source_index = source.index(); + let target_index = target.index(); + + graph.add_edge( + nodes[source_index + n], + nodes[target_index + n], + py.None(), + ); + + if bidirectional { + graph.add_edge( + nodes[source_index + n], + nodes[target_index + n], + py.None(), + ); + } + } + + graph.add_edge(nodes[0], nodes[n], py.None()); + + n *= 2; + } + + Ok(digraph::PyDiGraph { + graph, + node_removed: false, + check_cycle: false, + cycle_state: algo::DfsSpace::default(), + multigraph: true, + }) +} + #[pymodule] pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(cycle_graph))?; @@ -1093,5 +1197,6 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(grid_graph))?; m.add_wrapped(wrap_pyfunction!(directed_grid_graph))?; m.add_wrapped(wrap_pyfunction!(binomial_tree_graph))?; + m.add_wrapped(wrap_pyfunction!(directed_binomial_tree_graph))?; Ok(()) } diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index dee991e61f..2d846d7b8d 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -33,3 +33,20 @@ def test_binomial_tree_graph_weights(self): def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) + + def test_directed_binomial_tree_graph(self): + for n in range(10): + graph = retworkx.generators.directed_binomial_tree_graph(n) + self.assertEqual(len(graph), 2**n) + self.assertEqual(len(graph.edges()), 2**n - 1) + + def test_directed_binomial_tree_graph_weights(self): + graph = retworkx.generators.directed_binomial_tree_graph( + 2, weights=list(range(4))) + self.assertEqual(len(graph), 4) + self.assertEqual([x for x in range(4)], graph.nodes()) + self.assertEqual(len(graph.edges()), 3) + + def test_directed_binomial_tree_no_order(self): + with self.assertRaises(TypeError): + retworkx.generators.directed_binomial_tree_graph(weights=list(range(4))) From 199ee008dad2d17891ccaf1f3b9b114a8d803055 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Mon, 26 Apr 2021 15:59:29 -0300 Subject: [PATCH 12/32] lint --- tests/generators/test_binomial_tree.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 2d846d7b8d..8409e22da4 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -33,7 +33,7 @@ def test_binomial_tree_graph_weights(self): def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) - + def test_directed_binomial_tree_graph(self): for n in range(10): graph = retworkx.generators.directed_binomial_tree_graph(n) @@ -49,4 +49,5 @@ def test_directed_binomial_tree_graph_weights(self): def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): - retworkx.generators.directed_binomial_tree_graph(weights=list(range(4))) + retworkx.generators.directed_binomial_tree_graph( + weights=list(range(4))) From 1a2e8fd260d2150f1e23c1c359145b7ebaa2d43a Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Tue, 4 May 2021 10:15:45 -0300 Subject: [PATCH 13/32] fix positional argument Co-authored-by: Matthew Treinish --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index df3640331f..7960abe222 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1023,7 +1023,7 @@ pub fn directed_grid_graph( /// image /// #[pyfunction(multigraph = true)] -#[text_signature = "(/, order=None, weights=None, multigraph=True)"] +#[text_signature = "(order=None, /, weights=None, multigraph=True)"] pub fn binomial_tree_graph( py: Python, order: u32, From 764f487637e20eb4d2d28f835efa8b97d395d43d Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Tue, 4 May 2021 10:54:38 -0300 Subject: [PATCH 14/32] updated test Co-authored-by: Matthew Treinish --- tests/generators/test_binomial_tree.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 8409e22da4..c54b5b8f3b 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -19,9 +19,10 @@ class TestBinomailTreeGraph(unittest.TestCase): def test_binomial_tree_graph(self): for n in range(10): - graph = retworkx.generators.binomial_tree_graph(n) - self.assertEqual(len(graph), 2**n) - self.assertEqual(len(graph.edges()), 2**n - 1) + with self.subTest(n=n): + graph = retworkx.generators.binomial_tree_graph(n) + self.assertEqual(len(graph), 2**n) + self.assertEqual(len(graph.edges()), 2**n - 1) def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( From 590e82436667dc22c66ee1e9c3b385504095d479 Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Tue, 4 May 2021 10:54:52 -0300 Subject: [PATCH 15/32] updated tests Co-authored-by: Matthew Treinish --- tests/generators/test_binomial_tree.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index c54b5b8f3b..f6e6bbee6f 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -37,9 +37,10 @@ def test_binomial_tree_no_order(self): def test_directed_binomial_tree_graph(self): for n in range(10): - graph = retworkx.generators.directed_binomial_tree_graph(n) - self.assertEqual(len(graph), 2**n) - self.assertEqual(len(graph.edges()), 2**n - 1) + with self.subTest(n=n): + graph = retworkx.generators.directed_binomial_tree_graph(n) + self.assertEqual(len(graph), 2**n) + self.assertEqual(len(graph.edges()), 2**n - 1) def test_directed_binomial_tree_graph_weights(self): graph = retworkx.generators.directed_binomial_tree_graph( From 4fa210f28a4ed9f66c45669e46adbdd6360c526a Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 4 May 2021 10:55:29 -0300 Subject: [PATCH 16/32] add case mismatch weights --- src/generators.rs | 23 ++++++++++++++++++++--- tests/generators/test_binomial_tree.py | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index df3640331f..87eed81ca1 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -989,7 +989,8 @@ pub fn directed_grid_graph( /// Generate an undirected binomial tree of order n recursively. /// /// :param int order: Order of the binomial tree. -/// :param list weights: A list of node weights. It must have 2**order values. +/// :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 /// :class:`~retworkx.PyGraph` object will not be not be a multigraph and /// won't allow parallel edges to be added. Instead @@ -1038,11 +1039,19 @@ pub fn binomial_tree_graph( Some(weights) => { let mut node_list: Vec = Vec::new(); + let mut node_count = num_nodes; + for weight in weights { let index = graph.add_node(weight); node_list.push(index); + node_count -= 1; } - + + for _i in 0..node_count { + let index = graph.add_node(py.None()); + node_list.push(index); + } + node_list } @@ -1084,7 +1093,8 @@ pub fn binomial_tree_graph( /// The edges propagate towards right and bottom direction if ``bidirectional`` is ``false`` /// /// :param int order: Order of the binomial tree. -/// :param list weights: A list of node weights. It must have 2**order values. +/// :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 /// @@ -1131,10 +1141,17 @@ pub fn directed_binomial_tree_graph( let nodes: Vec = match weights { Some(weights) => { let mut node_list: Vec = Vec::new(); + let mut node_count = num_nodes; for weight in weights { let index = graph.add_node(weight); node_list.push(index); + node_count -= num_nodes; + } + + for _i in 0..node_count { + let index = graph.add_node(py.None()); + node_list.push(index); } node_list diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 8409e22da4..6c0fff68a8 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -30,6 +30,15 @@ def test_binomial_tree_graph_weights(self): self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) + def test_binomial_tree_graph_mismatch_nodes_weights(self): + graph = retworkx.generators.binomial_tree_graph( + 2, weights=list(range(2))) + self.assertEqual(len(graph), 4) + expected_weights = [x for x in range(2)] + expected_weights.extend([None, None]) + self.assertEqual(expected_weights, graph.nodes()) + self.assertEqual(len(graph.edges()), 3) + def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) @@ -47,6 +56,15 @@ def test_directed_binomial_tree_graph_weights(self): self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) + def test_directed_binomial_tree_graph_mismatch_nodes_weights(self): + graph = retworkx.generators.binomial_tree_graph( + 2, weights=list(range(2))) + self.assertEqual(len(graph), 4) + expected_weights = [x for x in range(2)] + expected_weights.extend([None, None]) + self.assertEqual(expected_weights, graph.nodes()) + self.assertEqual(len(graph.edges()), 3) + def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.directed_binomial_tree_graph( From 769b04b28463a5cd8b1368f6b1f3254c06ba338b Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 4 May 2021 16:52:34 -0300 Subject: [PATCH 17/32] add edgelist assertion --- src/generators.rs | 35 +++++++++++----- tests/generators/test_binomial_tree.py | 56 +++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 4080d73cbd..6bf67abb51 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -989,7 +989,7 @@ pub fn directed_grid_graph( /// Generate an undirected binomial tree of order n recursively. /// /// :param int order: Order of the binomial tree. -/// :param list weights: A list of node weights. If the number of weights is +/// :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 /// :class:`~retworkx.PyGraph` object will not be not be a multigraph and @@ -998,7 +998,7 @@ pub fn directed_grid_graph( /// /// :returns: A binomial tree with 2^n vertices and 2^n - 1 edges. /// :rtype: PyGraph -/// :raises IndexError: If neither ``order`` or ``weights`` are specified +/// :raises IndexError: If the lenght of ``weights`` is greater that 2^n /// /// .. jupyter-execute:: /// @@ -1041,17 +1041,23 @@ pub fn binomial_tree_graph( let mut node_count = num_nodes; + if weights.len() > num_nodes { + return Err(PyIndexError::new_err( + "weights should be <= 2**order", + )); + } + for weight in weights { let index = graph.add_node(weight); node_list.push(index); node_count -= 1; } - + for _i in 0..node_count { let index = graph.add_node(py.None()); node_list.push(index); } - + node_list } @@ -1093,15 +1099,14 @@ pub fn binomial_tree_graph( /// The edges propagate towards right and bottom direction if ``bidirectional`` is ``false`` /// /// :param int order: Order of the binomial tree. -/// :param list weights: A list of node weights. If the number of weights is +/// :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 /// /// :returns: A directed binomial tree with 2^n vertices and 2^n - 1 edges. /// :rtype: PyDiGraph -/// :raises IndexError: If neither ``rows`` or ``cols`` and ``weights`` are -/// specified +/// :raises IndexError: If the lenght of ``weights`` is greater that 2^n /// /// .. jupyter-execute:: /// @@ -1127,7 +1132,7 @@ pub fn binomial_tree_graph( /// image /// #[pyfunction(bidirectional = "false")] -#[text_signature = "(/, order=None, weights=None, multigraph=True)"] +#[text_signature = "(/, order=None, weights=None, bidirectional=False)"] pub fn directed_binomial_tree_graph( py: Python, order: u32, @@ -1143,10 +1148,16 @@ pub fn directed_binomial_tree_graph( let mut node_list: Vec = Vec::new(); let mut node_count = num_nodes; + if weights.len() > num_nodes { + return Err(PyIndexError::new_err( + "weights should be <= 2**order", + )); + } + for weight in weights { let index = graph.add_node(weight); node_list.push(index); - node_count -= num_nodes; + node_count -= 1; } for _i in 0..node_count { @@ -1180,8 +1191,8 @@ pub fn directed_binomial_tree_graph( if bidirectional { graph.add_edge( - nodes[source_index + n], nodes[target_index + n], + nodes[source_index + n], py.None(), ); } @@ -1189,6 +1200,10 @@ pub fn directed_binomial_tree_graph( graph.add_edge(nodes[0], nodes[n], py.None()); + if bidirectional { + graph.add_edge(nodes[n], nodes[0], py.None()); + } + n *= 2; } diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 6c297919ff..f1f3ed55fe 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -15,23 +15,42 @@ import retworkx -class TestBinomailTreeGraph(unittest.TestCase): +class TestBinomialTreeGraph(unittest.TestCase): def test_binomial_tree_graph(self): - for n in range(10): + expected_edges = {0 : [], + 1 : [(0, 1)], + 2: [(0, 1), (0, 2), (2, 3)], + 3: [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), + (6, 7)], + 4 :[(0, 1), (0, 2), (0, 4), (0, 8), + (2, 3), (4, 5), (4, 6), (6, 7), + (8, 9), (8, 10), (8, 12), + (10, 11), (12, 13), (12, 14), + (14, 15)] + } + for n in range(5): with self.subTest(n=n): graph = retworkx.generators.binomial_tree_graph(n) self.assertEqual(len(graph), 2**n) self.assertEqual(len(graph.edges()), 2**n - 1) + for edge in list(graph.edge_list()): + self.assertIn(edge, expected_edges[n]) def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(4))) + expected_edges = [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), + (6, 7)] self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) + for edge in list(graph.edge_list()): + self.assertIn(edge, expected_edges) - def test_binomial_tree_graph_mismatch_nodes_weights(self): + def test_binomial_tree_graph_weight_less_nodes(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(2))) self.assertEqual(len(graph), 4) @@ -40,16 +59,36 @@ def test_binomial_tree_graph_mismatch_nodes_weights(self): self.assertEqual(expected_weights, graph.nodes()) self.assertEqual(len(graph.edges()), 3) + def test_binomial_tree_graph_weights_greater_nodes(self): + with self.assertRaises(IndexError): + graph = retworkx.generators.binomial_tree_graph( + 2, weights=list(range(7))) + + def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) def test_directed_binomial_tree_graph(self): - for n in range(10): + expected_edges = {0 : [], + 1 : [(0, 1)], + 2: [(0, 1), (0, 2), (2, 3)], + 3: [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), + (6, 7)], + 4 :[(0, 1), (0, 2), (0, 4), (0, 8), + (2, 3), (4, 5), (4, 6), (6, 7), + (8, 9), (8, 10), (8, 12), + (10, 11), (12, 13), (12, 14), + (14, 15)] + } + for n in range(5): with self.subTest(n=n): graph = retworkx.generators.directed_binomial_tree_graph(n) self.assertEqual(len(graph), 2**n) self.assertEqual(len(graph.edges()), 2**n - 1) + for edge in list(graph.edge_list()): + self.assertIn(edge, expected_edges[n]) def test_directed_binomial_tree_graph_weights(self): graph = retworkx.generators.directed_binomial_tree_graph( @@ -58,8 +97,8 @@ def test_directed_binomial_tree_graph_weights(self): self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) - def test_directed_binomial_tree_graph_mismatch_nodes_weights(self): - graph = retworkx.generators.binomial_tree_graph( + def test_directed_binomial_tree_graph_weight_less_nodes(self): + graph = retworkx.generators.directed_binomial_tree_graph( 2, weights=list(range(2))) self.assertEqual(len(graph), 4) expected_weights = [x for x in range(2)] @@ -67,6 +106,11 @@ def test_directed_binomial_tree_graph_mismatch_nodes_weights(self): self.assertEqual(expected_weights, graph.nodes()) self.assertEqual(len(graph.edges()), 3) + def test_directed_binomial_tree_graph_weights_greater_nodes(self): + with self.assertRaises(IndexError): + graph = retworkx.generators.directed_binomial_tree_graph( + 2, weights=list(range(7))) + def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.directed_binomial_tree_graph( From 7f8f78ab69dee27f398a66021cbf4ff38f8b1b70 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 4 May 2021 17:02:52 -0300 Subject: [PATCH 18/32] lint --- tests/generators/test_binomial_tree.py | 47 ++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index f1f3ed55fe..7b433a3885 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -18,18 +18,17 @@ class TestBinomialTreeGraph(unittest.TestCase): def test_binomial_tree_graph(self): - expected_edges = {0 : [], - 1 : [(0, 1)], + expected_edges = {0: [], + 1: [(0, 1)], 2: [(0, 1), (0, 2), (2, 3)], - 3: [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), + 3: [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), (6, 7)], - 4 :[(0, 1), (0, 2), (0, 4), (0, 8), - (2, 3), (4, 5), (4, 6), (6, 7), - (8, 9), (8, 10), (8, 12), - (10, 11), (12, 13), (12, 14), - (14, 15)] - } + 4: [(0, 1), (0, 2), (0, 4), (0, 8), + (2, 3), (4, 5), (4, 6), (6, 7), + (8, 9), (8, 10), (8, 12), + (10, 11), (12, 13), (12, 14), + (14, 15)]} for n in range(5): with self.subTest(n=n): graph = retworkx.generators.binomial_tree_graph(n) @@ -41,8 +40,8 @@ def test_binomial_tree_graph(self): def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(4))) - expected_edges = [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), + expected_edges = [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), (6, 7)] self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) @@ -61,27 +60,25 @@ def test_binomial_tree_graph_weight_less_nodes(self): def test_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): - graph = retworkx.generators.binomial_tree_graph( + retworkx.generators.binomial_tree_graph( 2, weights=list(range(7))) - def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) def test_directed_binomial_tree_graph(self): - expected_edges = {0 : [], - 1 : [(0, 1)], + expected_edges = {0: [], + 1: [(0, 1)], 2: [(0, 1), (0, 2), (2, 3)], - 3: [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), + 3: [(0, 1), (0, 2), (0, 4), + (2, 3), (4, 5), (4, 6), (6, 7)], - 4 :[(0, 1), (0, 2), (0, 4), (0, 8), - (2, 3), (4, 5), (4, 6), (6, 7), - (8, 9), (8, 10), (8, 12), - (10, 11), (12, 13), (12, 14), - (14, 15)] - } + 4: [(0, 1), (0, 2), (0, 4), (0, 8), + (2, 3), (4, 5), (4, 6), (6, 7), + (8, 9), (8, 10), (8, 12), + (10, 11), (12, 13), (12, 14), + (14, 15)]} for n in range(5): with self.subTest(n=n): graph = retworkx.generators.directed_binomial_tree_graph(n) @@ -108,7 +105,7 @@ def test_directed_binomial_tree_graph_weight_less_nodes(self): def test_directed_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): - graph = retworkx.generators.directed_binomial_tree_graph( + retworkx.generators.directed_binomial_tree_graph( 2, weights=list(range(7))) def test_directed_binomial_tree_no_order(self): From d3365993d3b90475ecb86bdc0cce38a5fb770494 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 17:34:17 -0300 Subject: [PATCH 19/32] add find_edge before adding edge `find_edge`makes sure that you don't add repeated edges on the graph --- src/generators.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 6bf67abb51..564a20d0e1 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1183,25 +1183,38 @@ pub fn directed_binomial_tree_graph( let source_index = source.index(); let target_index = target.index(); - graph.add_edge( - nodes[source_index + n], - nodes[target_index + n], - py.None(), - ); - - if bidirectional { + if graph.find_edge(nodes[source_index + n], nodes[target_index + n]) + == None + { graph.add_edge( - nodes[target_index + n], nodes[source_index + n], + nodes[target_index + n], py.None(), ); } + + if bidirectional { + if graph + .find_edge(nodes[target_index + n], nodes[source_index + n]) + == None + { + graph.add_edge( + nodes[target_index + n], + nodes[source_index + n], + py.None(), + ); + } + } } - graph.add_edge(nodes[0], nodes[n], py.None()); + if graph.find_edge(nodes[0], nodes[n]) == None { + graph.add_edge(nodes[0], nodes[n], py.None()); + } if bidirectional { - graph.add_edge(nodes[n], nodes[0], py.None()); + if graph.find_edge(nodes[n], nodes[0]) == None { + graph.add_edge(nodes[n], nodes[0], py.None()); + } } n *= 2; From 7449f7c94a43e924e9dc8819cbcff319ee8aa0f8 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 17:55:12 -0300 Subject: [PATCH 20/32] add bidirectional tests --- tests/generators/test_binomial_tree.py | 64 +++++++++++++++----------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 7b433a3885..dfc1c3ed33 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -20,34 +20,27 @@ class TestBinomialTreeGraph(unittest.TestCase): def test_binomial_tree_graph(self): expected_edges = {0: [], 1: [(0, 1)], - 2: [(0, 1), (0, 2), (2, 3)], - 3: [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), - (6, 7)], - 4: [(0, 1), (0, 2), (0, 4), (0, 8), - (2, 3), (4, 5), (4, 6), (6, 7), - (8, 9), (8, 10), (8, 12), - (10, 11), (12, 13), (12, 14), - (14, 15)]} + 2: [(0, 1), (2, 3), (0, 2)], + 3: [(0, 1), (2, 3), (0, 2), (4, 5), + (6, 7), (4, 6), (0, 4)], + 4: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), + (4, 6), (0, 4), (8, 9), (10, 11), (8, 10), + (12, 13), (14, 15), (12, 14), (8, 12), (0, 8)]} for n in range(5): with self.subTest(n=n): graph = retworkx.generators.binomial_tree_graph(n) self.assertEqual(len(graph), 2**n) self.assertEqual(len(graph.edges()), 2**n - 1) - for edge in list(graph.edge_list()): - self.assertIn(edge, expected_edges[n]) + self.assertEqual(list(graph.edge_list()), expected_edges[n]) def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(4))) - expected_edges = [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), - (6, 7)] + expected_edges = [(0, 1), (2, 3), (0, 2)] self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) - for edge in list(graph.edge_list()): - self.assertIn(edge, expected_edges) + self.assertEqual(list(graph.edge_list()), expected_edges) def test_binomial_tree_graph_weight_less_nodes(self): graph = retworkx.generators.binomial_tree_graph( @@ -70,22 +63,18 @@ def test_binomial_tree_no_order(self): def test_directed_binomial_tree_graph(self): expected_edges = {0: [], 1: [(0, 1)], - 2: [(0, 1), (0, 2), (2, 3)], - 3: [(0, 1), (0, 2), (0, 4), - (2, 3), (4, 5), (4, 6), - (6, 7)], - 4: [(0, 1), (0, 2), (0, 4), (0, 8), - (2, 3), (4, 5), (4, 6), (6, 7), - (8, 9), (8, 10), (8, 12), - (10, 11), (12, 13), (12, 14), - (14, 15)]} + 2: [(0, 1), (2, 3), (0, 2)], + 3: [(0, 1), (2, 3), (0, 2), (4, 5), + (6, 7), (4, 6), (0, 4)], + 4: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), + (4, 6), (0, 4), (8, 9), (10, 11), (8, 10), + (12, 13), (14, 15), (12, 14), (8, 12), (0, 8)]} for n in range(5): with self.subTest(n=n): graph = retworkx.generators.directed_binomial_tree_graph(n) self.assertEqual(len(graph), 2**n) self.assertEqual(len(graph.edges()), 2**n - 1) - for edge in list(graph.edge_list()): - self.assertIn(edge, expected_edges[n]) + self.assertEqual(list(graph.edge_list()), expected_edges[n]) def test_directed_binomial_tree_graph_weights(self): graph = retworkx.generators.directed_binomial_tree_graph( @@ -112,3 +101,24 @@ def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.directed_binomial_tree_graph( weights=list(range(4))) + + def test_directed_binomial_tree_graph_bidirectional(self): + expected_edges = {0: [], + 1: [(0, 1), (1, 0)], + 2: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0)], + 3: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0), + (4, 5), (5, 4), (6, 7), (7, 6), (4, 6), (6, 4), + (0, 4), (4, 0)], + 4: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0), + (4, 5), (5, 4), (6, 7), (7, 6), (4, 6), (6, 4), + (0, 4), (4, 0), (8, 9), (9, 8), (10, 11), (11, 10), + (8, 10), (10, 8), (12, 13), (13, 12), (14, 15), + (15, 14), (12, 14), (14, 12), (8, 12), (12, 8), + (0, 8), (8, 0)]} + for n in range(5): + with self.subTest(n=n): + graph = retworkx.generators.directed_binomial_tree_graph( + n, bidirectional=True) + self.assertEqual(len(graph), 2**n) + self.assertEqual(len(graph.edges()), 2 * (2**n - 1)) + self.assertEqual(list(graph.edge_list()), expected_edges[n]) From 43158eedb6d3654a10d05c08c79311779791d3ef Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 18:01:28 -0300 Subject: [PATCH 21/32] clippy --- src/generators.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 564a20d0e1..1e266456c3 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1193,17 +1193,16 @@ pub fn directed_binomial_tree_graph( ); } - if bidirectional { - if graph + if bidirectional + && graph .find_edge(nodes[target_index + n], nodes[source_index + n]) == None - { - graph.add_edge( - nodes[target_index + n], - nodes[source_index + n], - py.None(), - ); - } + { + graph.add_edge( + nodes[target_index + n], + nodes[source_index + n], + py.None(), + ); } } @@ -1211,10 +1210,8 @@ pub fn directed_binomial_tree_graph( graph.add_edge(nodes[0], nodes[n], py.None()); } - if bidirectional { - if graph.find_edge(nodes[n], nodes[0]) == None { - graph.add_edge(nodes[n], nodes[0], py.None()); - } + if bidirectional && graph.find_edge(nodes[n], nodes[0]) == None { + graph.add_edge(nodes[n], nodes[0], py.None()); } n *= 2; From ee8017e5407811f0345d37002ee8110b1d3dbdcc Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 21:00:43 -0300 Subject: [PATCH 22/32] lint --- tests/generators/test_binomial_tree.py | 161 +++++++++++++++++++------ 1 file changed, 121 insertions(+), 40 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index dfc1c3ed33..604c36ea4d 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -16,21 +16,43 @@ class TestBinomialTreeGraph(unittest.TestCase): - def test_binomial_tree_graph(self): - expected_edges = {0: [], - 1: [(0, 1)], - 2: [(0, 1), (2, 3), (0, 2)], - 3: [(0, 1), (2, 3), (0, 2), (4, 5), - (6, 7), (4, 6), (0, 4)], - 4: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), - (4, 6), (0, 4), (8, 9), (10, 11), (8, 10), - (12, 13), (14, 15), (12, 14), (8, 12), (0, 8)]} + expected_edges = { + 0: [], + 1: [(0, 1)], + 2: [(0, 1), (2, 3), (0, 2)], + 3: [ + (0, 1), + (2, 3), + (0, 2), + (4, 5), + (6, 7), + (4, 6), + (0, 4) + ], + 4: [ + (0, 1), + (2, 3), + (0, 2), + (4, 5), + (6, 7), + (4, 6), + (0, 4), + (8, 9), + (10, 11), + (8, 10), + (12, 13), + (14, 15), + (12, 14), + (8, 12), + (0, 8), + ], + } for n in range(5): with self.subTest(n=n): graph = retworkx.generators.binomial_tree_graph(n) - self.assertEqual(len(graph), 2**n) - self.assertEqual(len(graph.edges()), 2**n - 1) + self.assertEqual(len(graph), 2 ** n) + self.assertEqual(len(graph.edges()), 2 ** n - 1) self.assertEqual(list(graph.edge_list()), expected_edges[n]) def test_binomial_tree_graph_weights(self): @@ -53,39 +75,56 @@ def test_binomial_tree_graph_weight_less_nodes(self): def test_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): - retworkx.generators.binomial_tree_graph( - 2, weights=list(range(7))) + retworkx.generators.binomial_tree_graph(2, weights=list(range(7))) def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.binomial_tree_graph(weights=list(range(4))) def test_directed_binomial_tree_graph(self): - expected_edges = {0: [], - 1: [(0, 1)], - 2: [(0, 1), (2, 3), (0, 2)], - 3: [(0, 1), (2, 3), (0, 2), (4, 5), - (6, 7), (4, 6), (0, 4)], - 4: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), - (4, 6), (0, 4), (8, 9), (10, 11), (8, 10), - (12, 13), (14, 15), (12, 14), (8, 12), (0, 8)]} + expected_edges = { + 0: [], + 1: [(0, 1)], + 2: [(0, 1), (2, 3), (0, 2)], + 3: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), (4, 6), (0, 4)], + 4: [ + (0, 1), + (2, 3), + (0, 2), + (4, 5), + (6, 7), + (4, 6), + (0, 4), + (8, 9), + (10, 11), + (8, 10), + (12, 13), + (14, 15), + (12, 14), + (8, 12), + (0, 8), + ], + } + for n in range(5): with self.subTest(n=n): graph = retworkx.generators.directed_binomial_tree_graph(n) - self.assertEqual(len(graph), 2**n) - self.assertEqual(len(graph.edges()), 2**n - 1) + self.assertEqual(len(graph), 2 ** n) + self.assertEqual(len(graph.edges()), 2 ** n - 1) self.assertEqual(list(graph.edge_list()), expected_edges[n]) def test_directed_binomial_tree_graph_weights(self): graph = retworkx.generators.directed_binomial_tree_graph( - 2, weights=list(range(4))) + 2, weights=list(range(4)) + ) self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) self.assertEqual(len(graph.edges()), 3) def test_directed_binomial_tree_graph_weight_less_nodes(self): graph = retworkx.generators.directed_binomial_tree_graph( - 2, weights=list(range(2))) + 2, weights=list(range(2)) + ) self.assertEqual(len(graph), 4) expected_weights = [x for x in range(2)] expected_weights.extend([None, None]) @@ -103,22 +142,64 @@ def test_directed_binomial_tree_no_order(self): weights=list(range(4))) def test_directed_binomial_tree_graph_bidirectional(self): - expected_edges = {0: [], - 1: [(0, 1), (1, 0)], - 2: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0)], - 3: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0), - (4, 5), (5, 4), (6, 7), (7, 6), (4, 6), (6, 4), - (0, 4), (4, 0)], - 4: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0), - (4, 5), (5, 4), (6, 7), (7, 6), (4, 6), (6, 4), - (0, 4), (4, 0), (8, 9), (9, 8), (10, 11), (11, 10), - (8, 10), (10, 8), (12, 13), (13, 12), (14, 15), - (15, 14), (12, 14), (14, 12), (8, 12), (12, 8), - (0, 8), (8, 0)]} + expected_edges = { + 0: [], + 1: [(0, 1), (1, 0)], + 2: [(0, 1), (1, 0), (2, 3), (3, 2), (0, 2), (2, 0)], + 3: [ + (0, 1), + (1, 0), + (2, 3), + (3, 2), + (0, 2), + (2, 0), + (4, 5), + (5, 4), + (6, 7), + (7, 6), + (4, 6), + (6, 4), + (0, 4), + (4, 0), + ], + 4: [ + (0, 1), + (1, 0), + (2, 3), + (3, 2), + (0, 2), + (2, 0), + (4, 5), + (5, 4), + (6, 7), + (7, 6), + (4, 6), + (6, 4), + (0, 4), + (4, 0), + (8, 9), + (9, 8), + (10, 11), + (11, 10), + (8, 10), + (10, 8), + (12, 13), + (13, 12), + (14, 15), + (15, 14), + (12, 14), + (14, 12), + (8, 12), + (12, 8), + (0, 8), + (8, 0), + ], + } for n in range(5): with self.subTest(n=n): graph = retworkx.generators.directed_binomial_tree_graph( - n, bidirectional=True) - self.assertEqual(len(graph), 2**n) - self.assertEqual(len(graph.edges()), 2 * (2**n - 1)) + n, bidirectional=True + ) + self.assertEqual(len(graph), 2 ** n) + self.assertEqual(len(graph.edges()), 2 * (2 ** n - 1)) self.assertEqual(list(graph.edge_list()), expected_edges[n]) From d598afd725c5e65d77a38e1a3bb1409258a8cbec Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 21:08:29 -0300 Subject: [PATCH 23/32] lint --- tests/generators/test_binomial_tree.py | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index 604c36ea4d..e035461a10 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -21,15 +21,7 @@ def test_binomial_tree_graph(self): 0: [], 1: [(0, 1)], 2: [(0, 1), (2, 3), (0, 2)], - 3: [ - (0, 1), - (2, 3), - (0, 2), - (4, 5), - (6, 7), - (4, 6), - (0, 4) - ], + 3: [(0, 1), (2, 3), (0, 2), (4, 5), (6, 7), (4, 6), (0, 4)], 4: [ (0, 1), (2, 3), @@ -57,7 +49,8 @@ def test_binomial_tree_graph(self): def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( - 2, weights=list(range(4))) + 2, weights=list(range(4)) + ) expected_edges = [(0, 1), (2, 3), (0, 2)] self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) @@ -66,7 +59,8 @@ def test_binomial_tree_graph_weights(self): def test_binomial_tree_graph_weight_less_nodes(self): graph = retworkx.generators.binomial_tree_graph( - 2, weights=list(range(2))) + 2, weights=list(range(2)) + ) self.assertEqual(len(graph), 4) expected_weights = [x for x in range(2)] expected_weights.extend([None, None]) @@ -75,11 +69,15 @@ def test_binomial_tree_graph_weight_less_nodes(self): def test_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): - retworkx.generators.binomial_tree_graph(2, weights=list(range(7))) + retworkx.generators.binomial_tree_graph( + 2, weights=list(range(7)) + ) def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): - retworkx.generators.binomial_tree_graph(weights=list(range(4))) + retworkx.generators.binomial_tree_graph( + weights=list(range(4)) + ) def test_directed_binomial_tree_graph(self): expected_edges = { @@ -134,12 +132,14 @@ def test_directed_binomial_tree_graph_weight_less_nodes(self): def test_directed_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): retworkx.generators.directed_binomial_tree_graph( - 2, weights=list(range(7))) + 2, weights=list(range(7)) + ) def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.directed_binomial_tree_graph( - weights=list(range(4))) + weights=list(range(4)) + ) def test_directed_binomial_tree_graph_bidirectional(self): expected_edges = { From 23e4e5ee8ad7778e3df64bed5bbbd4adbd195795 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Fri, 7 May 2021 21:16:57 -0300 Subject: [PATCH 24/32] run black --- tests/generators/test_binomial_tree.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/generators/test_binomial_tree.py b/tests/generators/test_binomial_tree.py index e035461a10..02d86369ea 100644 --- a/tests/generators/test_binomial_tree.py +++ b/tests/generators/test_binomial_tree.py @@ -50,7 +50,7 @@ def test_binomial_tree_graph(self): def test_binomial_tree_graph_weights(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(4)) - ) + ) expected_edges = [(0, 1), (2, 3), (0, 2)] self.assertEqual(len(graph), 4) self.assertEqual([x for x in range(4)], graph.nodes()) @@ -60,7 +60,7 @@ def test_binomial_tree_graph_weights(self): def test_binomial_tree_graph_weight_less_nodes(self): graph = retworkx.generators.binomial_tree_graph( 2, weights=list(range(2)) - ) + ) self.assertEqual(len(graph), 4) expected_weights = [x for x in range(2)] expected_weights.extend([None, None]) @@ -69,15 +69,11 @@ def test_binomial_tree_graph_weight_less_nodes(self): def test_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): - retworkx.generators.binomial_tree_graph( - 2, weights=list(range(7)) - ) + retworkx.generators.binomial_tree_graph(2, weights=list(range(7))) def test_binomial_tree_no_order(self): with self.assertRaises(TypeError): - retworkx.generators.binomial_tree_graph( - weights=list(range(4)) - ) + retworkx.generators.binomial_tree_graph(weights=list(range(4))) def test_directed_binomial_tree_graph(self): expected_edges = { @@ -133,13 +129,13 @@ def test_directed_binomial_tree_graph_weights_greater_nodes(self): with self.assertRaises(IndexError): retworkx.generators.directed_binomial_tree_graph( 2, weights=list(range(7)) - ) + ) def test_directed_binomial_tree_no_order(self): with self.assertRaises(TypeError): retworkx.generators.directed_binomial_tree_graph( weights=list(range(4)) - ) + ) def test_directed_binomial_tree_graph_bidirectional(self): expected_edges = { From 7aa3d3cdf3b99ea36ca4f20d9aa35c64cc85238d Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 18 May 2021 10:07:40 -0300 Subject: [PATCH 25/32] fix merge leftover --- src/generators.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index be67fef6b2..6e847054e6 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1225,8 +1225,6 @@ pub fn directed_binomial_tree_graph( }) } -||||||| merged common ancestors -======= /// Generate an undirected hexagonal lattice graph. /// /// :param int rows: The number of rows to generate the graph with. @@ -1437,7 +1435,6 @@ pub fn directed_hexagonal_lattice_graph( }) } ->>>>>>> upstream/main #[pymodule] pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(cycle_graph))?; From f977eafefa4d28c984a99d114bcbd3f048be0c39 Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 18 May 2021 10:10:27 -0300 Subject: [PATCH 26/32] fix lint --- src/generators.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 6e847054e6..376d3c8d2b 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -984,7 +984,6 @@ pub fn directed_grid_graph( }) } -<<<<<<< HEAD /// Generate an undirected binomial tree of order n recursively. /// /// :param int order: Order of the binomial tree. From 0fef932b46541feac6f2a7b5a45829571fe5e18e Mon Sep 17 00:00:00 2001 From: nahumsa Date: Tue, 18 May 2021 10:11:52 -0300 Subject: [PATCH 27/32] add newline release notes --- .../add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml b/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml index 5f0951a845..23bef73d62 100644 --- a/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml +++ b/releasenotes/notes/add-binomial-tree-graph-generator-1f6ff6ba3809b901.yaml @@ -1,4 +1,4 @@ --- features: - | - Added a new generator for constructing a binomial tree graph (:func:`retworkx.generators.binomial_tree_graph`). \ No newline at end of file + Added a new generator for constructing a binomial tree graph (:func:`retworkx.generators.binomial_tree_graph`). From 7b3238afdb042061b44ed7a0e99b78797c29f91a Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Fri, 21 May 2021 08:52:09 -0300 Subject: [PATCH 28/32] add `.is_none()` assertion Co-authored-by: Matthew Treinish --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 376d3c8d2b..ac77608757 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1204,7 +1204,7 @@ pub fn directed_binomial_tree_graph( } } - if graph.find_edge(nodes[0], nodes[n]) == None { + if graph.find_edge(nodes[0], nodes[n]).is_none() { graph.add_edge(nodes[0], nodes[n], py.None()); } From 534d49a80be5b8972e0212b2e8808093e53e4fb5 Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Fri, 21 May 2021 08:52:46 -0300 Subject: [PATCH 29/32] `order` required arg Co-authored-by: Matthew Treinish --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index ac77608757..a42208cff8 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1022,7 +1022,7 @@ pub fn directed_grid_graph( /// image /// #[pyfunction(multigraph = true)] -#[text_signature = "(order=None, /, weights=None, multigraph=True)"] +#[text_signature = "(order, /, weights=None, multigraph=True)"] pub fn binomial_tree_graph( py: Python, order: u32, From ad0d838321d0a96f43e0d22352a8c92fab910b92 Mon Sep 17 00:00:00 2001 From: Nahum Rosa Cruz Sa <49600259+nahumsa@users.noreply.github.com> Date: Fri, 21 May 2021 08:53:02 -0300 Subject: [PATCH 30/32] `order` required arg Co-authored-by: Matthew Treinish --- src/generators.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index a42208cff8..5212b92422 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1130,7 +1130,7 @@ pub fn binomial_tree_graph( /// image /// #[pyfunction(bidirectional = "false")] -#[text_signature = "(/, order=None, weights=None, bidirectional=False)"] +#[text_signature = "(order, /, weights=None, bidirectional=False)"] pub fn directed_binomial_tree_graph( py: Python, order: u32, From c5fe7d2335fe3b2602d68520970b0f687006d367 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 21 May 2021 10:14:14 -0400 Subject: [PATCH 31/32] Use `.is_none()` instead of `== None` everywhere --- src/generators.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/generators.rs b/src/generators.rs index 5212b92422..198f12d85e 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1182,7 +1182,7 @@ pub fn directed_binomial_tree_graph( let target_index = target.index(); if graph.find_edge(nodes[source_index + n], nodes[target_index + n]) - == None + .is_none() { graph.add_edge( nodes[source_index + n], @@ -1194,7 +1194,7 @@ pub fn directed_binomial_tree_graph( if bidirectional && graph .find_edge(nodes[target_index + n], nodes[source_index + n]) - == None + .is_none() { graph.add_edge( nodes[target_index + n], @@ -1208,7 +1208,7 @@ pub fn directed_binomial_tree_graph( graph.add_edge(nodes[0], nodes[n], py.None()); } - if bidirectional && graph.find_edge(nodes[n], nodes[0]) == None { + if bidirectional && graph.find_edge(nodes[n], nodes[0]).is_none() { graph.add_edge(nodes[n], nodes[0], py.None()); } From fd1707a970728301103202cce57d00ca0ab8ff6a Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 21 May 2021 10:18:28 -0400 Subject: [PATCH 32/32] Run cargo fmt --- src/generators.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/generators.rs b/src/generators.rs index 198f12d85e..8750d631f4 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1181,7 +1181,8 @@ pub fn directed_binomial_tree_graph( let source_index = source.index(); let target_index = target.index(); - if graph.find_edge(nodes[source_index + n], nodes[target_index + n]) + if graph + .find_edge(nodes[source_index + n], nodes[target_index + n]) .is_none() { graph.add_edge(