github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/topo/topo_test.go (about)

     1  // Copyright ©2014 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  func TestIsPath(t *testing.T) {
    18  	dg := simple.NewDirectedGraph()
    19  	if !IsPathIn(dg, nil) {
    20  		t.Error("IsPath returns false on nil path")
    21  	}
    22  	p := []graph.Node{simple.Node(0)}
    23  	if IsPathIn(dg, p) {
    24  		t.Error("IsPath returns true on nonexistant node")
    25  	}
    26  	dg.AddNode(p[0])
    27  	if !IsPathIn(dg, p) {
    28  		t.Error("IsPath returns false on single-length path with existing node")
    29  	}
    30  	p = append(p, simple.Node(1))
    31  	dg.AddNode(p[1])
    32  	if IsPathIn(dg, p) {
    33  		t.Error("IsPath returns true on bad path of length 2")
    34  	}
    35  	dg.SetEdge(simple.Edge{F: p[0], T: p[1]})
    36  	if !IsPathIn(dg, p) {
    37  		t.Error("IsPath returns false on correct path of length 2")
    38  	}
    39  	p[0], p[1] = p[1], p[0]
    40  	if IsPathIn(dg, p) {
    41  		t.Error("IsPath erroneously returns true for a reverse path")
    42  	}
    43  	p = []graph.Node{p[1], p[0], simple.Node(2)}
    44  	dg.SetEdge(simple.Edge{F: p[1], T: p[2]})
    45  	if !IsPathIn(dg, p) {
    46  		t.Error("IsPath does not find a correct path for path > 2 nodes")
    47  	}
    48  	ug := simple.NewUndirectedGraph()
    49  	ug.SetEdge(simple.Edge{F: p[1], T: p[0]})
    50  	ug.SetEdge(simple.Edge{F: p[1], T: p[2]})
    51  	if !IsPathIn(dg, p) {
    52  		t.Error("IsPath does not correctly account for undirected behavior")
    53  	}
    54  }
    55  
    56  var pathExistsInUndirectedTests = []struct {
    57  	g        []intset
    58  	from, to int
    59  	want     bool
    60  }{
    61  	{g: batageljZaversnikGraph, from: 0, to: 0, want: true},
    62  	{g: batageljZaversnikGraph, from: 0, to: 1, want: false},
    63  	{g: batageljZaversnikGraph, from: 1, to: 2, want: true},
    64  	{g: batageljZaversnikGraph, from: 2, to: 1, want: true},
    65  	{g: batageljZaversnikGraph, from: 2, to: 12, want: false},
    66  	{g: batageljZaversnikGraph, from: 20, to: 6, want: true},
    67  }
    68  
    69  func TestPathExistsInUndirected(t *testing.T) {
    70  	for i, test := range pathExistsInUndirectedTests {
    71  		g := simple.NewUndirectedGraph()
    72  
    73  		for u, e := range test.g {
    74  			if g.Node(int64(u)) == nil {
    75  				g.AddNode(simple.Node(u))
    76  			}
    77  			for v := range e {
    78  				if g.Node(int64(v)) == nil {
    79  					g.AddNode(simple.Node(v))
    80  				}
    81  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
    82  			}
    83  		}
    84  
    85  		got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to))
    86  		if got != test.want {
    87  			t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want)
    88  		}
    89  	}
    90  }
    91  
    92  var pathExistsInDirectedTests = []struct {
    93  	g        []intset
    94  	from, to int
    95  	want     bool
    96  }{
    97  	// The graph definition is such that from node IDs are
    98  	// less than to node IDs.
    99  	{g: batageljZaversnikGraph, from: 0, to: 0, want: true},
   100  	{g: batageljZaversnikGraph, from: 0, to: 1, want: false},
   101  	{g: batageljZaversnikGraph, from: 1, to: 2, want: true},
   102  	{g: batageljZaversnikGraph, from: 2, to: 1, want: false},
   103  	{g: batageljZaversnikGraph, from: 2, to: 12, want: false},
   104  	{g: batageljZaversnikGraph, from: 20, to: 6, want: false},
   105  	{g: batageljZaversnikGraph, from: 6, to: 20, want: true},
   106  }
   107  
   108  func TestPathExistsInDirected(t *testing.T) {
   109  	for i, test := range pathExistsInDirectedTests {
   110  		g := simple.NewDirectedGraph()
   111  
   112  		for u, e := range test.g {
   113  			if g.Node(int64(u)) == nil {
   114  				g.AddNode(simple.Node(u))
   115  			}
   116  			for v := range e {
   117  				if g.Node(int64(v)) == nil {
   118  					g.AddNode(simple.Node(v))
   119  				}
   120  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
   121  			}
   122  		}
   123  
   124  		got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to))
   125  		if got != test.want {
   126  			t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want)
   127  		}
   128  	}
   129  }
   130  
   131  var connectedComponentTests = []struct {
   132  	g    []intset
   133  	want [][]int64
   134  }{
   135  	{
   136  		g: batageljZaversnikGraph,
   137  		want: [][]int64{
   138  			{0},
   139  			{1, 2, 3, 4, 5},
   140  			{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
   141  		},
   142  	},
   143  }
   144  
   145  func TestConnectedComponents(t *testing.T) {
   146  	for i, test := range connectedComponentTests {
   147  		g := simple.NewUndirectedGraph()
   148  
   149  		for u, e := range test.g {
   150  			if g.Node(int64(u)) == nil {
   151  				g.AddNode(simple.Node(u))
   152  			}
   153  			for v := range e {
   154  				if g.Node(int64(v)) == nil {
   155  					g.AddNode(simple.Node(v))
   156  				}
   157  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
   158  			}
   159  		}
   160  		cc := ConnectedComponents(g)
   161  		got := make([][]int64, len(cc))
   162  		for j, c := range cc {
   163  			ids := make([]int64, len(c))
   164  			for k, n := range c {
   165  				ids[k] = n.ID()
   166  			}
   167  			sort.Sort(ordered.Int64s(ids))
   168  			got[j] = ids
   169  		}
   170  		sort.Sort(ordered.BySliceValues(got))
   171  		if !reflect.DeepEqual(got, test.want) {
   172  			t.Errorf("unexpected connected components for test %d %T:\ngot: %v\nwant:%v", i, g, got, test.want)
   173  		}
   174  	}
   175  }
   176  
   177  var equalTests = []struct {
   178  	name string
   179  	a, b graph.Graph
   180  	want bool
   181  }{
   182  	{name: "empty g=g", a: simple.NewUndirectedGraph(), b: simple.NewUndirectedGraph(), want: true},
   183  	{name: "empty dg=dg", a: simple.NewDirectedGraph(), b: simple.NewDirectedGraph(), want: true},
   184  	{name: "empty g=dg", a: simple.NewUndirectedGraph(), b: simple.NewDirectedGraph(), want: true},
   185  
   186  	{
   187  		name: "1 g=g", want: true,
   188  		a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   189  		b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   190  	},
   191  	{
   192  		name: "1 dg=dg", want: true,
   193  		a: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   194  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   195  	},
   196  	{
   197  		name: "1 g=dg", want: true,
   198  		a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   199  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   200  	},
   201  
   202  	{
   203  		name: "0/1 g≠g", want: false,
   204  		a: simple.NewUndirectedGraph(),
   205  		b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   206  	},
   207  	{
   208  		name: "0/1 dg≠dg", want: false,
   209  		a: simple.NewDirectedGraph(),
   210  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   211  	},
   212  	{
   213  		name: "0/1 g≠dg", want: false,
   214  		a: simple.NewUndirectedGraph(),
   215  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   216  	},
   217  	{
   218  		name: "0/1 g≠dg", want: false,
   219  		a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   220  		b: simple.NewDirectedGraph(),
   221  	},
   222  
   223  	{
   224  		name: "1 g≠g", want: false,
   225  		a: addNodes(simple.NewUndirectedGraph(), simple.Node(0)),
   226  		b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)),
   227  	},
   228  	{
   229  		name: "1 dg≠dg", want: false,
   230  		a: addNodes(simple.NewDirectedGraph(), simple.Node(0)),
   231  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   232  	},
   233  	{
   234  		name: "1 g≠dg", want: false,
   235  		a: addNodes(simple.NewUndirectedGraph(), simple.Node(0)),
   236  		b: addNodes(simple.NewDirectedGraph(), simple.Node(1)),
   237  	},
   238  
   239  	{
   240  		name: "box g=g", want: true,
   241  		a: setEdges(simple.NewUndirectedGraph(),
   242  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   243  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   244  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   245  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   246  		),
   247  		b: setEdges(simple.NewUndirectedGraph(),
   248  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   249  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   250  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   251  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   252  		),
   253  	},
   254  	{
   255  		name: "box dg=dg", want: true,
   256  		a: setEdges(simple.NewDirectedGraph(),
   257  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   258  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   259  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   260  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   261  		),
   262  		b: setEdges(simple.NewDirectedGraph(),
   263  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   264  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   265  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   266  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   267  		),
   268  	},
   269  	{
   270  		name: "box reversed dg≠dg", want: false,
   271  		a: setEdges(simple.NewDirectedGraph(),
   272  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   273  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   274  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   275  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   276  		),
   277  		b: setEdges(simple.NewDirectedGraph(),
   278  			simple.Edge{F: simple.Node(1), T: simple.Node(0)},
   279  			simple.Edge{F: simple.Node(2), T: simple.Node(1)},
   280  			simple.Edge{F: simple.Node(3), T: simple.Node(2)},
   281  			simple.Edge{F: simple.Node(0), T: simple.Node(3)},
   282  		),
   283  	},
   284  	{
   285  		name: "box g=dg", want: true,
   286  		a: setEdges(simple.NewUndirectedGraph(),
   287  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   288  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   289  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   290  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   291  		),
   292  		b: setEdges(simple.NewDirectedGraph(),
   293  			simple.Edge{F: simple.Node(0), T: simple.Node(1)},
   294  			simple.Edge{F: simple.Node(1), T: simple.Node(0)},
   295  			simple.Edge{F: simple.Node(1), T: simple.Node(2)},
   296  			simple.Edge{F: simple.Node(2), T: simple.Node(3)},
   297  			simple.Edge{F: simple.Node(2), T: simple.Node(1)},
   298  			simple.Edge{F: simple.Node(3), T: simple.Node(2)},
   299  			simple.Edge{F: simple.Node(3), T: simple.Node(0)},
   300  			simple.Edge{F: simple.Node(0), T: simple.Node(3)},
   301  		),
   302  	},
   303  }
   304  
   305  func TestEqual(t *testing.T) {
   306  	for _, test := range equalTests {
   307  		if got := Equal(test.a, test.b); got != test.want {
   308  			t.Errorf("unexpected result for %q equality test: got:%t want:%t", test.name, got, test.want)
   309  		}
   310  		if got := Equal(plainGraph{test.a}, plainGraph{test.b}); got != test.want {
   311  			t.Errorf("unexpected result for %q equality test with filtered method set: got:%t want:%t", test.name, got, test.want)
   312  		}
   313  	}
   314  }
   315  
   316  type plainGraph struct {
   317  	graph.Graph
   318  }
   319  
   320  type builder interface {
   321  	graph.Graph
   322  	graph.Builder
   323  }
   324  
   325  func addNodes(dst builder, nodes ...graph.Node) builder {
   326  	for _, n := range nodes {
   327  		dst.AddNode(n)
   328  	}
   329  	return dst
   330  }
   331  
   332  func setEdges(dst builder, edges ...graph.Edge) builder {
   333  	for _, e := range edges {
   334  		dst.SetEdge(e)
   335  	}
   336  	return dst
   337  }