Yen's algorithm for finding the k shortest loopless paths between two nodes.
This algorithm iteratively finds the next shortest path by exploring "spur" deviations from previously found paths. It is a natural extension of Dijkstra's algorithm for applications that require backup routes or alternative paths.
Time Complexity: O(k · N · (E + V log V)) where N is the number of nodes in the shortest path.
Algorithm
- Find the shortest path using Dijkstra.
- For each previously found path, consider every node as a "spur node".
- Temporarily remove the edge following the spur node and all earlier nodes in the path, then run Dijkstra from the spur node to the target.
- Combine the root path with the spur path to form a candidate.
- Select the lowest-weight candidate as the next shortest path.
Example
iex> graph = Yog.from_edges(:directed, [
...> {1, 2, 1}, {1, 3, 2}, {2, 3, 1}, {2, 4, 3},
...> {3, 4, 1}, {3, 5, 4}, {4, 5, 1}
...> ])
iex> {:ok, paths} = Yog.Pathfinding.Yen.k_shortest_paths(graph, 1, 5, 3)
iex> length(paths)
3
iex> hd(paths).weight
4References
- Jin Y. Yen (1971). "Finding the k shortest loopless paths in a network"
Summary
Functions
Finds the k shortest loopless paths from source to target.
Functions
@spec k_shortest_paths( Yog.Graph.t(), Yog.node_id(), Yog.node_id(), pos_integer(), keyword() ) :: {:ok, [Yog.Pathfinding.Path.t()]} | :error
Finds the k shortest loopless paths from source to target.
Options
:with- Function to extract/transform edge weight before pathfinding:zero- Identity value for the weight type (default:0):add- Function to add two weights (default:&Kernel.+/2):compare- Function comparing two weights returning:lt,:eq, or:gt(default:&Yog.Utils.compare/2)
Returns
{:ok, [Path.t()]}— list of paths sorted by total weight, shortest first:error— if no path exists at all