gonum.org/v1/gonum@v0.14.0/graph/network/hits.go (about) 1 // Copyright ©2015 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 network 6 7 import ( 8 "math" 9 10 "gonum.org/v1/gonum/floats" 11 "gonum.org/v1/gonum/graph" 12 ) 13 14 // HubAuthority is a Hyperlink-Induced Topic Search hub-authority score pair. 15 type HubAuthority struct { 16 Hub float64 17 Authority float64 18 } 19 20 // HITS returns the Hyperlink-Induced Topic Search hub-authority scores for 21 // nodes of the directed graph g. HITS terminates when the 2-norm of the 22 // vector difference between iterations is below tol. The returned map is 23 // keyed on the graph node IDs. 24 func HITS(g graph.Directed, tol float64) map[int64]HubAuthority { 25 nodes := graph.NodesOf(g.Nodes()) 26 27 // Make a topological copy of g with dense node IDs. 28 indexOf := make(map[int64]int, len(nodes)) 29 for i, n := range nodes { 30 indexOf[n.ID()] = i 31 } 32 nodesLinkingTo := make([][]int, len(nodes)) 33 nodesLinkedFrom := make([][]int, len(nodes)) 34 for i, n := range nodes { 35 id := n.ID() 36 from := g.To(id) 37 for from.Next() { 38 u := from.Node() 39 nodesLinkingTo[i] = append(nodesLinkingTo[i], indexOf[u.ID()]) 40 } 41 to := g.From(id) 42 for to.Next() { 43 v := to.Node() 44 nodesLinkedFrom[i] = append(nodesLinkedFrom[i], indexOf[v.ID()]) 45 } 46 } 47 48 w := make([]float64, 4*len(nodes)) 49 auth := w[:len(nodes)] 50 hub := w[len(nodes) : 2*len(nodes)] 51 for i := range nodes { 52 auth[i] = 1 53 hub[i] = 1 54 } 55 deltaAuth := w[2*len(nodes) : 3*len(nodes)] 56 deltaHub := w[3*len(nodes):] 57 58 var norm float64 59 for { 60 norm = 0 61 for v := range nodes { 62 var a float64 63 for _, u := range nodesLinkingTo[v] { 64 a += hub[u] 65 } 66 deltaAuth[v] = auth[v] 67 auth[v] = a 68 norm += a * a 69 } 70 norm = math.Sqrt(norm) 71 72 for i := range auth { 73 auth[i] /= norm 74 deltaAuth[i] -= auth[i] 75 } 76 77 norm = 0 78 for u := range nodes { 79 var h float64 80 for _, v := range nodesLinkedFrom[u] { 81 h += auth[v] 82 } 83 deltaHub[u] = hub[u] 84 hub[u] = h 85 norm += h * h 86 } 87 norm = math.Sqrt(norm) 88 89 for i := range hub { 90 hub[i] /= norm 91 deltaHub[i] -= hub[i] 92 } 93 94 if floats.Norm(deltaAuth, 2) < tol && floats.Norm(deltaHub, 2) < tol { 95 break 96 } 97 } 98 99 hubAuth := make(map[int64]HubAuthority, len(nodes)) 100 for i, n := range nodes { 101 hubAuth[n.ID()] = HubAuthority{Hub: hub[i], Authority: auth[i]} 102 } 103 104 return hubAuth 105 }