@@ -2420,6 +2420,93 @@ pub fn barbell_graph(
2420
2420
} )
2421
2421
}
2422
2422
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
+
2423
2510
#[ pymodule]
2424
2511
pub fn generators ( _py : Python , m : & PyModule ) -> PyResult < ( ) > {
2425
2512
m. add_wrapped ( wrap_pyfunction ! ( cycle_graph) ) ?;
@@ -2444,5 +2531,6 @@ pub fn generators(_py: Python, m: &PyModule) -> PyResult<()> {
2444
2531
m. add_wrapped ( wrap_pyfunction ! ( full_rary_tree) ) ?;
2445
2532
m. add_wrapped ( wrap_pyfunction ! ( generalized_petersen_graph) ) ?;
2446
2533
m. add_wrapped ( wrap_pyfunction ! ( barbell_graph) ) ?;
2534
+ m. add_wrapped ( wrap_pyfunction ! ( ladder_graph) ) ?;
2447
2535
Ok ( ( ) )
2448
2536
}
0 commit comments