yog/pathfinding/matrix

Optimized distance matrix computation for subsets of nodes.

This module provides an auto-selecting algorithm for computing shortest path distances between specified “points of interest” (POIs) in a graph. It intelligently chooses between Floyd-Warshall, Johnson’s, and multiple Dijkstra runs based on graph characteristics and POI density.

Algorithm Selection

With negative weights support (when with_subtract is provided):

AlgorithmWhen SelectedComplexity
Johnson’sSparse graphs (E < V²/4)O(V² log V + VE) then filter
Floyd-WarshallDense graphs (E ≥ V²/4)O(V³) then filter

Without negative weights (when with_subtract is None):

AlgorithmWhen SelectedComplexity
Dijkstra × PFew POIs (P ≤ V/3)O(P × (V + E) log V)
Floyd-WarshallMany POIs (P > V/3)O(V³) then filter

Heuristics

For graphs with potential negative weights:

For non-negative weights only:

Use Cases

Example

// Compute distances only between important waypoints
let pois = [start, waypoint_a, waypoint_b, goal]
let distances = matrix.distance_matrix(
  in: graph,
  between: pois,
  with_zero: 0,
  with_add: int.add,
  with_compare: int.compare,
)
// Result contains only 4×4 = 16 distances, not full V×V matrix

References

Values

pub fn distance_matrix(
  in graph: model.Graph(n, e),
  between points_of_interest: List(Int),
  with_zero zero: e,
  with_add add: fn(e, e) -> e,
  with_subtract subtract: option.Option(fn(e, e) -> e),
  with_compare compare: fn(e, e) -> order.Order,
) -> Result(dict.Dict(#(Int, Int), e), Nil)

Computes shortest distances between all pairs of points of interest.

Automatically chooses the best algorithm based on:

  • Whether negative weights are possible (presence of with_subtract)
  • Graph sparsity (E relative to V²)
  • POI density (P relative to V)

Time Complexity: O(V³), O(V² log V + VE), or O(P × (V + E) log V)

Parameters

  • with_subtract: Optional subtraction function for negative weight support. If provided, enables Johnson’s algorithm for sparse graphs with negative weights. If None, assumes non-negative weights and may use Dijkstra.

Examples

// Non-negative weights only (uses Dijkstra or Floyd-Warshall)
matrix.distance_matrix(
  in: graph,
  between: pois,
  with_zero: 0,
  with_add: int.add,
  with_subtract: None,
  with_compare: int.compare,
)

// Support negative weights (uses Johnson's or Floyd-Warshall)
matrix.distance_matrix(
  in: graph,
  between: pois,
  with_zero: 0,
  with_add: int.add,
  with_subtract: Some(int.subtract),
  with_compare: int.compare,
)
Search Document