Function rustworkx_core::steiner_tree::steiner_tree

source ·
pub fn steiner_tree<G, F, E>(
    graph: G,
    terminal_nodes: &[G::NodeId],
    weight_fn: F,
) -> Result<Option<SteinerTreeResult>, E>
Expand description

Return an approximation to the minimum Steiner tree of a graph.

The minimum tree of graph with regard to a set of terminal_nodes is a tree within graph that spans those nodes and has a minimum size (measured as the sum of edge weights) amoung all such trees.

The minimum steiner tree can be approximated by computing the minimum spanning tree of the subgraph of the metric closure of graph induced by the terminal nodes, where the metric closure of graph is the complete graph in which each edge is weighted by the shortest path distance between nodes in graph.

This algorithm [1]_ produces a tree whose weight is within a :math:(2 - (2 / t)) factor of the weight of the optimal Steiner tree where :math:t is the number of terminal nodes. The algorithm implemented here is due to [2]_ . It avoids computing all pairs shortest paths but rather reduces the problem to a single source shortest path and a minimum spanning tree problem.

Arguments: graph: The input graph to compute the steiner tree of terminal_nodes: The terminal nodes of the steiner tree weight_fn: A callable weight function that will be passed an edge reference for each edge in the graph and it is expected to return a Result<f64> which if it doesn’t error represents the weight of that edge.

Returns a custom struct that contains a set of nodes and edges and None if the graph is disconnected relative to the terminal nodes.

§Example

use std::convert::Infallible;

use rustworkx_core::petgraph::Graph;
use rustworkx_core::petgraph::graph::NodeIndex;
use rustworkx_core::petgraph::Undirected;
use rustworkx_core::petgraph::graph::EdgeReference;
use rustworkx_core::petgraph::visit::{IntoEdgeReferences, EdgeRef};

use rustworkx_core::steiner_tree::steiner_tree;

let input_graph = Graph::<(), u8, Undirected>::from_edges(&[
    (0, 1, 10),
    (1, 2, 10),
    (2, 3, 10),
    (3, 4, 10),
    (4, 5, 10),
    (1, 6, 1),
    (6, 4, 1),
]);

let weight_fn = |e: EdgeReference<u8>| -> Result<f64, Infallible> {
   Ok(*e.weight() as f64)
};
let terminal_nodes = vec![
    NodeIndex::new(0),
    NodeIndex::new(1),
    NodeIndex::new(2),
    NodeIndex::new(3),
    NodeIndex::new(4),
    NodeIndex::new(5),
];

let tree = steiner_tree(&input_graph, &terminal_nodes, weight_fn).unwrap().unwrap();

.. [1] Kou, Markowsky & Berman, “A fast algorithm for Steiner trees” Acta Informatica 15, 141–145 (1981). https://link.springer.com/article/10.1007/BF00288961 .. [2] Kurt Mehlhorn, “A faster approximation algorithm for the Steiner problem in graphs” https://doi.org/10.1016/0020-0190(88)90066-X