gonum.org/v1/gonum@v0.14.0/graph/multi/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 multi_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/iterator"
    16  	"gonum.org/v1/gonum/graph/multi"
    17  	"gonum.org/v1/gonum/graph/testgraph"
    18  )
    19  
    20  const (
    21  	usesEmpty     = true
    22  	reversesEdges = true
    23  )
    24  
    25  func undirectedBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, _, _ float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) {
    26  	seen := set.NewNodes()
    27  	ug := multi.NewUndirectedGraph()
    28  	for _, n := range nodes {
    29  		seen.Add(n)
    30  		ug.AddNode(n)
    31  	}
    32  	for _, edge := range edges {
    33  		f := ug.Node(edge.From().ID())
    34  		if f == nil {
    35  			f = edge.From()
    36  		}
    37  		t := ug.Node(edge.To().ID())
    38  		if t == nil {
    39  			t = edge.To()
    40  		}
    41  		ce := multi.Line{F: f, T: t, UID: edge.ID()}
    42  		seen.Add(ce.F)
    43  		seen.Add(ce.T)
    44  		e = append(e, ce)
    45  		ug.SetLine(ce)
    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, math.NaN(), math.NaN(), true
    54  }
    55  
    56  func TestUndirected(t *testing.T) {
    57  	t.Run("EdgeExistence", func(t *testing.T) {
    58  		testgraph.EdgeExistence(t, undirectedBuilder, reversesEdges)
    59  	})
    60  	t.Run("LineExistence", func(t *testing.T) {
    61  		testgraph.LineExistence(t, undirectedBuilder, usesEmpty, reversesEdges)
    62  	})
    63  	t.Run("NodeExistence", func(t *testing.T) {
    64  		testgraph.NodeExistence(t, undirectedBuilder)
    65  	})
    66  	t.Run("ReturnAdjacentNodes", func(t *testing.T) {
    67  		testgraph.ReturnAdjacentNodes(t, undirectedBuilder, usesEmpty, reversesEdges)
    68  	})
    69  	t.Run("ReturnAllLines", func(t *testing.T) {
    70  		testgraph.ReturnAllLines(t, undirectedBuilder, usesEmpty)
    71  	})
    72  	t.Run("ReturnAllNodes", func(t *testing.T) {
    73  		testgraph.ReturnAllNodes(t, undirectedBuilder, usesEmpty)
    74  	})
    75  	t.Run("ReturnNodeSlice", func(t *testing.T) {
    76  		testgraph.ReturnNodeSlice(t, undirectedBuilder, usesEmpty)
    77  	})
    78  
    79  	t.Run("AddNodes", func(t *testing.T) {
    80  		testgraph.AddNodes(t, multi.NewUndirectedGraph(), 100)
    81  	})
    82  	t.Run("AddArbitraryNodes", func(t *testing.T) {
    83  		testgraph.AddArbitraryNodes(t,
    84  			multi.NewUndirectedGraph(),
    85  			testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.Node(id) }),
    86  		)
    87  	})
    88  	t.Run("RemoveNodes", func(t *testing.T) {
    89  		g := multi.NewUndirectedGraph()
    90  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.Node(id) })
    91  		for it.Next() {
    92  			g.AddNode(it.Node())
    93  		}
    94  		it.Reset()
    95  		rnd := rand.New(rand.NewSource(1))
    96  		for it.Next() {
    97  			u := it.Node()
    98  			d := rnd.Intn(5)
    99  			vit := g.Nodes()
   100  			for d >= 0 && vit.Next() {
   101  				v := vit.Node()
   102  				d--
   103  				g.SetLine(g.NewLine(u, v))
   104  			}
   105  		}
   106  		testgraph.RemoveNodes(t, g)
   107  	})
   108  	t.Run("AddLines", func(t *testing.T) {
   109  		testgraph.AddLines(t, 100,
   110  			multi.NewUndirectedGraph(),
   111  			func(id int64) graph.Node { return multi.Node(id) },
   112  			true, // Can update nodes.
   113  		)
   114  	})
   115  	t.Run("RemoveLines", func(t *testing.T) {
   116  		g := multi.NewUndirectedGraph()
   117  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.Node(id) })
   118  		for it.Next() {
   119  			g.AddNode(it.Node())
   120  		}
   121  		it.Reset()
   122  		var lines []graph.Line
   123  		rnd := rand.New(rand.NewSource(1))
   124  		for it.Next() {
   125  			u := it.Node()
   126  			d := rnd.Intn(5)
   127  			vit := g.Nodes()
   128  			for d >= 0 && vit.Next() {
   129  				v := vit.Node()
   130  				d--
   131  				l := g.NewLine(u, v)
   132  				g.SetLine(l)
   133  				lines = append(lines, l)
   134  			}
   135  		}
   136  		rnd.Shuffle(len(lines), func(i, j int) {
   137  			lines[i], lines[j] = lines[j], lines[i]
   138  		})
   139  		testgraph.RemoveLines(t, g, iterator.NewOrderedLines(lines))
   140  	})
   141  }
   142  
   143  func TestMaxID(t *testing.T) {
   144  	g := multi.NewUndirectedGraph()
   145  	nodes := make(map[graph.Node]struct{})
   146  	for i := multi.Node(0); i < 3; i++ {
   147  		g.AddNode(i)
   148  		nodes[i] = struct{}{}
   149  	}
   150  	g.RemoveNode(int64(0))
   151  	delete(nodes, multi.Node(0))
   152  	g.RemoveNode(int64(2))
   153  	delete(nodes, multi.Node(2))
   154  	n := g.NewNode()
   155  	g.AddNode(n)
   156  	if g.Node(n.ID()) == nil {
   157  		t.Error("added node does not exist in graph")
   158  	}
   159  	if _, exists := nodes[n]; exists {
   160  		t.Errorf("Created already existing node id: %v", n.ID())
   161  	}
   162  }
   163  
   164  // Test for issue #123 https://github.com/gonum/graph/issues/123
   165  func TestIssue123UndirectedGraph(t *testing.T) {
   166  	defer func() {
   167  		if r := recover(); r != nil {
   168  			t.Errorf("unexpected panic: %v", r)
   169  		}
   170  	}()
   171  	g := multi.NewUndirectedGraph()
   172  
   173  	n0 := g.NewNode()
   174  	g.AddNode(n0)
   175  
   176  	n1 := g.NewNode()
   177  	g.AddNode(n1)
   178  
   179  	g.RemoveNode(n0.ID())
   180  
   181  	n2 := g.NewNode()
   182  	g.AddNode(n2)
   183  }