gonum.org/v1/gonum@v0.14.0/graph/simple/weighted_directed_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  	"golang.org/x/exp/rand"
    12  
    13  	"gonum.org/v1/gonum/graph"
    14  	"gonum.org/v1/gonum/graph/internal/set"
    15  	"gonum.org/v1/gonum/graph/simple"
    16  	"gonum.org/v1/gonum/graph/testgraph"
    17  )
    18  
    19  func weightedDirectedBuilder(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  	dg := simple.NewWeightedDirectedGraph(self, absent)
    22  	for _, n := range nodes {
    23  		seen.Add(n)
    24  		dg.AddNode(n)
    25  	}
    26  	for _, edge := range edges {
    27  		if edge.From().ID() == edge.To().ID() {
    28  			continue
    29  		}
    30  		f := dg.Node(edge.From().ID())
    31  		if f == nil {
    32  			f = edge.From()
    33  		}
    34  		t := dg.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  		dg.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 dg, n, e, self, absent, true
    54  }
    55  
    56  func TestWeightedDirected(t *testing.T) {
    57  	t.Run("EdgeExistence", func(t *testing.T) {
    58  		testgraph.EdgeExistence(t, weightedDirectedBuilder, reversesEdges)
    59  	})
    60  	t.Run("NodeExistence", func(t *testing.T) {
    61  		testgraph.NodeExistence(t, weightedDirectedBuilder)
    62  	})
    63  	t.Run("ReturnAdjacentNodes", func(t *testing.T) {
    64  		testgraph.ReturnAdjacentNodes(t, weightedDirectedBuilder, usesEmpty, reversesEdges)
    65  	})
    66  	t.Run("ReturnAllEdges", func(t *testing.T) {
    67  		testgraph.ReturnAllEdges(t, weightedDirectedBuilder, usesEmpty)
    68  	})
    69  	t.Run("ReturnAllNodes", func(t *testing.T) {
    70  		testgraph.ReturnAllNodes(t, weightedDirectedBuilder, usesEmpty)
    71  	})
    72  	t.Run("ReturnAllWeightedEdges", func(t *testing.T) {
    73  		testgraph.ReturnAllWeightedEdges(t, weightedDirectedBuilder, usesEmpty)
    74  	})
    75  	t.Run("ReturnEdgeSlice", func(t *testing.T) {
    76  		testgraph.ReturnEdgeSlice(t, weightedDirectedBuilder, usesEmpty)
    77  	})
    78  	t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) {
    79  		testgraph.ReturnWeightedEdgeSlice(t, weightedDirectedBuilder, usesEmpty)
    80  	})
    81  	t.Run("ReturnNodeSlice", func(t *testing.T) {
    82  		testgraph.ReturnNodeSlice(t, weightedDirectedBuilder, usesEmpty)
    83  	})
    84  	t.Run("Weight", func(t *testing.T) {
    85  		testgraph.Weight(t, weightedDirectedBuilder)
    86  	})
    87  
    88  	t.Run("AddNodes", func(t *testing.T) {
    89  		testgraph.AddNodes(t, simple.NewWeightedDirectedGraph(1, 0), 100)
    90  	})
    91  	t.Run("AddArbitraryNodes", func(t *testing.T) {
    92  		testgraph.AddArbitraryNodes(t,
    93  			simple.NewWeightedDirectedGraph(1, 0),
    94  			testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }),
    95  		)
    96  	})
    97  	t.Run("RemoveNodes", func(t *testing.T) {
    98  		g := simple.NewWeightedDirectedGraph(1, 0)
    99  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) })
   100  		for it.Next() {
   101  			g.AddNode(it.Node())
   102  		}
   103  		it.Reset()
   104  		rnd := rand.New(rand.NewSource(1))
   105  		for it.Next() {
   106  			u := it.Node()
   107  			d := rnd.Intn(5)
   108  			vit := g.Nodes()
   109  			for d >= 0 && vit.Next() {
   110  				v := vit.Node()
   111  				if v.ID() == u.ID() {
   112  					continue
   113  				}
   114  				d--
   115  				g.SetWeightedEdge(g.NewWeightedEdge(u, v, 1))
   116  			}
   117  		}
   118  		testgraph.RemoveNodes(t, g)
   119  	})
   120  	t.Run("AddWeightedEdges", func(t *testing.T) {
   121  		testgraph.AddWeightedEdges(t, 100,
   122  			simple.NewWeightedDirectedGraph(1, 0),
   123  			0.5,
   124  			func(id int64) graph.Node { return simple.Node(id) },
   125  			false, // Cannot set self-loops.
   126  			true,  // Can update nodes.
   127  		)
   128  	})
   129  	t.Run("NoLoopAddWeightedEdges", func(t *testing.T) {
   130  		testgraph.NoLoopAddWeightedEdges(t, 100,
   131  			simple.NewWeightedDirectedGraph(1, 0),
   132  			0.5,
   133  			func(id int64) graph.Node { return simple.Node(id) },
   134  		)
   135  	})
   136  	t.Run("RemoveEdges", func(t *testing.T) {
   137  		g := simple.NewWeightedDirectedGraph(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  // Tests Issue #27
   162  func TestWeightedEdgeOvercounting(t *testing.T) {
   163  	g := generateDummyWeightedGraph()
   164  
   165  	if neigh := graph.NodesOf(g.From(int64(2))); len(neigh) != 2 {
   166  		t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh))
   167  	}
   168  }
   169  
   170  func generateDummyWeightedGraph() *simple.WeightedDirectedGraph {
   171  	nodes := [4]struct{ srcID, targetID int }{
   172  		{2, 1},
   173  		{1, 0},
   174  		{2, 0},
   175  		{0, 2},
   176  	}
   177  
   178  	g := simple.NewWeightedDirectedGraph(0, math.Inf(1))
   179  
   180  	for _, n := range nodes {
   181  		g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(n.srcID), T: simple.Node(n.targetID), W: 1})
   182  	}
   183  
   184  	return g
   185  }
   186  
   187  // Test for issue #123 https://github.com/gonum/graph/issues/123
   188  func TestIssue123WeightedDirectedGraph(t *testing.T) {
   189  	defer func() {
   190  		if r := recover(); r != nil {
   191  			t.Errorf("unexpected panic: %v", r)
   192  		}
   193  	}()
   194  	g := simple.NewWeightedDirectedGraph(0, math.Inf(1))
   195  
   196  	n0 := g.NewNode()
   197  	g.AddNode(n0)
   198  
   199  	n1 := g.NewNode()
   200  	g.AddNode(n1)
   201  
   202  	g.RemoveNode(n0.ID())
   203  
   204  	n2 := g.NewNode()
   205  	g.AddNode(n2)
   206  }