Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Find a route through a graph

std.graph stores nodes and the edges between them. UnGraph edges join two nodes both ways; DiGraph edges run from a source to a target. Each node and edge owns a value, and adding one returns a handle that names it.

from std.graph import UnGraph, GraphError

def minutes(walk: &i64) -> f64:
    f64(*walk)

def main() -> Result[(), AllocError | IoError | GraphError]:
    mut town = UnGraph[str, i64]()?
    home = town.add_node("home")?
    shop = town.add_node("shop")?
    park = town.add_node("park")?
    school = town.add_node("school")?
    town.add_edge(home, shop, 10)?
    town.add_edge(home, park, 4)?
    town.add_edge(park, shop, 3)?
    town.add_edge(shop, school, 6)?
    paths = town.dijkstra(home, &minutes)?
    for stop in paths.path(school)?:
        print(*town.node(stop))?
    print(paths.distance(school))?
    Ok(())
home
park
shop
school
Option[f64].Some(13.0)

The graph does not know what edge values mean, so dijkstra takes a function that turns one into a non-negative weight. The result answers distance and path queries for every node reachable from the start.

Handles stay valid after removals: removing park leaves shop and school naming the same places, and the path now takes the direct road.

from std.graph import UnGraph, GraphError

def minutes(walk: &i64) -> f64:
    f64(*walk)

def main() -> Result[(), AllocError | IoError | GraphError]:
    mut town = UnGraph[str, i64]()?
    home = town.add_node("home")?
    shop = town.add_node("shop")?
    park = town.add_node("park")?
    town.add_edge(home, shop, 10)?
    town.add_edge(home, park, 4)?
    town.add_edge(park, shop, 3)?
    print(town.remove_node(park))?
    print(town.contains_node(park), town.edge_count())?
    print(town.get_node_ref(park), town.get_node_ref(shop))?
    print(town.dijkstra(home, &minutes)?.distance(shop))?
    Ok(())
Option[str].Some("park")
False 1
Option[&str].Nothing Option[&str].Some("shop")
Option[f64].Some(10.0)

Using a removed handle with node or add_edge traps. When a handle may be stale, get_node_ref and get_edge_ref return Nothing instead of trapping, and get_node_mut and get_edge_mut do the same for changes. See the module reference for traversal, topological order, components, spanning trees and costs.