lnd.xprv/routing/rt/graph/dijkstra.go

68 lines
1.5 KiB
Go
Raw Normal View History

// Copyright (c) 2016 Bitfury Group Limited
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
package graph
import "math"
func DijkstraPathWeight(g *Graph, source, target Vertex) (float64, error) {
dist, _, err := dijkstra(g, source, target)
if err != nil {
return 0, err
}
if _, ok := dist[target]; !ok {
return 0, PathNotFoundError
}
return dist[target], nil
}
func DijkstraPath(g *Graph, source, target Vertex) ([]Vertex, error) {
_, parent, err := dijkstra(g, source, target)
if err != nil {
return nil, err
}
if _, ok := parent[target]; !ok {
return nil, PathNotFoundError
}
path, err := Path(source, target, parent)
if err != nil {
return nil, err
}
return path, nil
}
func dijkstra(g *Graph, source, target Vertex) (map[Vertex]float64, map[Vertex]Vertex, error) {
dist := make(map[Vertex]float64)
colored := make(map[Vertex]bool)
parent := make(map[Vertex]Vertex)
dist[source] = 0
for {
bestDist := math.MaxFloat64
var bestID Vertex
for id, val := range dist {
if val < bestDist && !colored[id] {
bestDist = val
bestID = id
}
}
if bestID == target {
break
}
colored[bestID] = true
targets, err := g.GetNeighbors(bestID)
if err != nil {
return nil, nil, err
}
for id, multiedges := range targets {
for _, edge := range multiedges {
if have, ok := dist[id]; !ok || have > dist[bestID]+edge.Wgt {
dist[id] = dist[bestID] + edge.Wgt
parent[id] = bestID
}
}
}
}
return dist, parent, nil
}