github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/spectral/laplacian_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 spectral
     6  
     7  import (
     8  	"sort"
     9  	"testing"
    10  
    11  	"github.com/jingcheng-WU/gonum/floats/scalar"
    12  	"github.com/jingcheng-WU/gonum/graph"
    13  	"github.com/jingcheng-WU/gonum/graph/internal/ordered"
    14  	"github.com/jingcheng-WU/gonum/graph/iterator"
    15  	"github.com/jingcheng-WU/gonum/graph/simple"
    16  	"github.com/jingcheng-WU/gonum/mat"
    17  )
    18  
    19  var randomWalkLaplacianTests = []struct {
    20  	g    []set
    21  	damp float64
    22  
    23  	want *mat.Dense
    24  }{
    25  	{
    26  		g: []set{
    27  			A: linksTo(B, C),
    28  			B: linksTo(C),
    29  			C: nil,
    30  		},
    31  
    32  		want: mat.NewDense(3, 3, []float64{
    33  			1, 0, 0,
    34  			-0.5, 1, 0,
    35  			-0.5, -1, 0,
    36  		}),
    37  	},
    38  	{
    39  		g: []set{
    40  			A: linksTo(B, C),
    41  			B: linksTo(C),
    42  			C: nil,
    43  		},
    44  		damp: 0.85,
    45  
    46  		want: mat.NewDense(3, 3, []float64{
    47  			0.15, 0, 0,
    48  			-0.075, 0.15, 0,
    49  			-0.075, -0.15, 0,
    50  		}),
    51  	},
    52  	{
    53  		g: []set{
    54  			A: linksTo(B),
    55  			B: linksTo(C),
    56  			C: linksTo(A),
    57  		},
    58  		damp: 0.85,
    59  
    60  		want: mat.NewDense(3, 3, []float64{
    61  			0.15, 0, -0.15,
    62  			-0.15, 0.15, 0,
    63  			0, -0.15, 0.15,
    64  		}),
    65  	},
    66  	{
    67  		// Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009
    68  		g: []set{
    69  			A: nil,
    70  			B: linksTo(C),
    71  			C: linksTo(B),
    72  			D: linksTo(A, B),
    73  			E: linksTo(D, B, F),
    74  			F: linksTo(B, E),
    75  			G: linksTo(B, E),
    76  			H: linksTo(B, E),
    77  			I: linksTo(B, E),
    78  			J: linksTo(E),
    79  			K: linksTo(E),
    80  		},
    81  
    82  		want: mat.NewDense(11, 11, []float64{
    83  			0, 0, 0, -0.5, 0, 0, 0, 0, 0, 0, 0,
    84  			0, 1, -1, -0.5, -1. / 3., -0.5, -0.5, -0.5, -0.5, 0, 0,
    85  			0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
    86  			0, 0, 0, 1, -1. / 3., 0, 0, 0, 0, 0, 0,
    87  			0, 0, 0, 0, 1, -0.5, -0.5, -0.5, -0.5, -1, -1,
    88  			0, 0, 0, 0, -1. / 3., 1, 0, 0, 0, 0, 0,
    89  			0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
    90  			0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
    91  			0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
    92  			0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
    93  			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    94  		}),
    95  	},
    96  }
    97  
    98  func TestRandomWalkLaplacian(t *testing.T) {
    99  	const tol = 1e-14
   100  	for i, test := range randomWalkLaplacianTests {
   101  		g := simple.NewDirectedGraph()
   102  		for u, e := range test.g {
   103  			// Add nodes that are not defined by an edge.
   104  			if g.Node(int64(u)) == nil {
   105  				g.AddNode(simple.Node(u))
   106  			}
   107  			for v := range e {
   108  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
   109  			}
   110  		}
   111  		l := NewRandomWalkLaplacian(g, test.damp)
   112  		_, c := l.Dims()
   113  		for j := 0; j < c; j++ {
   114  			if got := mat.Sum(l.Matrix.(*mat.Dense).ColView(j)); !scalar.EqualWithinAbsOrRel(got, 0, tol, tol) {
   115  				t.Errorf("unexpected column sum for test %d, column %d: got:%v want:0", i, j, got)
   116  			}
   117  		}
   118  		l = NewRandomWalkLaplacian(sortedNodeGraph{g}, test.damp)
   119  		if !mat.EqualApprox(l, test.want, tol) {
   120  			t.Errorf("unexpected result for test %d:\ngot:\n% .2v\nwant:\n% .2v",
   121  				i, mat.Formatted(l), mat.Formatted(test.want))
   122  		}
   123  	}
   124  }
   125  
   126  type sortedNodeGraph struct {
   127  	graph.Graph
   128  }
   129  
   130  func (g sortedNodeGraph) Nodes() graph.Nodes {
   131  	n := graph.NodesOf(g.Graph.Nodes())
   132  	sort.Sort(ordered.ByID(n))
   133  	return iterator.NewOrderedNodes(n)
   134  }
   135  
   136  const (
   137  	A = iota
   138  	B
   139  	C
   140  	D
   141  	E
   142  	F
   143  	G
   144  	H
   145  	I
   146  	J
   147  	K
   148  	L
   149  	M
   150  	N
   151  	O
   152  	P
   153  	Q
   154  	R
   155  	S
   156  	T
   157  	U
   158  	V
   159  	W
   160  	X
   161  	Y
   162  	Z
   163  )
   164  
   165  // set is an integer set.
   166  type set map[int64]struct{}
   167  
   168  func linksTo(i ...int64) set {
   169  	if len(i) == 0 {
   170  		return nil
   171  	}
   172  	s := make(set)
   173  	for _, v := range i {
   174  		s[v] = struct{}{}
   175  	}
   176  	return s
   177  }