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  }