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