Single-source shortest paths with non-negative edge weights.
dist(v) is the shortest distance from source to v, or
GRAPH_INFINITY when v is unreachable. prev(v) is the
predecessor of v on that shortest path, or GRAPH_NO_PREDECESSOR
for the source and for unreachable vertices. Both outputs are
allocated to the number of vertices.
prev is deterministic: see the module documentation on
reproducibility. Reports ERROR_VALIDATION for a malformed or
non-square adjacency matrix, an out-of-range source, or any
negative edge weight; in that case both outputs come back zero-size.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(csr_t), | intent(in) | :: | graph |
Square weighted adjacency matrix of the graph |
||
| integer(kind=default_int), | intent(in) | :: | source |
Source vertex, in |
||
| real(kind=dp), | intent(out), | allocatable | :: | dist(:) |
Shortest distance to each vertex |
|
| integer(kind=default_int), | intent(out), | allocatable | :: | prev(:) |
Predecessor of each vertex on its shortest path |
|
| type(error_t), | intent(out), | optional | :: | err |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=dp), | private | :: | candidate | ||||
| real(kind=dp), | private | :: | dist_u | ||||
| integer(kind=default_int), | private | :: | k | ||||
| integer(kind=int64), | private | :: | key | ||||
| integer(kind=default_int), | private | :: | n | ||||
| integer(kind=int32), | private | :: | payload | ||||
| type(heap_t), | private | :: | queue | ||||
| logical, | private, | allocatable | :: | settled(:) | |||
| integer(kind=default_int), | private | :: | u | ||||
| integer(kind=default_int), | private | :: | v |
subroutine dijkstra(graph, source, dist, prev, err) !! Single-source shortest paths with non-negative edge weights. !! !! `dist(v)` is the shortest distance from `source` to `v`, or !! `GRAPH_INFINITY` when `v` is unreachable. `prev(v)` is the !! predecessor of `v` on that shortest path, or `GRAPH_NO_PREDECESSOR` !! for the source and for unreachable vertices. Both outputs are !! allocated to the number of vertices. !! !! `prev` is deterministic: see the module documentation on !! reproducibility. Reports `ERROR_VALIDATION` for a malformed or !! non-square adjacency matrix, an out-of-range `source`, or any !! negative edge weight; in that case both outputs come back zero-size. type(csr_t), intent(in) :: graph !! Square weighted adjacency matrix of the graph integer(default_int), intent(in) :: source !! Source vertex, in `1:n` real(dp), allocatable, intent(out) :: dist(:) !! Shortest distance to each vertex integer(default_int), allocatable, intent(out) :: prev(:) !! Predecessor of each vertex on its shortest path type(error_t), intent(out), optional :: err type(heap_t) :: queue logical, allocatable :: settled(:) integer(default_int) :: n, u, v, k integer(int64) :: key integer(int32) :: payload real(dp) :: dist_u, candidate if (.not. check_graph(graph, source, err)) then allocate (dist(0)) allocate (prev(0)) return end if if (.not. check_weights(graph, err)) then allocate (dist(0)) allocate (prev(0)) return end if n = graph%n_rows() allocate (dist(n)) allocate (prev(n)) allocate (settled(n)) dist = GRAPH_INFINITY prev = GRAPH_NO_PREDECESSOR settled = .false. dist(source) = 0.0_dp call queue%init(n) call queue%push(distance_key(0.0_dp), int(source, int32)) do while (.not. queue%is_empty()) call queue%pop(key, payload) u = int(payload, default_int) if (settled(u)) cycle settled(u) = .true. dist_u = dist(u) do k = graph%row_ptr(u), graph%row_ptr(u + 1) - 1 v = graph%col_idx(k) candidate = dist_u + graph%values(k) if (candidate < dist(v)) then dist(v) = candidate prev(v) = u call queue%push(distance_key(candidate), int(v, int32)) end if end do end do call queue%destroy() end subroutine dijkstra