bfs_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // CookieJar - A contestant's algorithm toolbox
  2. // Copyright 2013 Peter Szilagyi. All rights reserved.
  3. //
  4. // CookieJar is dual licensed: use of this source code is governed by a BSD
  5. // license that can be found in the LICENSE file. Alternatively, the CookieJar
  6. // toolbox may be used in accordance with the terms and conditions contained
  7. // in a signed written agreement between you and the author(s).
  8. package bfs
  9. import (
  10. "testing"
  11. "gopkg.in/karalabe/cookiejar.v2/graph"
  12. )
  13. type graphTest struct {
  14. nodes int
  15. edges [][]int
  16. }
  17. var graphTests = []graphTest{
  18. // Random Erdos-Renyi graph with 64 nodes and 0.25 conenction probability.
  19. {
  20. 64,
  21. [][]int{
  22. {48, 34, 9, 57, 11, 61, 16, 17, 18, 51, 21, 23, 25, 60, 29, 63},
  23. {32, 34, 5, 7, 8, 42, 15, 48, 17, 50, 19, 52, 57, 26, 63},
  24. {4, 8, 42, 51, 20, 22, 57, 36, 29},
  25. {34, 35, 4, 38, 7, 14, 17, 57, 54, 23, 36, 26},
  26. {32, 48, 47, 16, 51, 20, 21, 23, 24, 26, 31},
  27. {6, 9, 11, 44, 46, 19, 22, 23, 60},
  28. {8, 10, 11, 12, 14, 15, 16, 17, 23, 25, 30, 33, 34, 37, 39, 45, 46, 48, 54, 55, 59},
  29. {37, 35, 49, 8, 60, 45, 14, 17, 19, 20, 46, 56, 25, 26, 28, 29, 30, 53},
  30. {33, 43, 12, 48, 17, 20, 53, 22, 60},
  31. {32, 36, 40, 43, 12, 47, 49, 18, 20, 21, 22, 23, 24, 52, 58, 59, 30},
  32. {42, 46, 14, 50, 19, 20, 21, 23, 52, 58, 27, 60, 53},
  33. {48, 59, 39, 46, 15, 16, 19, 58, 38, 51},
  34. {33, 38, 42, 43, 15, 16, 40, 51, 22, 41, 24, 58, 27, 60, 29},
  35. {33, 37, 38, 49, 40, 42, 43, 50, 15, 16, 17, 18, 29},
  36. {36, 38, 40, 46, 17, 50, 20, 23, 63},
  37. {35, 40, 46, 51, 21, 22, 55, 24, 58, 60, 61, 53},
  38. {34, 38, 39, 40, 46, 51, 57, 27, 61, 30},
  39. {34, 54, 55, 22, 23, 57, 31},
  40. {32, 36, 51, 40, 42, 19, 20, 41, 52, 27, 62, 63},
  41. {50, 46, 20, 53, 30},
  42. {59, 44, 47, 21, 54, 56, 58, 27, 42},
  43. {33, 45, 48, 56, 53, 54, 24, 26, 47},
  44. {24, 25, 30, 37, 40, 41, 48, 49, 50, 52, 54, 55, 60, 62, 63},
  45. {32, 33, 43, 44, 45, 48, 24, 25, 61},
  46. {37, 38, 39, 40, 61, 48, 50, 51, 25, 26, 60, 58, 62, 63},
  47. {38, 41, 42, 39, 49, 50, 56, 58, 60, 29, 31},
  48. {33, 43, 45, 46, 47, 51, 54, 55, 58, 31},
  49. {33, 38, 39, 46, 49, 51, 62, 59, 28, 61, 30},
  50. {35, 38, 39, 59, 43, 50, 53, 54, 58, 30},
  51. {38, 40, 41, 42, 39, 46, 47, 51, 61},
  52. {59, 36, 54, 42, 43, 60, 49, 50, 52, 53, 62, 63},
  53. {34, 40, 44, 46, 48, 53, 61},
  54. {50, 33, 44, 45, 53, 54, 58, 63},
  55. {35, 37, 43, 46, 40, 56, 55, 60, 53},
  56. {49, 41, 50, 60, 62},
  57. {37, 42, 43, 48, 61},
  58. {48, 53, 55, 56, 57, 63},
  59. {40, 41, 39, 44, 56, 50, 52, 57, 58, 60, 62},
  60. {44, 53, 54, 57, 58, 62},
  61. {43, 44, 61, 47, 49, 58, 62},
  62. {50, 62},
  63. {52, 53, 59},
  64. {46, 50, 49, 51, 53, 57, 58, 52},
  65. {45, 44, 56, 47},
  66. {45, 47, 53, 54, 62},
  67. {59, 60, 61, 62, 53},
  68. {47, 49, 53, 56},
  69. {57, 49, 55, 52, 62},
  70. {56, 52, 63, 53, 55},
  71. {59, 53, 58, 60},
  72. {61, 53, 58},
  73. {59, 58, 53, 60},
  74. {53, 58, 60},
  75. {55, 56},
  76. {60, 63},
  77. {60, 62, 63},
  78. {63, 57, 59},
  79. {58, 63},
  80. {59, 60, 63},
  81. {61, 63},
  82. {63},
  83. {63},
  84. {},
  85. {},
  86. },
  87. },
  88. // Random Erdos-Renyi graph with 64 nodes and 0.1 conenction probability.
  89. {
  90. 64,
  91. [][]int{
  92. {38, 40, 12, 61, 47, 17, 57, 28, 29},
  93. {5, 15, 22, 24, 26, 47, 28, 63},
  94. {33, 4, 40, 13, 15, 17, 25, 27, 62},
  95. {17, 4, 6, 49},
  96. {5, 20, 23, 27, 37},
  97. {32, 18, 20, 56, 57},
  98. {9, 55},
  99. {34, 63, 13, 21},
  100. {37, 60, 14, 47, 17, 52, 53, 28},
  101. {56, 45},
  102. {43, 58, 19, 63},
  103. {36, 42, 13, 14, 16, 46, 22, 56},
  104. {40, 30, 23},
  105. {40, 41, 45, 46, 56},
  106. {47, 50, 51, 22, 26},
  107. {37, 44, 45, 25, 26},
  108. {32, 49, 51, 22, 56},
  109. {36, 45, 47, 52, 56},
  110. {39, 43, 58, 60, 62},
  111. {57},
  112. {47, 56, 24, 61},
  113. {32, 49, 55},
  114. {34, 33, 47, 55, 39, 62, 63},
  115. {40, 44, 25, 60, 63},
  116. {38, 39, 46, 54, 57, 30},
  117. {35, 41, 45, 34, 52},
  118. {38, 39, 45, 27},
  119. {42},
  120. {33, 39, 40, 47, 51, 55, 60},
  121. {50, 63, 39},
  122. {36, 43, 57},
  123. {34, 35, 40, 42, 52, 53, 57},
  124. {34, 36, 50, 56},
  125. {36, 39, 44, 55},
  126. {38, 51},
  127. {47},
  128. {51, 55},
  129. {61},
  130. {48},
  131. {41, 44, 52},
  132. {60, 50},
  133. {48, 49, 50, 59},
  134. {46},
  135. {45, 47, 53, 61, 63},
  136. {55, 58, 61},
  137. {49, 48, 57},
  138. {58},
  139. {49, 55},
  140. {50, 51},
  141. {},
  142. {},
  143. {52, 53, 58},
  144. {57},
  145. {63, 59, 61},
  146. {56, 59},
  147. {61, 62},
  148. {},
  149. {},
  150. {62},
  151. {60, 63},
  152. {},
  153. {},
  154. {},
  155. {},
  156. },
  157. },
  158. }
  159. func TestBFS(t *testing.T) {
  160. for i, tt := range graphTests {
  161. // Assemble the graph
  162. g := graph.New(tt.nodes)
  163. for v, peers := range tt.edges {
  164. for _, peer := range peers {
  165. g.Connect(v, peer)
  166. }
  167. }
  168. // Create a bfs structure and verify it
  169. for src := 0; src < tt.nodes; src++ {
  170. b := New(g, src)
  171. // Ensure that paths are indeed connected links
  172. for dst := 0; dst < tt.nodes; dst++ {
  173. if b.Reachable(dst) {
  174. // If reachable, generate the path and verify each link
  175. if path := b.Path(dst); path == nil {
  176. t.Errorf("test %d: reachable nil path %v->%v.", i, src, dst)
  177. } else {
  178. for p := 1; p < len(path); p++ {
  179. a := path[p-1]
  180. b := path[p]
  181. if a > b {
  182. a, b = b, a
  183. }
  184. found := false
  185. for _, v := range tt.edges[a] {
  186. if v == b {
  187. found = true
  188. break
  189. }
  190. }
  191. if !found {
  192. t.Errorf("test %d: path link %v-%v not found.", i, a, b)
  193. }
  194. }
  195. }
  196. } else {
  197. // If not reachable, make sure path is also nil
  198. if path := b.Path(dst); path != nil {
  199. t.Errorf("test %d: non reachable path %v->%v: have %v, want %v.", i, src, dst, path, nil)
  200. }
  201. }
  202. }
  203. // Ensure that the order is consistent with the paths returned
  204. ord := b.Order()
  205. for dst := 0; dst < tt.nodes; dst++ {
  206. if b.Reachable(dst) {
  207. path := b.Path(dst)
  208. for oi, pi := 0, 0; pi < len(path); pi++ {
  209. for ord[oi] != path[pi] {
  210. if oi >= len(ord) {
  211. t.Errorf("test %d: order/path mismatch: o=%v, p=%v.", i, ord, path)
  212. }
  213. oi++
  214. }
  215. }
  216. }
  217. }
  218. }
  219. }
  220. }
  221. func TestBreadth(t *testing.T) {
  222. // Create a simple graph and check breadth visit order
  223. g := graph.New(6)
  224. g.Connect(0, 1)
  225. g.Connect(1, 2)
  226. g.Connect(1, 4)
  227. g.Connect(2, 3)
  228. g.Connect(4, 5)
  229. g.Connect(3, 5)
  230. // Check the bfs paths
  231. b := New(g, 0)
  232. if p := b.Path(5); len(p) != 4 || p[0] != 0 || p[1] != 1 || p[2] != 4 || p[3] != 5 {
  233. t.Errorf("path mismatch: have %v, want%v.", p, []int{0, 1, 4, 5})
  234. }
  235. }