Skip to content

Commit 15be344

Browse files
committed
Added ladder graph generators and test_ladder
1 parent ced0310 commit 15be344

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

Diff for: src/generators.rs

+88
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,93 @@ pub fn barbell_graph(
24202420
})
24212421
}
24222422

2423+
/// Generate a ladder graph
2424+
///
2425+
/// :param int num_node: The number of nodes to generate the graph with. Node
2426+
/// weights will be None if this is specified. If both ``num_node`` and
2427+
/// ``weights`` are set this will be ignored and ``weights``will be used.
2428+
/// :param list weights: A list of node weights. If both ``num_node`` and
2429+
/// ``weights`` are set this will be ignored and ``weights`` will be used.
2430+
/// :param bool multigraph: When set to False the output
2431+
/// :class:`~rustworkx.PyGraph` object will not be a multigraph and
2432+
/// won't allow parallel edges to be added. Instead
2433+
/// calls which would create a parallel edge will update the existing edge.
2434+
///
2435+
/// :returns: The generated ladder graph
2436+
/// :rtype: PyGraph
2437+
/// :raises IndexError: If neither ``num_nodes`` or ``weights`` are specified
2438+
///
2439+
/// .. jupyter-execute::
2440+
///
2441+
/// import rustworkx.generators
2442+
/// from rustworkx.visualization import mpl_draw
2443+
///
2444+
/// graph = rustworkx.generators.ladder_graph(5)
2445+
/// mpl_draw(graph)
2446+
///
2447+
#[pyfunction(multigraph = true)]
2448+
#[pyo3(text_signature = "(/, num_nodes=None, weights=None, multigraph=True")]
2449+
pub fn ladder_graph(
2450+
py: Python,
2451+
num_nodes: Option<usize>,
2452+
weights: Option<Vec<PyObject>>,
2453+
multigraph: bool,
2454+
) -> PyResult<graph::PyGraph> {
2455+
if weights.is_none() && num_nodes.is_none() {
2456+
return Err(PyIndexError::new_err(
2457+
"num_nodes and weights list not specified",
2458+
));
2459+
} else if num_nodes.is_none() && weights.as_ref().unwrap().len() % 2 == 1 {
2460+
return Err(PyIndexError::new_err(
2461+
"length of weights must be even numbers",
2462+
));
2463+
}
2464+
let node_len = if weights.is_none() {
2465+
num_nodes.unwrap()
2466+
} else {
2467+
weights.as_ref().unwrap().len() / 2
2468+
};
2469+
2470+
if node_len == 0 {
2471+
return Ok(graph::PyGraph {
2472+
graph: StablePyGraph::<Undirected>::default(),
2473+
node_removed: false,
2474+
multigraph,
2475+
attrs: py.None(),
2476+
});
2477+
}
2478+
let num_edges = 3 * node_len - 2;
2479+
let mut graph = StablePyGraph::<Undirected>::with_capacity(node_len * 2, num_edges);
2480+
match weights {
2481+
Some(weights) => {
2482+
for weight in weights {
2483+
graph.add_node(weight);
2484+
}
2485+
}
2486+
None => {
2487+
(0..(node_len * 2)).for_each(|_| {
2488+
graph.add_node(py.None());
2489+
});
2490+
}
2491+
};
2492+
2493+
for rail_a in 0..node_len - 1 {
2494+
graph.add_edge(NodeIndex::new(rail_a), NodeIndex::new(rail_a+1), py.None());
2495+
let rail_b = rail_a + node_len;
2496+
graph.add_edge(NodeIndex::new(rail_b), NodeIndex::new(rail_b+1), py.None());
2497+
}
2498+
for rung_a in 0..node_len {
2499+
graph.add_edge(NodeIndex::new(rung_a), NodeIndex::new(rung_a+node_len), py.None());
2500+
}
2501+
2502+
Ok(graph::PyGraph {
2503+
graph,
2504+
node_removed: false,
2505+
multigraph,
2506+
attrs: py.None(),
2507+
})
2508+
}
2509+
24232510
#[pymodule]
24242511
pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> {
24252512
m.add_wrapped(wrap_pyfunction!(cycle_graph))?;
@@ -2444,5 +2531,6 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> {
24442531
m.add_wrapped(wrap_pyfunction!(full_rary_tree))?;
24452532
m.add_wrapped(wrap_pyfunction!(generalized_petersen_graph))?;
24462533
m.add_wrapped(wrap_pyfunction!(barbell_graph))?;
2534+
m.add_wrapped(wrap_pyfunction!(ladder_graph))?;
24472535
Ok(())
24482536
}

Diff for: tests/rustworkx_tests/generators/test_ladder.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Licensed under the Apache License,
2+
3+
import unittest
4+
5+
import rustworkx
6+
7+
8+
class TestLadderGraph(unittest.TestCase):
9+
def test_ladder_graph(self):
10+
graph = rustworkx.generators.ladder_graph(20)
11+
self.assertEqual(len(graph), 40)
12+
self.assertEqual(len(graph.edges()), 58)
13+
14+
def test_ladder_graph_weights(self):
15+
graph = rustworkx.generators.ladder_graph(weights=list(range(40)))
16+
self.assertEqual(len(graph), 40)
17+
self.assertEqual([x for x in range(40)], graph.nodes())
18+
self.assertEqual(len(graph.edges()), 58)
19+
20+
def test_ladder_no_weights_or_num(self):
21+
with self.assertRaises(IndexError):
22+
rustworkx.generators.ladder_graph()
23+
24+
def test_zero_length_ladder_graph(self):
25+
graph = rustworkx.generators.ladder_graph(0)
26+
self.assertEqual(0, len(graph))

0 commit comments

Comments
 (0)