-
Notifications
You must be signed in to change notification settings - Fork 2
/
simplegraph.go
129 lines (109 loc) · 3.18 KB
/
simplegraph.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package graph
import (
"fmt"
"github.com/sbromberger/graphmatrix"
)
// SimpleGraph is a graph structure representing an undirected graph.
type SimpleGraph struct {
fmx, bmx graphmatrix.GraphMatrix
}
func (g SimpleGraph) String() string {
return fmt.Sprintf("(%d, %d) graph", g.NumVertices(), g.NumEdges())
}
// MakeSimpleGraph creates an undirected graph from vectors of source and dest vertices.
func New(ss, ds []uint32) (SimpleGraph, error) {
rSs := make([]uint32, len(ss))
rDs := make([]uint32, len(ds))
copy(rSs, ss)
copy(rDs, ds)
err := graphmatrix.SortIJ(&ss, &ds)
if err != nil {
return SimpleGraph{}, err
}
err = graphmatrix.SortIJ(&rDs, &rSs)
if err != nil {
return SimpleGraph{}, err
}
fmx, err := graphmatrix.NewFromSortedIJ(ss, ds)
if err != nil {
return SimpleGraph{}, err
}
bmx, err := graphmatrix.NewFromSortedIJ(rDs, rSs)
if err != nil {
return SimpleGraph{}, err
}
return SimpleGraph{fmx: fmx, bmx: bmx}, nil
}
func NewFromEdgeList(l EdgeList) (SimpleGraph, error) {
ss := make([]uint32, len(l))
ds := make([]uint32, len(l))
for i, e := range l {
ss[i] = e.Src()
ds[i] = e.Dst()
}
return New(ss, ds)
}
// OutDegree returns the out degree of vertex u.
func (g SimpleGraph) OutDegree(u uint32) uint32 { return uint32(len(g.OutNeighbors(u))) }
// InDegree returns the indegree of vertex u.
func (g SimpleGraph) InDegree(u uint32) uint32 { return uint32(len(g.InNeighbors(u))) }
// OutNeighbors returns the out neighbors of vertex u.
func (g SimpleGraph) OutNeighbors(u uint32) []uint32 {
r, _ := g.fmx.GetRow(u)
return r
}
// InNeighbors returns the in neighbors of vertex u.
func (g SimpleGraph) InNeighbors(u uint32) []uint32 {
r, _ := g.bmx.GetRow(u)
return r
}
// HasEdge returns true if an edge exists between u and v.
func (g SimpleGraph) HasEdge(u, v uint32) bool {
un := g.OutNeighbors(u)
vn := g.InNeighbors(v)
lenun := uint64(len(un))
lenvn := uint64(len(vn))
var found bool
if lenvn > lenun {
_, found = graphmatrix.SearchSorted32(un, v, 0, lenun)
} else {
_, found = graphmatrix.SearchSorted32(vn, u, 0, lenvn)
}
return found
}
// AddEdge adds an edge to graph g
func (g *SimpleGraph) AddEdge(u, v uint32) error {
if err := g.fmx.SetIndex(u, v); err != nil {
return err
}
if err := g.bmx.SetIndex(v, u); err != nil {
return err
}
return nil
}
// NumEdges returns the number of edges
func (g SimpleGraph) NumEdges() uint64 {
return g.fmx.N()
}
// NumVertices returns the number of vertices
func (g SimpleGraph) NumVertices() uint32 {
return g.fmx.Dim()
}
// Edges returns an iterator of edges
func (g SimpleGraph) Edges() EdgeIter {
return &SimpleEdgeIter{mxiter: g.fmx.NewNZIter()}
}
// FMat returns the forward matrix of the graph.
func (g SimpleGraph) FMat() graphmatrix.GraphMatrix {
return g.fmx
}
// BMat returns the backward matrix of the graph.
func (g SimpleGraph) BMat() graphmatrix.GraphMatrix {
return g.bmx
}
func (g SimpleGraph) IsDirected() bool { return false }
func FromRaw(findptr []uint64, find []uint32, bindptr []uint64, bind []uint32) (SimpleGraph, error) {
fmx := graphmatrix.GraphMatrix{IndPtr: findptr, Indices: find}
bmx := graphmatrix.GraphMatrix{IndPtr: bindptr, Indices: bind}
return SimpleGraph{fmx, bmx}, nil
}