github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/topo/bron_kerbosch_test.go (about) 1 // Copyright ©2015 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package topo 6 7 import ( 8 "reflect" 9 "sort" 10 "testing" 11 12 "github.com/jingcheng-WU/gonum/graph" 13 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 14 "github.com/jingcheng-WU/gonum/graph/simple" 15 ) 16 17 var vOrderTests = []struct { 18 g []intset 19 wantCore [][]int64 20 wantK int 21 }{ 22 { 23 g: []intset{ 24 0: linksTo(1, 2, 4, 6), 25 1: linksTo(2, 4, 6), 26 2: linksTo(3, 6), 27 3: linksTo(4, 5), 28 4: linksTo(6), 29 5: nil, 30 6: nil, 31 }, 32 wantCore: [][]int64{ 33 {}, 34 {5}, 35 {3}, 36 {0, 1, 2, 4, 6}, 37 }, 38 wantK: 3, 39 }, 40 { 41 g: batageljZaversnikGraph, 42 wantCore: [][]int64{ 43 {0}, 44 {5, 9, 10, 16}, 45 {1, 2, 3, 4, 11, 12, 13, 15}, 46 {6, 7, 8, 14, 17, 18, 19, 20}, 47 }, 48 wantK: 3, 49 }, 50 } 51 52 func TestDegeneracyOrdering(t *testing.T) { 53 for i, test := range vOrderTests { 54 g := simple.NewUndirectedGraph() 55 for u, e := range test.g { 56 // Add nodes that are not defined by an edge. 57 if g.Node(int64(u)) == nil { 58 g.AddNode(simple.Node(u)) 59 } 60 for v := range e { 61 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 62 } 63 } 64 order, core := DegeneracyOrdering(g) 65 if len(core)-1 != test.wantK { 66 t.Errorf("unexpected value of k for test %d: got: %d want: %d", i, len(core)-1, test.wantK) 67 } 68 var offset int 69 for k, want := range test.wantCore { 70 sort.Sort(ordered.Int64s(want)) 71 got := make([]int64, len(want)) 72 for j, n := range order[len(order)-len(want)-offset : len(order)-offset] { 73 got[j] = n.ID() 74 } 75 sort.Sort(ordered.Int64s(got)) 76 if !reflect.DeepEqual(got, want) { 77 t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, want) 78 } 79 80 for j, n := range core[k] { 81 got[j] = n.ID() 82 } 83 sort.Sort(ordered.Int64s(got)) 84 if !reflect.DeepEqual(got, want) { 85 t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, want) 86 } 87 offset += len(want) 88 } 89 } 90 } 91 92 func TestKCore(t *testing.T) { 93 for i, test := range vOrderTests { 94 g := simple.NewUndirectedGraph() 95 for u, e := range test.g { 96 // Add nodes that are not defined by an edge. 97 if g.Node(int64(u)) == nil { 98 g.AddNode(simple.Node(u)) 99 } 100 for v := range e { 101 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 102 } 103 } 104 105 for k := 0; k <= test.wantK+1; k++ { 106 var want []int64 107 for _, c := range test.wantCore[k:] { 108 want = append(want, c...) 109 } 110 core := KCore(k, g) 111 if len(core) != len(want) { 112 t.Errorf("unexpected %d-core length for test %d:\ngot: %v\nwant:%v", k, i, len(core), len(want)) 113 continue 114 } 115 116 var got []int64 117 for _, n := range core { 118 got = append(got, n.ID()) 119 } 120 sort.Sort(ordered.Int64s(got)) 121 sort.Sort(ordered.Int64s(want)) 122 if !reflect.DeepEqual(got, want) { 123 t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, want) 124 } 125 } 126 } 127 } 128 129 var bronKerboschTests = []struct { 130 name string 131 g []intset 132 want [][]int64 133 }{ 134 { 135 // This is the example given in the Bron-Kerbosch article on wikipedia (renumbered). 136 // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 137 name: "wikipedia example", 138 g: []intset{ 139 0: linksTo(1, 4), 140 1: linksTo(2, 4), 141 2: linksTo(3), 142 3: linksTo(4, 5), 143 4: nil, 144 5: nil, 145 }, 146 want: [][]int64{ 147 {0, 1, 4}, 148 {1, 2}, 149 {2, 3}, 150 {3, 4}, 151 {3, 5}, 152 }, 153 }, 154 { 155 name: "Batagelj-Zaversnik Graph", 156 g: batageljZaversnikGraph, 157 want: [][]int64{ 158 {0}, 159 {1, 2}, 160 {1, 3}, 161 {2, 4}, 162 {3, 4}, 163 {4, 5}, 164 {6, 7, 8, 14}, 165 {7, 11, 12}, 166 {9, 11}, 167 {10, 11}, 168 {12, 18}, 169 {13, 14, 15}, 170 {14, 15, 17}, 171 {15, 16}, 172 {17, 18, 19, 20}, 173 }, 174 }, 175 } 176 177 func TestBronKerbosch(t *testing.T) { 178 for _, test := range bronKerboschTests { 179 g := simple.NewUndirectedGraph() 180 for u, e := range test.g { 181 // Add nodes that are not defined by an edge. 182 if g.Node(int64(u)) == nil { 183 g.AddNode(simple.Node(u)) 184 } 185 for v := range e { 186 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 187 } 188 } 189 cliques := BronKerbosch(g) 190 got := make([][]int64, len(cliques)) 191 for j, c := range cliques { 192 ids := make([]int64, len(c)) 193 for k, n := range c { 194 ids[k] = n.ID() 195 } 196 sort.Sort(ordered.Int64s(ids)) 197 got[j] = ids 198 } 199 sort.Sort(ordered.BySliceValues(got)) 200 if !reflect.DeepEqual(got, test.want) { 201 t.Errorf("unexpected cliques for test %q:\ngot: %v\nwant:%v", test.name, got, test.want) 202 } 203 } 204 } 205 206 func BenchmarkBronKerbosch(b *testing.B) { 207 for _, test := range bronKerboschTests { 208 g := simple.NewUndirectedGraph() 209 for u, e := range test.g { 210 // Add nodes that are not defined by an edge. 211 if g.Node(int64(u)) == nil { 212 g.AddNode(simple.Node(u)) 213 } 214 for v := range e { 215 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 216 } 217 } 218 219 b.Run(test.name, func(b *testing.B) { 220 var got [][]graph.Node 221 for i := 0; i < b.N; i++ { 222 got = BronKerbosch(g) 223 } 224 if len(got) != len(test.want) { 225 b.Errorf("unexpected cliques for test %q:\ngot: %v\nwant:%v", test.name, got, test.want) 226 } 227 }) 228 } 229 }