blob: 875c96e9747fa0d827e842e5b0541f4ee7567daa [file] [log] [blame]
// Copyright ©2015 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package topo
import (
"math"
"reflect"
"sort"
"testing"
"gonum.org/v1/gonum/graph/internal/ordered"
"gonum.org/v1/gonum/graph/simple"
)
var vOrderTests = []struct {
g []intset
wantCore [][]int64
wantK int
}{
{
g: []intset{
0: linksTo(1, 2, 4, 6),
1: linksTo(2, 4, 6),
2: linksTo(3, 6),
3: linksTo(4, 5),
4: linksTo(6),
5: nil,
6: nil,
},
wantCore: [][]int64{
{},
{5},
{3},
{0, 1, 2, 4, 6},
},
wantK: 3,
},
{
g: batageljZaversnikGraph,
wantCore: [][]int64{
{0},
{5, 9, 10, 16},
{1, 2, 3, 4, 11, 12, 13, 15},
{6, 7, 8, 14, 17, 18, 19, 20},
},
wantK: 3,
},
}
func TestVertexOrdering(t *testing.T) {
for i, test := range vOrderTests {
g := simple.NewUndirectedGraph(0, math.Inf(1))
for u, e := range test.g {
// Add nodes that are not defined by an edge.
if !g.Has(simple.Node(u)) {
g.AddNode(simple.Node(u))
}
for v := range e {
g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
}
}
order, core := VertexOrdering(g)
if len(core)-1 != test.wantK {
t.Errorf("unexpected value of k for test %d: got: %d want: %d", i, len(core)-1, test.wantK)
}
var offset int
for k, want := range test.wantCore {
sort.Sort(ordered.Int64s(want))
got := make([]int64, len(want))
for j, n := range order[len(order)-len(want)-offset : len(order)-offset] {
got[j] = n.ID()
}
sort.Sort(ordered.Int64s(got))
if !reflect.DeepEqual(got, want) {
t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, test.wantCore)
}
for j, n := range core[k] {
got[j] = n.ID()
}
sort.Sort(ordered.Int64s(got))
if !reflect.DeepEqual(got, want) {
t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", k, i, got, test.wantCore)
}
offset += len(want)
}
}
}
var bronKerboschTests = []struct {
g []intset
want [][]int64
}{
{
// This is the example given in the Bron-Kerbosch article on wikipedia (renumbered).
// http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858
g: []intset{
0: linksTo(1, 4),
1: linksTo(2, 4),
2: linksTo(3),
3: linksTo(4, 5),
4: nil,
5: nil,
},
want: [][]int64{
{0, 1, 4},
{1, 2},
{2, 3},
{3, 4},
{3, 5},
},
},
{
g: batageljZaversnikGraph,
want: [][]int64{
{0},
{1, 2},
{1, 3},
{2, 4},
{3, 4},
{4, 5},
{6, 7, 8, 14},
{7, 11, 12},
{9, 11},
{10, 11},
{12, 18},
{13, 14, 15},
{14, 15, 17},
{15, 16},
{17, 18, 19, 20},
},
},
}
func TestBronKerbosch(t *testing.T) {
for i, test := range bronKerboschTests {
g := simple.NewUndirectedGraph(0, math.Inf(1))
for u, e := range test.g {
// Add nodes that are not defined by an edge.
if !g.Has(simple.Node(u)) {
g.AddNode(simple.Node(u))
}
for v := range e {
g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
}
}
cliques := BronKerbosch(g)
got := make([][]int64, len(cliques))
for j, c := range cliques {
ids := make([]int64, len(c))
for k, n := range c {
ids[k] = n.ID()
}
sort.Sort(ordered.Int64s(ids))
got[j] = ids
}
sort.Sort(ordered.BySliceValues(got))
if !reflect.DeepEqual(got, test.want) {
t.Errorf("unexpected cliques for test %d:\ngot: %v\nwant:%v", i, got, test.want)
}
}
}