// Copyright ©2016 The gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore // printgraphs allows us to generate a consistent directed view of // a set of edges that follows a reasonably real-world-meaningful // graph. The interpretation of the links in the resulting directed // graphs are either "suggests" in the context of a Page Ranking or // possibly "looks up to" in the Zachary graph. package main import ( "fmt" "sort" "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/ordered" "gonum.org/v1/gonum/graph/network" "gonum.org/v1/gonum/graph/simple" ) // set is an integer set. type set map[int]struct{} func linksTo(i ...int) set { if len(i) == 0 { return nil } s := make(set) for _, v := range i { s[v] = struct{}{} } return s } var ( zachary = []set{ 0: linksTo(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 17, 19, 21, 31), 1: linksTo(2, 3, 7, 13, 17, 19, 21, 30), 2: linksTo(3, 7, 8, 9, 13, 27, 28, 32), 3: linksTo(7, 12, 13), 4: linksTo(6, 10), 5: linksTo(6, 10, 16), 6: linksTo(16), 8: linksTo(30, 32, 33), 9: linksTo(33), 13: linksTo(33), 14: linksTo(32, 33), 15: linksTo(32, 33), 18: linksTo(32, 33), 19: linksTo(33), 20: linksTo(32, 33), 22: linksTo(32, 33), 23: linksTo(25, 27, 29, 32, 33), 24: linksTo(25, 27, 31), 25: linksTo(31), 26: linksTo(29, 33), 27: linksTo(33), 28: linksTo(31, 33), 29: linksTo(32, 33), 30: linksTo(32, 33), 31: linksTo(32, 33), 32: linksTo(33), 33: nil, } blondel = []set{ 0: linksTo(2, 3, 4, 5), 1: linksTo(2, 4, 7), 2: linksTo(4, 5, 6), 3: linksTo(7), 4: linksTo(10), 5: linksTo(7, 11), 6: linksTo(7, 11), 8: linksTo(9, 10, 11, 14, 15), 9: linksTo(12, 14), 10: linksTo(11, 12, 13, 14), 11: linksTo(13), 15: nil, } ) func main() { for _, raw := range []struct { name string set []set }{ {"zachary", zachary}, {"blondel", blondel}, } { g := simple.NewUndirectedGraph(0, 0) for u, e := range raw.set { // Add nodes that are not defined by an edge. if !g.Has(simple.Node(u)) { g.AddNode(simple.Node(u)) } for v := range e { g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) } } nodes := g.Nodes() sort.Sort(ordered.ByID(nodes)) fmt.Printf("%s = []set{\n", raw.name) rank := network.PageRank(asDirected{g}, 0.85, 1e-8) for _, u := range nodes { to := g.From(nodes[u.ID()]) sort.Sort(ordered.ByID(to)) var links []int for _, v := range to { if rank[u.ID()] <= rank[v.ID()] { links = append(links, v.ID()) } } if links == nil { fmt.Printf("\t%d: nil, // rank=%.4v\n", u.ID(), rank[u.ID()]) continue } fmt.Printf("\t%d: linksTo(", u.ID()) for i, v := range links { if i != 0 { fmt.Print(", ") } fmt.Print(v) } fmt.Printf("), // rank=%.4v\n", rank[u.ID()]) } fmt.Println("}") } } type asDirected struct{ *simple.UndirectedGraph } func (g asDirected) HasEdgeFromTo(u, v graph.Node) bool { return g.UndirectedGraph.HasEdgeBetween(u, v) } func (g asDirected) To(v graph.Node) []graph.Node { return g.From(v) }