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

     1  // Copyright ©2017 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 graph_test
     6  
     7  import (
     8  	"sort"
     9  	"testing"
    10  
    11  	"github.com/jingcheng-WU/gonum/graph"
    12  	"github.com/jingcheng-WU/gonum/graph/internal/ordered"
    13  	"github.com/jingcheng-WU/gonum/graph/simple"
    14  )
    15  
    16  type graphBuilder interface {
    17  	graph.Graph
    18  	graph.Builder
    19  }
    20  
    21  var copyTests = []struct {
    22  	desc string
    23  
    24  	src graph.Graph
    25  	dst graphBuilder
    26  
    27  	// If want is nil, compare to src.
    28  	want graph.Graph
    29  }{
    30  	{
    31  		desc: "undirected to undirected",
    32  		src: func() graph.Graph {
    33  			g := simple.NewUndirectedGraph()
    34  			g.AddNode(simple.Node(-1))
    35  			for _, e := range []simple.Edge{
    36  				{F: simple.Node(0), T: simple.Node(1)},
    37  				{F: simple.Node(0), T: simple.Node(3)},
    38  				{F: simple.Node(1), T: simple.Node(2)},
    39  			} {
    40  				g.SetEdge(e)
    41  			}
    42  			return g
    43  		}(),
    44  		dst: simple.NewUndirectedGraph(),
    45  	},
    46  	{
    47  		desc: "undirected to directed",
    48  		src: func() graph.Graph {
    49  			g := simple.NewUndirectedGraph()
    50  			g.AddNode(simple.Node(-1))
    51  			for _, e := range []simple.Edge{
    52  				{F: simple.Node(0), T: simple.Node(1)},
    53  				{F: simple.Node(0), T: simple.Node(3)},
    54  				{F: simple.Node(1), T: simple.Node(2)},
    55  			} {
    56  				g.SetEdge(e)
    57  			}
    58  			return g
    59  		}(),
    60  		dst: simple.NewDirectedGraph(),
    61  
    62  		want: func() graph.Graph {
    63  			g := simple.NewDirectedGraph()
    64  			g.AddNode(simple.Node(-1))
    65  			for _, e := range []simple.Edge{
    66  				{F: simple.Node(0), T: simple.Node(1)},
    67  				{F: simple.Node(0), T: simple.Node(3)},
    68  				{F: simple.Node(1), T: simple.Node(2)},
    69  			} {
    70  				// want is a directed graph copied from
    71  				// an undirected graph so we need to have
    72  				// all edges in both directions.
    73  				g.SetEdge(e)
    74  				e.T, e.F = e.F, e.T
    75  				g.SetEdge(e)
    76  			}
    77  			return g
    78  		}(),
    79  	},
    80  	{
    81  		desc: "directed to undirected",
    82  		src: func() graph.Graph {
    83  			g := simple.NewDirectedGraph()
    84  			g.AddNode(simple.Node(-1))
    85  			for _, e := range []simple.Edge{
    86  				{F: simple.Node(0), T: simple.Node(1)},
    87  				{F: simple.Node(0), T: simple.Node(3)},
    88  				{F: simple.Node(1), T: simple.Node(2)},
    89  			} {
    90  				g.SetEdge(e)
    91  			}
    92  			return g
    93  		}(),
    94  		dst: simple.NewUndirectedGraph(),
    95  
    96  		want: func() graph.Graph {
    97  			g := simple.NewUndirectedGraph()
    98  			g.AddNode(simple.Node(-1))
    99  			for _, e := range []simple.Edge{
   100  				{F: simple.Node(0), T: simple.Node(1)},
   101  				{F: simple.Node(0), T: simple.Node(3)},
   102  				{F: simple.Node(1), T: simple.Node(2)},
   103  			} {
   104  				g.SetEdge(e)
   105  			}
   106  			return g
   107  		}(),
   108  	},
   109  	{
   110  		desc: "directed to directed",
   111  		src: func() graph.Graph {
   112  			g := simple.NewDirectedGraph()
   113  			g.AddNode(simple.Node(-1))
   114  			for _, e := range []simple.Edge{
   115  				{F: simple.Node(0), T: simple.Node(1)},
   116  				{F: simple.Node(0), T: simple.Node(3)},
   117  				{F: simple.Node(1), T: simple.Node(2)},
   118  			} {
   119  				g.SetEdge(e)
   120  			}
   121  			return g
   122  		}(),
   123  		dst: simple.NewDirectedGraph(),
   124  	},
   125  }
   126  
   127  func TestCopy(t *testing.T) {
   128  	for _, test := range copyTests {
   129  		graph.Copy(test.dst, test.src)
   130  		want := test.want
   131  		if want == nil {
   132  			want = test.src
   133  		}
   134  		if !same(test.dst, want) {
   135  			t.Errorf("unexpected copy result for %s", test.desc)
   136  		}
   137  	}
   138  }
   139  
   140  type graphWeightedBuilder interface {
   141  	graph.Graph
   142  	graph.WeightedBuilder
   143  }
   144  
   145  var copyWeightedTests = []struct {
   146  	desc string
   147  
   148  	src graph.Weighted
   149  	dst graphWeightedBuilder
   150  
   151  	// If want is nil, compare to src.
   152  	want graph.Graph
   153  }{
   154  	{
   155  		desc: "undirected to undirected",
   156  		src: func() graph.Weighted {
   157  			g := simple.NewWeightedUndirectedGraph(0, 0)
   158  			g.AddNode(simple.Node(-1))
   159  			for _, e := range []simple.WeightedEdge{
   160  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   161  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   162  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   163  			} {
   164  				g.SetWeightedEdge(e)
   165  			}
   166  			return g
   167  		}(),
   168  		dst: simple.NewWeightedUndirectedGraph(0, 0),
   169  	},
   170  	{
   171  		desc: "undirected to directed",
   172  		src: func() graph.Weighted {
   173  			g := simple.NewWeightedUndirectedGraph(0, 0)
   174  			g.AddNode(simple.Node(-1))
   175  			for _, e := range []simple.WeightedEdge{
   176  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   177  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   178  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   179  			} {
   180  				g.SetWeightedEdge(e)
   181  			}
   182  			return g
   183  		}(),
   184  		dst: simple.NewWeightedDirectedGraph(0, 0),
   185  
   186  		want: func() graph.Graph {
   187  			g := simple.NewWeightedDirectedGraph(0, 0)
   188  			g.AddNode(simple.Node(-1))
   189  			for _, e := range []simple.WeightedEdge{
   190  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   191  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   192  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   193  			} {
   194  				// want is a directed graph copied from
   195  				// an undirected graph so we need to have
   196  				// all edges in both directions.
   197  				g.SetWeightedEdge(e)
   198  				e.T, e.F = e.F, e.T
   199  				g.SetWeightedEdge(e)
   200  			}
   201  			return g
   202  		}(),
   203  	},
   204  	{
   205  		desc: "directed to undirected",
   206  		src: func() graph.Weighted {
   207  			g := simple.NewWeightedDirectedGraph(0, 0)
   208  			g.AddNode(simple.Node(-1))
   209  			for _, e := range []simple.WeightedEdge{
   210  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   211  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   212  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   213  			} {
   214  				g.SetWeightedEdge(e)
   215  			}
   216  			return g
   217  		}(),
   218  		dst: simple.NewWeightedUndirectedGraph(0, 0),
   219  
   220  		want: func() graph.Weighted {
   221  			g := simple.NewWeightedUndirectedGraph(0, 0)
   222  			g.AddNode(simple.Node(-1))
   223  			for _, e := range []simple.WeightedEdge{
   224  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   225  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   226  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   227  			} {
   228  				g.SetWeightedEdge(e)
   229  			}
   230  			return g
   231  		}(),
   232  	},
   233  	{
   234  		desc: "directed to directed",
   235  		src: func() graph.Weighted {
   236  			g := simple.NewWeightedDirectedGraph(0, 0)
   237  			g.AddNode(simple.Node(-1))
   238  			for _, e := range []simple.WeightedEdge{
   239  				{F: simple.Node(0), T: simple.Node(1), W: 1},
   240  				{F: simple.Node(0), T: simple.Node(3), W: 1},
   241  				{F: simple.Node(1), T: simple.Node(2), W: 1},
   242  			} {
   243  				g.SetWeightedEdge(e)
   244  			}
   245  			return g
   246  		}(),
   247  		dst: simple.NewWeightedDirectedGraph(0, 0),
   248  	},
   249  }
   250  
   251  func TestCopyWeighted(t *testing.T) {
   252  	for _, test := range copyWeightedTests {
   253  		graph.CopyWeighted(test.dst, test.src)
   254  		want := test.want
   255  		if want == nil {
   256  			want = test.src
   257  		}
   258  		if !same(test.dst, want) {
   259  			t.Errorf("unexpected copy result for %s", test.desc)
   260  		}
   261  	}
   262  }
   263  
   264  func same(a, b graph.Graph) bool {
   265  	aNodes := graph.NodesOf(a.Nodes())
   266  	bNodes := graph.NodesOf(b.Nodes())
   267  	sort.Sort(ordered.ByID(aNodes))
   268  	sort.Sort(ordered.ByID(bNodes))
   269  	for i, na := range aNodes {
   270  		nb := bNodes[i]
   271  		if na != nb {
   272  			return false
   273  		}
   274  	}
   275  	for _, u := range graph.NodesOf(a.Nodes()) {
   276  		aFromU := graph.NodesOf(a.From(u.ID()))
   277  		bFromU := graph.NodesOf(b.From(u.ID()))
   278  		if len(aFromU) != len(bFromU) {
   279  			return false
   280  		}
   281  		sort.Sort(ordered.ByID(aFromU))
   282  		sort.Sort(ordered.ByID(bFromU))
   283  		for i, va := range aFromU {
   284  			vb := bFromU[i]
   285  			if va != vb {
   286  				return false
   287  			}
   288  			aW, aWok := a.(graph.Weighted)
   289  			bW, bWok := b.(graph.Weighted)
   290  			if aWok && bWok {
   291  				if aW.WeightedEdge(u.ID(), va.ID()).Weight() != bW.WeightedEdge(u.ID(), vb.ID()).Weight() {
   292  					return false
   293  				}
   294  			}
   295  		}
   296  	}
   297  	type edger interface {
   298  		Edges() graph.Edges
   299  	}
   300  	type weightedEdger interface {
   301  		WeightedEdges() graph.WeightedEdges
   302  	}
   303  	var sizeA, sizeB int
   304  	switch a := a.(type) {
   305  	case edger:
   306  		sizeA = len(graph.EdgesOf(a.Edges()))
   307  	case weightedEdger:
   308  		sizeA = len(graph.WeightedEdgesOf(a.WeightedEdges()))
   309  	}
   310  	switch b := b.(type) {
   311  	case edger:
   312  		sizeB = len(graph.EdgesOf(b.Edges()))
   313  	case weightedEdger:
   314  		sizeB = len(graph.WeightedEdgesOf(b.WeightedEdges()))
   315  	}
   316  	return sizeA == sizeB
   317  }