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  }