github.com/gopherd/gonum@v0.0.4/graph/simple/weighted_undirected_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 simple_test
     6  
     7  import (
     8  	"math"
     9  	"testing"
    10  
    11  	"math/rand"
    12  
    13  	"github.com/gopherd/gonum/graph"
    14  	"github.com/gopherd/gonum/graph/internal/set"
    15  	"github.com/gopherd/gonum/graph/simple"
    16  	"github.com/gopherd/gonum/graph/testgraph"
    17  )
    18  
    19  func weightedUndirectedBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) {
    20  	seen := set.NewNodes()
    21  	ug := simple.NewWeightedUndirectedGraph(self, absent)
    22  	for _, n := range nodes {
    23  		seen.Add(n)
    24  		ug.AddNode(n)
    25  	}
    26  	for _, edge := range edges {
    27  		if edge.From().ID() == edge.To().ID() {
    28  			continue
    29  		}
    30  		f := ug.Node(edge.From().ID())
    31  		if f == nil {
    32  			f = edge.From()
    33  		}
    34  		t := ug.Node(edge.To().ID())
    35  		if t == nil {
    36  			t = edge.To()
    37  		}
    38  		ce := simple.WeightedEdge{F: f, T: t, W: edge.Weight()}
    39  		seen.Add(ce.F)
    40  		seen.Add(ce.T)
    41  		e = append(e, ce)
    42  		ug.SetWeightedEdge(ce)
    43  	}
    44  	if len(e) == 0 && len(edges) != 0 {
    45  		return nil, nil, nil, math.NaN(), math.NaN(), false
    46  	}
    47  	if len(seen) != 0 {
    48  		n = make([]graph.Node, 0, len(seen))
    49  	}
    50  	for _, sn := range seen {
    51  		n = append(n, sn)
    52  	}
    53  	return ug, n, e, self, absent, true
    54  }
    55  
    56  func TestWeightedUndirected(t *testing.T) {
    57  	t.Run("EdgeExistence", func(t *testing.T) {
    58  		testgraph.EdgeExistence(t, weightedUndirectedBuilder, reversesEdges)
    59  	})
    60  	t.Run("NodeExistence", func(t *testing.T) {
    61  		testgraph.NodeExistence(t, weightedUndirectedBuilder)
    62  	})
    63  	t.Run("ReturnAdjacentNodes", func(t *testing.T) {
    64  		testgraph.ReturnAdjacentNodes(t, weightedUndirectedBuilder, usesEmpty, reversesEdges)
    65  	})
    66  	t.Run("ReturnAllEdges", func(t *testing.T) {
    67  		testgraph.ReturnAllEdges(t, weightedUndirectedBuilder, usesEmpty)
    68  	})
    69  	t.Run("ReturnAllNodes", func(t *testing.T) {
    70  		testgraph.ReturnAllNodes(t, weightedUndirectedBuilder, usesEmpty)
    71  	})
    72  	t.Run("ReturnAllWeightedEdges", func(t *testing.T) {
    73  		testgraph.ReturnAllWeightedEdges(t, weightedUndirectedBuilder, usesEmpty)
    74  	})
    75  	t.Run("ReturnEdgeSlice", func(t *testing.T) {
    76  		testgraph.ReturnEdgeSlice(t, weightedUndirectedBuilder, usesEmpty)
    77  	})
    78  	t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) {
    79  		testgraph.ReturnWeightedEdgeSlice(t, weightedUndirectedBuilder, usesEmpty)
    80  	})
    81  	t.Run("ReturnNodeSlice", func(t *testing.T) {
    82  		testgraph.ReturnNodeSlice(t, weightedUndirectedBuilder, usesEmpty)
    83  	})
    84  	t.Run("Weight", func(t *testing.T) {
    85  		testgraph.Weight(t, weightedUndirectedBuilder)
    86  	})
    87  
    88  	t.Run("AddNodes", func(t *testing.T) {
    89  		testgraph.AddNodes(t, simple.NewWeightedUndirectedGraph(1, 0), 100)
    90  	})
    91  	t.Run("AddArbitraryNodes", func(t *testing.T) {
    92  		testgraph.AddArbitraryNodes(t,
    93  			simple.NewWeightedUndirectedGraph(1, 0),
    94  			testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }),
    95  		)
    96  	})
    97  	t.Run("AddWeightedEdges", func(t *testing.T) {
    98  		testgraph.AddWeightedEdges(t, 100,
    99  			simple.NewWeightedUndirectedGraph(1, 0),
   100  			0.5,
   101  			func(id int64) graph.Node { return simple.Node(id) },
   102  			false, // Cannot set self-loops.
   103  			true,  // Can update nodes.
   104  		)
   105  	})
   106  	t.Run("NoLoopAddWeightedEdges", func(t *testing.T) {
   107  		testgraph.NoLoopAddWeightedEdges(t, 100,
   108  			simple.NewWeightedUndirectedGraph(1, 0),
   109  			0.5,
   110  			func(id int64) graph.Node { return simple.Node(id) },
   111  		)
   112  	})
   113  	t.Run("RemoveNodes", func(t *testing.T) {
   114  		g := simple.NewWeightedUndirectedGraph(1, 0)
   115  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) })
   116  		for it.Next() {
   117  			g.AddNode(it.Node())
   118  		}
   119  		it.Reset()
   120  		rnd := rand.New(rand.NewSource(1))
   121  		for it.Next() {
   122  			u := it.Node()
   123  			d := rnd.Intn(5)
   124  			vit := g.Nodes()
   125  			for d >= 0 && vit.Next() {
   126  				v := vit.Node()
   127  				if v.ID() == u.ID() {
   128  					continue
   129  				}
   130  				d--
   131  				g.SetWeightedEdge(g.NewWeightedEdge(u, v, 1))
   132  			}
   133  		}
   134  		testgraph.RemoveNodes(t, g)
   135  	})
   136  	t.Run("RemoveEdges", func(t *testing.T) {
   137  		g := simple.NewWeightedUndirectedGraph(1, 0)
   138  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) })
   139  		for it.Next() {
   140  			g.AddNode(it.Node())
   141  		}
   142  		it.Reset()
   143  		rnd := rand.New(rand.NewSource(1))
   144  		for it.Next() {
   145  			u := it.Node()
   146  			d := rnd.Intn(5)
   147  			vit := g.Nodes()
   148  			for d >= 0 && vit.Next() {
   149  				v := vit.Node()
   150  				if v.ID() == u.ID() {
   151  					continue
   152  				}
   153  				d--
   154  				g.SetWeightedEdge(g.NewWeightedEdge(u, v, 1))
   155  			}
   156  		}
   157  		testgraph.RemoveEdges(t, g, g.Edges())
   158  	})
   159  }
   160  
   161  func TestAssertWeightedMutableNotDirected(t *testing.T) {
   162  	var g graph.UndirectedWeightedBuilder = simple.NewWeightedUndirectedGraph(0, math.Inf(1))
   163  	if _, ok := g.(graph.Directed); ok {
   164  		t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!")
   165  	}
   166  }
   167  
   168  func TestWeightedMaxID(t *testing.T) {
   169  	g := simple.NewWeightedUndirectedGraph(0, math.Inf(1))
   170  	nodes := make(map[graph.Node]struct{})
   171  	for i := simple.Node(0); i < 3; i++ {
   172  		g.AddNode(i)
   173  		nodes[i] = struct{}{}
   174  	}
   175  	g.RemoveNode(int64(0))
   176  	delete(nodes, simple.Node(0))
   177  	g.RemoveNode(int64(2))
   178  	delete(nodes, simple.Node(2))
   179  	n := g.NewNode()
   180  	g.AddNode(n)
   181  	if g.Node(n.ID()) == nil {
   182  		t.Error("added node does not exist in graph")
   183  	}
   184  	if _, exists := nodes[n]; exists {
   185  		t.Errorf("Created already existing node id: %v", n.ID())
   186  	}
   187  }
   188  
   189  // Test for issue #123 https://github.com/gonum/graph/issues/123
   190  func TestIssue123WeightedUndirectedGraph(t *testing.T) {
   191  	defer func() {
   192  		if r := recover(); r != nil {
   193  			t.Errorf("unexpected panic: %v", r)
   194  		}
   195  	}()
   196  	g := simple.NewWeightedUndirectedGraph(0, math.Inf(1))
   197  
   198  	n0 := g.NewNode()
   199  	g.AddNode(n0)
   200  
   201  	n1 := g.NewNode()
   202  	g.AddNode(n1)
   203  
   204  	g.RemoveNode(n0.ID())
   205  
   206  	n2 := g.NewNode()
   207  	g.AddNode(n2)
   208  }