github.com/LdDl/ch@v1.7.8/vanilla_dijkstra_turn_restricted.go (about) 1 package ch 2 3 import ( 4 "container/heap" 5 "log" 6 ) 7 8 // VanillaTurnRestrictedShortestPath Computes and returns turns restricted 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) VanillaTurnRestrictedShortestPath(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 // st := time.Now() 42 // for each vertex v in Graph: 43 for i := range graph.Vertices { 44 // if v ≠ source: 45 if graph.Vertices[i].vertexNum != source { 46 // dist[v] = INFINITY 47 distance[graph.Vertices[i].vertexNum] = Infinity 48 } 49 // prev[v] ← UNDEFINED 50 // nothing here 51 } 52 Q.add_with_priority(graph.Vertices[source].vertexNum, distance[graph.Vertices[source].vertexNum]) 53 heap.Init(Q) 54 prevNodeID := int64(-1) 55 // while Q is not empty: 56 for Q.Len() != 0 { 57 // u ← Q.extract_min() 58 u := heap.Pop(Q).(*minHeapVertex) 59 destinationRestrictionID := int64(-1) 60 if restrictions, ok := graph.restrictions[prevNodeID]; ok { 61 // found some restrictions 62 destinationRestrictionID = restrictions[u.id] 63 } 64 65 // if u == target: 66 if u.id == target { 67 // break 68 break 69 } 70 71 vertexList := graph.Vertices[u.id].outIncidentEdges 72 73 // for each neighbor v of u: 74 for v := range vertexList { 75 neighbor := vertexList[v].vertexID 76 if v1, ok1 := graph.shortcuts[u.id]; ok1 { 77 if _, ok2 := v1[neighbor]; ok2 { 78 // Ignore shortcut 79 continue 80 } 81 } 82 if neighbor == destinationRestrictionID { 83 // If there is a turn restriction 84 distance[u.id] = Infinity 85 continue 86 } 87 cost := vertexList[v].weight 88 // alt ← dist[u] + length(u, v) 89 alt := distance[u.id] + cost 90 // if alt < dist[v] 91 if distance[neighbor] > alt { 92 // dist[v] ← alt 93 distance[neighbor] = alt 94 // prev[v] ← u 95 prev[neighbor] = u.id 96 // Q.decrease_priority(v, alt) 97 // Q.decrease_priority(v, alt) 98 Q.add_with_priority(neighbor, alt) 99 } 100 } 101 102 prevNodeID = u.id 103 // heap.Init(Q) 104 } 105 106 // path = [] 107 var path []int64 108 // u = target 109 u := target 110 111 // while prev[u] is defined: 112 for { 113 if _, ok := prev[u]; !ok { 114 break 115 } 116 // path.push_front(u) 117 temp := make([]int64, len(path)+1) 118 temp[0] = u 119 copy(temp[1:], path) 120 path = temp 121 122 // u = prev[u] 123 u = prev[u] 124 } 125 126 temp := make([]int64, len(path)+1) 127 temp[0] = source 128 copy(temp[1:], path) 129 path = temp 130 131 usersLabelsPath := make([]int64, len(path)) 132 for e := 0; e < len(usersLabelsPath); e++ { 133 usersLabelsPath[e] = graph.Vertices[path[e]].Label 134 } 135 136 return distance[target], usersLabelsPath 137 }