github.com/LdDl/ch@v1.7.8/bidirectional_ch_one_to_n_test.go (about) 1 package ch 2 3 import ( 4 "fmt" 5 "math" 6 "math/rand" 7 "testing" 8 ) 9 10 func TestOneToManyShortestPath(t *testing.T) { 11 g := Graph{} 12 err := graphFromCSV(&g, "./data/pgrouting_osm.csv") 13 if err != nil { 14 t.Error(err) 15 return 16 } 17 t.Log("Please wait until contraction hierarchy is prepared") 18 g.PrepareContractionHierarchies() 19 t.Log("TestShortestPath is starting...") 20 u := int64(106600) 21 v := []int64{5924, 81611, 69618, 68427, 68490} 22 correctAns, correctPath := []float64{61089.42195558673, 94961.78959757874, 78692.8292369651, 61212.00481622628, 71101.1080090782}, []int{418, 866, 591, 314, 353} 23 ans, path := g.ShortestPathOneToMany(u, v) 24 for i := range path { 25 if len(path[i]) != correctPath[i] { 26 t.Errorf("Num of vertices in path should be %d, but got %d", correctPath[i], len(path[i])) 27 return 28 } 29 } 30 for i := range ans { 31 if math.Abs(ans[i]-correctAns[i]) > eps { 32 t.Errorf("Cost of path should be %f, but got %f", correctAns[i], ans[i]) 33 return 34 } 35 } 36 37 t.Log("TestShortestPath is Ok!") 38 } 39 40 func BenchmarkShortestPathOneToMany(b *testing.B) { 41 b.Log("BenchmarkShortestPathOneToMany is starting...") 42 rand.Seed(1337) 43 for k := 2.0; k <= 8; k++ { 44 n := int(math.Pow(2, k)) 45 g, err := generateSyntheticGraph(n) 46 if err != nil { 47 b.Error(err) 48 return 49 } 50 b.ResetTimer() 51 b.Run(fmt.Sprintf("%s/%d/vertices-%d-edges-%d-shortcuts-%d", "CH shortest path", n, len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum()), func(b *testing.B) { 52 for i := 0; i < b.N; i++ { 53 u := int64(rand.Intn(len(g.Vertices))) 54 v := []int64{ 55 int64(rand.Intn(len(g.Vertices))), 56 int64(rand.Intn(len(g.Vertices))), 57 int64(rand.Intn(len(g.Vertices))), 58 int64(rand.Intn(len(g.Vertices))), 59 int64(rand.Intn(len(g.Vertices))), 60 } 61 ans, path := g.ShortestPathOneToMany(u, v) 62 _, _ = ans, path 63 } 64 }) 65 } 66 } 67 68 func BenchmarkOldWayShortestPathOneToMany(b *testing.B) { 69 b.Log("BenchmarkOldWayShortestPathOneToMany is starting...") 70 rand.Seed(1337) 71 for k := 2.0; k <= 8; k++ { 72 n := int(math.Pow(2, k)) 73 g, err := generateSyntheticGraph(n) 74 if err != nil { 75 b.Error(err) 76 return 77 } 78 b.ResetTimer() 79 b.Run(fmt.Sprintf("%s/%d/vertices-%d-edges-%d-shortcuts-%d", "CH shortest path", n, len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum()), func(b *testing.B) { 80 for i := 0; i < b.N; i++ { 81 u := int64(rand.Intn(len(g.Vertices))) 82 v := []int64{ 83 int64(rand.Intn(len(g.Vertices))), 84 int64(rand.Intn(len(g.Vertices))), 85 int64(rand.Intn(len(g.Vertices))), 86 int64(rand.Intn(len(g.Vertices))), 87 int64(rand.Intn(len(g.Vertices))), 88 } 89 for vv := range v { 90 ans, path := g.ShortestPath(u, v[vv]) 91 _, _ = ans, path 92 } 93 } 94 }) 95 } 96 } 97 98 func BenchmarkTargetNodesShortestPathOneToMany(b *testing.B) { 99 g := Graph{} 100 err := graphFromCSV(&g, "./data/pgrouting_osm.csv") 101 if err != nil { 102 b.Error(err) 103 } 104 b.Log("Please wait until contraction hierarchy is prepared") 105 g.PrepareContractionHierarchies() 106 b.Log("BenchmarkTargetNodesShortestPathOneToMany is starting...") 107 b.ResetTimer() 108 109 rand.Seed(1337) 110 for k := 1.0; k <= 7; k++ { 111 u := int64(106600) 112 n := int(math.Pow(2, k)) 113 targets := 1 + rand.Intn(n) 114 v := make([]int64, targets) 115 for t := 0; t < targets; t++ { 116 v[t] = int64(rand.Intn(len(g.Vertices))) 117 } 118 b.Run(fmt.Sprintf("%s/%d/vertices-%d-edges-%d-shortcuts-%d-targets-%d", "CH shortest path", n, len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum(), targets), func(b *testing.B) { 119 for i := 0; i < b.N; i++ { 120 ans, path := g.ShortestPathOneToMany(u, v) 121 _, _ = ans, path 122 } 123 }) 124 } 125 } 126 127 func BenchmarkTargetNodesOldWayShortestPathOneToMany(b *testing.B) { 128 g := Graph{} 129 err := graphFromCSV(&g, "./data/pgrouting_osm.csv") 130 if err != nil { 131 b.Error(err) 132 } 133 b.Log("Please wait until contraction hierarchy is prepared") 134 g.PrepareContractionHierarchies() 135 b.Log("BenchmarkTargetNodesShortestPathOneToMany is starting...") 136 b.ResetTimer() 137 138 rand.Seed(1337) 139 for k := 1.0; k <= 7; k++ { 140 u := int64(106600) 141 n := int(math.Pow(2, k)) 142 targets := 1 + rand.Intn(n) 143 v := make([]int64, targets) 144 for t := 0; t < targets; t++ { 145 v[t] = int64(rand.Intn(len(g.Vertices))) 146 } 147 b.Run(fmt.Sprintf("%s/%d/vertices-%d-edges-%d-shortcuts-%d-targets-%d", "CH shortest path", n, len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum(), targets), func(b *testing.B) { 148 for i := 0; i < b.N; i++ { 149 for vv := range v { 150 ans, path := g.ShortestPath(u, v[vv]) 151 _, _ = ans, path 152 } 153 } 154 }) 155 } 156 } 157 158 func BenchmarkStaticCaseShortestPathOneToMany(b *testing.B) { 159 g := Graph{} 160 err := graphFromCSV(&g, "./data/pgrouting_osm.csv") 161 if err != nil { 162 b.Error(err) 163 } 164 b.Log("Please wait until contraction hierarchy is prepared") 165 g.PrepareContractionHierarchies() 166 b.Log("BenchmarkStaticCaseShortestPathOneToMany is starting...") 167 b.ResetTimer() 168 169 b.Run(fmt.Sprintf("%s/vertices-%d-edges-%d-shortcuts-%d", "CH shortest path (one to many)", len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum()), func(b *testing.B) { 170 for i := 0; i < b.N; i++ { 171 u := int64(106600) 172 v := []int64{5924, 81611, 69618, 68427, 68490} 173 ans, path := g.ShortestPathOneToMany(u, v) 174 _, _ = ans, path 175 } 176 }) 177 } 178 179 func BenchmarkStaticCaseOldWayShortestPathOneToMany(b *testing.B) { 180 g := Graph{} 181 err := graphFromCSV(&g, "data/pgrouting_osm.csv") 182 if err != nil { 183 b.Error(err) 184 } 185 b.Log("Please wait until contraction hierarchy is prepared") 186 g.PrepareContractionHierarchies() 187 b.Log("BenchmarkStaticCaseOldWayShortestPathOneToMany is starting...") 188 b.ResetTimer() 189 190 b.Run(fmt.Sprintf("%s/vertices-%d-edges-%d-shortcuts-%d", "CH shortest path (one to many)", len(g.Vertices), g.GetEdgesNum(), g.GetShortcutsNum()), func(b *testing.B) { 191 for i := 0; i < b.N; i++ { 192 u := int64(106600) 193 v := []int64{5924, 81611, 69618, 68427, 68490} 194 for vv := range v { 195 ans, path := g.ShortestPath(u, v[vv]) 196 _, _ = ans, path 197 } 198 } 199 }) 200 } 201 202 func TestOneToManyAlternatives(t *testing.T) { 203 // S-(1)-0-(1)-1-(1)-2 204 // | | | | 205 // (2) (1) (2) (2) 206 // | | | | 207 // 3-(1)-4-(1)-5-(1)-T 208 209 g := Graph{} 210 g.CreateVertex(0) 211 g.CreateVertex(1) 212 g.CreateVertex(2) 213 g.CreateVertex(3) 214 g.CreateVertex(4) 215 g.CreateVertex(5) 216 g.CreateVertex(6) 217 g.AddEdge(0, 1, 1.0) 218 g.AddEdge(0, 4, 1.0) 219 g.AddEdge(1, 2, 1.0) 220 g.AddEdge(1, 5, 2.0) 221 g.AddEdge(3, 4, 1.0) 222 g.AddEdge(4, 5, 1.0) 223 224 expectedPath := []int64{0, 4, 5} 225 226 g.PrepareContractionHierarchies() 227 t.Log("TestOneToManyAlternatives is starting...") 228 source := []VertexAlternative{ 229 {Label: 0, AdditionalDistance: 1.0}, 230 {Label: 3, AdditionalDistance: 2.0}, 231 } 232 targets := []VertexAlternative{ 233 {Label: 2, AdditionalDistance: 2.0}, 234 {Label: 5, AdditionalDistance: 1.0}, 235 } 236 ans, paths := g.ShortestPathOneToManyWithAlternatives(source, [][]VertexAlternative{targets}) 237 t.Log("TestOneToManyAlternatives returned", ans, paths) 238 path := paths[0] 239 if len(path) != len(expectedPath) { 240 t.Errorf("Num of vertices in path should be %d, but got %d", len(expectedPath), len(path)) 241 } 242 for i := range expectedPath { 243 if path[i] != expectedPath[i] { 244 t.Errorf("Path item %d should be %d, but got %d", i, expectedPath[i], path[i]) 245 } 246 } 247 correctCost := 4.0 248 if math.Abs(ans[0]-correctCost) > eps { 249 t.Errorf("Cost of path should be %f, but got %f", correctCost, ans[0]) 250 return 251 } 252 253 t.Log("TestOneToManyAlternatives is Ok!") 254 }