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  }