Skip to content

Commit

Permalink
Added ladder graph generators and test_ladder
Browse files Browse the repository at this point in the history
  • Loading branch information
Seungwook-Woo committed Nov 30, 2022
1 parent ced0310 commit 15be344
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
88 changes: 88 additions & 0 deletions src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2420,6 +2420,93 @@ pub fn barbell_graph(
})
}

/// Generate a ladder graph
///
/// :param int num_node: The number of nodes to generate the graph with. Node
/// weights will be None if this is specified. If both ``num_node`` and
/// ``weights`` are set this will be ignored and ``weights``will be used.
/// :param list weights: A list of node weights. If both ``num_node`` and
/// ``weights`` are set this will be ignored and ``weights`` will be used.
/// :param bool multigraph: When set to False the output
/// :class:`~rustworkx.PyGraph` object will not be a multigraph and
/// won't allow parallel edges to be added. Instead
/// calls which would create a parallel edge will update the existing edge.
///
/// :returns: The generated ladder graph
/// :rtype: PyGraph
/// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified
///
/// .. jupyter-execute::
///
/// import rustworkx.generators
/// from rustworkx.visualization import mpl_draw
///
/// graph = rustworkx.generators.ladder_graph(5)
/// mpl_draw(graph)
///
#[pyfunction(multigraph = true)]
#[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True")]
pub fn ladder_graph(
py: Python,
num_nodes: Option<usize>,
weights: Option<Vec<PyObject>>,
multigraph: bool,
) -> PyResult<graph::PyGraph> {
if weights.is_none() && num_nodes.is_none() {
return Err(PyIndexError::new_err(
"num_nodes and weights list not specified",
));
} else if num_nodes.is_none() && weights.as_ref().unwrap().len() % 2 == 1 {
return Err(PyIndexError::new_err(
"length of weights must be even numbers",
));
}
let node_len = if weights.is_none() {
num_nodes.unwrap()
} else {
weights.as_ref().unwrap().len() / 2
};

if node_len == 0 {
return Ok(graph::PyGraph {
graph: StablePyGraph::<Undirected>::default(),
node_removed: false,
multigraph,
attrs: py.None(),
});
}
let num_edges = 3 * node_len - 2;
let mut graph = StablePyGraph::<Undirected>::with_capacity(node_len * 2, num_edges);
match weights {
Some(weights) => {
for weight in weights {
graph.add_node(weight);
}
}
None => {
(0..(node_len * 2)).for_each(|_| {
graph.add_node(py.None());
});
}
};

for rail_a in 0..node_len - 1 {
graph.add_edge(NodeIndex::new(rail_a), NodeIndex::new(rail_a+1), py.None());
let rail_b = rail_a + node_len;
graph.add_edge(NodeIndex::new(rail_b), NodeIndex::new(rail_b+1), py.None());
}
for rung_a in 0..node_len {
graph.add_edge(NodeIndex::new(rung_a), NodeIndex::new(rung_a+node_len), py.None());
}

Ok(graph::PyGraph {
graph,
node_removed: false,
multigraph,
attrs: py.None(),
})
}

#[pymodule]
pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(cycle_graph))?;
Expand All @@ -2444,5 +2531,6 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(full_rary_tree))?;
m.add_wrapped(wrap_pyfunction!(generalized_petersen_graph))?;
m.add_wrapped(wrap_pyfunction!(barbell_graph))?;
m.add_wrapped(wrap_pyfunction!(ladder_graph))?;
Ok(())
}
26 changes: 26 additions & 0 deletions tests/rustworkx_tests/generators/test_ladder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Licensed under the Apache License,

import unittest

import rustworkx


class TestLadderGraph(unittest.TestCase):
def test_ladder_graph(self):
graph = rustworkx.generators.ladder_graph(20)
self.assertEqual(len(graph), 40)
self.assertEqual(len(graph.edges()), 58)

def test_ladder_graph_weights(self):
graph = rustworkx.generators.ladder_graph(weights=list(range(40)))
self.assertEqual(len(graph), 40)
self.assertEqual([x for x in range(40)], graph.nodes())
self.assertEqual(len(graph.edges()), 58)

def test_ladder_no_weights_or_num(self):
with self.assertRaises(IndexError):
rustworkx.generators.ladder_graph()

def test_zero_length_ladder_graph(self):
graph = rustworkx.generators.ladder_graph(0)
self.assertEqual(0, len(graph))

0 comments on commit 15be344

Please sign in to comment.