github.com/LdDl/ch@v1.7.8/vanilla_dijkstra.go (about) 1 package ch 2 3 import ( 4 "container/heap" 5 "log" 6 ) 7 8 // VanillaShortestPath Computes and returns shortest path and it's cost (vanilla Dijkstra's algorithm) 9 // 10 // If there are some errors then function returns '-1.0' as cost and nil as shortest path 11 // 12 // source User's definied ID of source vertex 13 // target User's definied ID of target vertex 14 // 15 // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm 16 func (graph *Graph) VanillaShortestPath(source, target int64) (float64, []int64) { 17 18 if source == target { 19 return 0, []int64{source} 20 } 21 var ok bool 22 23 if source, ok = graph.mapping[source]; !ok { 24 log.Println("No such source") 25 return -1.0, nil 26 } 27 if target, ok = graph.mapping[target]; !ok { 28 log.Println("No such target") 29 return -1.0, nil 30 } 31 32 // create vertex set Q 33 Q := &minHeap{} 34 35 // dist[source] ← 0 36 distance := make(map[int64]float64, len(graph.Vertices)) 37 distance[source] = 0 38 39 // prev[v] ← UNDEFINED 40 prev := make(map[int64]int64, len(graph.Vertices)) 41 // for each vertex v in Graph: 42 for i := range graph.Vertices { 43 // if v ≠ source: 44 if graph.Vertices[i].vertexNum != source { 45 // dist[v] = INFINITY 46 distance[graph.Vertices[i].vertexNum] = Infinity 47 } 48 // prev[v] ← UNDEFINED 49 // nothing here 50 } 51 Q.add_with_priority(graph.Vertices[source].vertexNum, distance[graph.Vertices[source].vertexNum]) 52 heap.Init(Q) 53 // while Q is not empty: 54 for Q.Len() != 0 { 55 // u ← Q.extract_min() 56 u := heap.Pop(Q).(*minHeapVertex) 57 58 // if u == target: 59 if u.id == target { 60 // break 61 break 62 } 63 64 vertexList := graph.Vertices[u.id].outIncidentEdges 65 66 // for each neighbor v of u: 67 for v := range vertexList { 68 neighbor := vertexList[v].vertexID 69 if v1, ok1 := graph.shortcuts[u.id]; ok1 { 70 if _, ok2 := v1[neighbor]; ok2 { 71 // Ignore shortcut 72 continue 73 } 74 } 75 cost := vertexList[v].weight 76 // alt ← dist[u] + length(u, v) 77 alt := distance[u.id] + cost 78 // if alt < dist[v] 79 if distance[neighbor] > alt { 80 // dist[v] ← alt 81 distance[neighbor] = alt 82 // prev[v] ← u 83 prev[neighbor] = u.id 84 // Q.decrease_priority(v, alt) 85 // Q.decrease_priority(v, alt) 86 Q.add_with_priority(neighbor, alt) 87 } 88 } 89 // heap.Init(Q) 90 } 91 92 if distance[target] == Infinity { 93 return -1, []int64{} 94 } 95 // path = [] 96 var path []int64 97 // u = target 98 u := target 99 100 // while prev[u] is defined: 101 for { 102 if _, ok := prev[u]; !ok { 103 break 104 } 105 // path.push_front(u) 106 temp := make([]int64, len(path)+1) 107 temp[0] = u 108 copy(temp[1:], path) 109 path = temp 110 111 // u = prev[u] 112 u = prev[u] 113 } 114 115 temp := make([]int64, len(path)+1) 116 temp[0] = source 117 copy(temp[1:], path) 118 path = temp 119 120 usersLabelsPath := make([]int64, len(path)) 121 for e := 0; e < len(usersLabelsPath); e++ { 122 usersLabelsPath[e] = graph.Vertices[path[e]].Label 123 } 124 125 // return path, prev 126 return distance[target], usersLabelsPath 127 }