github.com/LdDl/ch@v1.7.8/bidirectional_ch_n_to_n_test.go (about) 1 package ch 2 3 import ( 4 "fmt" 5 "math" 6 "math/rand" 7 "testing" 8 ) 9 10 func TestManyToManyShortestPath(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, 106600, 69618} 21 v := []int64{5924, 81611, 69618, 68427, 68490} 22 correctAns := [][]float64{ 23 {61089.42195558673, 94961.78959757874, 78692.8292369651, 61212.00481622628, 71101.1080090782}, 24 {61089.42195558673, 94961.78959757874, 78692.8292369651, 61212.00481622628, 71101.1080090782}, 25 {19135.6581215226, -2, -2, -2, -2}, 26 } 27 correctPath := [][]int{ 28 {418, 866, 591, 314, 353}, 29 {418, 866, 591, 314, 353}, 30 {160, -2, -2, -2, -2}, 31 } 32 ans, path := g.ShortestPathManyToMany(u, v) 33 // t.Log("ShortestPathManyToMany returned", ans, path) 34 for sourceIdx := range u { 35 for targetIdx := range v { 36 if correctPath[sourceIdx][targetIdx] != -2 && len(path[sourceIdx][targetIdx]) != correctPath[sourceIdx][targetIdx] { 37 t.Errorf("Num of vertices in path should be %d, but got %d", correctPath[sourceIdx][targetIdx], len(path[sourceIdx][targetIdx])) 38 return 39 } 40 if correctAns[sourceIdx][targetIdx] != -2 && math.Abs(ans[sourceIdx][targetIdx]-correctAns[sourceIdx][targetIdx]) > eps { 41 t.Errorf("Cost of path should be %f, but got %f", correctAns[sourceIdx][targetIdx], ans[sourceIdx][targetIdx]) 42 return 43 } 44 } 45 } 46 47 t.Log("TestShortestPath is Ok!") 48 } 49 50 func BenchmarkShortestPathManyToMany(b *testing.B) { 51 b.Log("BenchmarkShortestPathManyToMany is starting...") 52 rand.Seed(1337) 53 for k := 2.0; k <= 8; k++ { 54 n := int(math.Pow(2, k)) 55 g, err := generateSyntheticGraph(n) 56 if err != nil { 57 b.Error(err) 58 return 59 } 60 b.ResetTimer() 61 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) { 62 for i := 0; i < b.N; i++ { 63 u := []int64{int64(rand.Intn(len(g.Vertices)))} 64 v := []int64{ 65 int64(rand.Intn(len(g.Vertices))), 66 int64(rand.Intn(len(g.Vertices))), 67 int64(rand.Intn(len(g.Vertices))), 68 int64(rand.Intn(len(g.Vertices))), 69 int64(rand.Intn(len(g.Vertices))), 70 } 71 ans, path := g.ShortestPathManyToMany(u, v) 72 _, _ = ans, path 73 } 74 }) 75 } 76 } 77 78 func BenchmarkOldWayShortestPathManyToMany(b *testing.B) { 79 b.Log("BenchmarkOldWayShortestPathManyToMany is starting...") 80 rand.Seed(1337) 81 for k := 2.0; k <= 8; k++ { 82 n := int(math.Pow(2, k)) 83 g, err := generateSyntheticGraph(n) 84 if err != nil { 85 b.Error(err) 86 return 87 } 88 b.ResetTimer() 89 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) { 90 for i := 0; i < b.N; i++ { 91 u := int64(rand.Intn(len(g.Vertices))) 92 v := []int64{ 93 int64(rand.Intn(len(g.Vertices))), 94 int64(rand.Intn(len(g.Vertices))), 95 int64(rand.Intn(len(g.Vertices))), 96 int64(rand.Intn(len(g.Vertices))), 97 int64(rand.Intn(len(g.Vertices))), 98 } 99 for vv := range v { 100 ans, path := g.ShortestPath(u, v[vv]) 101 _, _ = ans, path 102 } 103 } 104 }) 105 } 106 } 107 108 func BenchmarkStaticCaseShortestPathManyToMany(b *testing.B) { 109 g := Graph{} 110 err := graphFromCSV(&g, "./data/pgrouting_osm.csv") 111 if err != nil { 112 b.Error(err) 113 } 114 b.Log("Please wait until contraction hierarchy is prepared") 115 g.PrepareContractionHierarchies() 116 b.Log("BenchmarkStaticCaseShortestPathManyToMany is starting...") 117 b.ResetTimer() 118 119 b.Run(fmt.Sprintf("%s/vertices-%d", "CH shortest path (many to many)", len(g.Vertices)), func(b *testing.B) { 120 for i := 0; i < b.N; i++ { 121 u := []int64{106600} 122 v := []int64{5924, 81611, 69618, 68427, 68490} 123 ans, path := g.ShortestPathManyToMany(u, v) 124 _, _ = ans, path 125 } 126 }) 127 } 128 129 func BenchmarkStaticCaseOldWayShortestPathManyToMany(b *testing.B) { 130 g := Graph{} 131 err := graphFromCSV(&g, "data/pgrouting_osm.csv") 132 if err != nil { 133 b.Error(err) 134 } 135 b.Log("Please wait until contraction hierarchy is prepared") 136 g.PrepareContractionHierarchies() 137 b.Log("BenchmarkStaticCaseOldWayShortestPathManyToMany is starting...") 138 b.ResetTimer() 139 140 b.Run(fmt.Sprintf("%s/vertices-%d", "CH shortest path (many to many)", len(g.Vertices)), func(b *testing.B) { 141 for i := 0; i < b.N; i++ { 142 u := int64(106600) 143 v := []int64{5924, 81611, 69618, 68427, 68490} 144 for vv := range v { 145 ans, path := g.ShortestPath(u, v[vv]) 146 _, _ = ans, path 147 } 148 } 149 }) 150 } 151 152 func TestManyToManyAlternatives(t *testing.T) { 153 // S-(1)-0-(1)-1-(1)-2 154 // | | | | 155 // (2) (1) (2) (2) 156 // | | | | 157 // 3-(1)-4-(1)-5-(1)-T 158 159 g := Graph{} 160 g.CreateVertex(0) 161 g.CreateVertex(1) 162 g.CreateVertex(2) 163 g.CreateVertex(3) 164 g.CreateVertex(4) 165 g.CreateVertex(5) 166 g.CreateVertex(6) 167 g.AddEdge(0, 1, 1.0) 168 g.AddEdge(0, 4, 1.0) 169 g.AddEdge(1, 2, 1.0) 170 g.AddEdge(1, 5, 2.0) 171 g.AddEdge(3, 4, 1.0) 172 g.AddEdge(4, 5, 1.0) 173 174 expectedPath := []int64{0, 4, 5} 175 176 g.PrepareContractionHierarchies() 177 t.Log("TestManyToManyAlternatives is starting...") 178 sources := []VertexAlternative{ 179 {Label: 0, AdditionalDistance: 1.0}, 180 {Label: 3, AdditionalDistance: 2.0}, 181 } 182 targets := []VertexAlternative{ 183 {Label: 2, AdditionalDistance: 2.0}, 184 {Label: 5, AdditionalDistance: 1.0}, 185 } 186 ans, paths := g.ShortestPathManyToManyWithAlternatives([][]VertexAlternative{sources}, [][]VertexAlternative{targets}) 187 t.Log("ShortestPathManyToManyWithAlternatives returned", ans, paths) 188 path := paths[0][0] 189 if len(path) != len(expectedPath) { 190 t.Errorf("Num of vertices in path should be %d, but got %d", len(expectedPath), len(path)) 191 } 192 for i := range expectedPath { 193 if path[i] != expectedPath[i] { 194 t.Errorf("Path item %d should be %d, but got %d", i, expectedPath[i], path[i]) 195 } 196 } 197 correctCost := 4.0 198 if math.Abs(ans[0][0]-correctCost) > eps { 199 t.Errorf("Cost of path should be %f, but got %f", correctCost, ans[0][0]) 200 return 201 } 202 t.Log("TestManyToManyAlternatives is Ok!") 203 }