@@ -21,62 +21,58 @@ type AdjacencyMatrix struct {
21
21
// TODO implement transpose, undirected
22
22
23
23
// NewAdjacencyMatrix returns an AdjacencyMatrix. Each vertex pair can only
24
- // have one edge. For a multigraph, use [NewMultiAdjacencyMatrix].
24
+ // have one edge. For a multigraph, where vertex pairs can store a count of
25
+ // multiple edges, use [NewMultiAdjacencyMatrix].
25
26
func NewAdjacencyMatrix () AdjacencyMatrix {
26
27
return AdjacencyMatrix {
27
28
mat : matrix .NewBit (4 , 4 ),
28
29
multi : false ,
29
30
}
30
31
}
31
32
32
- // NewAdjacencyMatrix returns an AdjacencyMatrix. Each vertex pair can have
33
- // a count of multiple edges. For a simple graph, use [NewAdjacencyMatrix].
33
+ // NewMultiAdjacencyMatrix returns an AdjacencyMatrix. Each vertex pair can
34
+ // have a count of multiple edges. For a simple graph, where each vertex pair
35
+ // can have at most one edge, use [NewAdjacencyMatrix].
34
36
func NewMultiAdjacencyMatrix () AdjacencyMatrix {
35
37
return AdjacencyMatrix {
36
38
mat : matrix .NewGrid [int ](4 , 4 ),
37
39
multi : true ,
38
40
}
39
41
}
40
42
41
- // Matrix returns a pointer to the underlying [matrix.M] (of type int).
43
+ // Matrix returns a pointer to the underlying [matrix.M] (of type int). Note
44
+ // that if the matrix is resized, this value may become an old reference.
42
45
func (m AdjacencyMatrix ) Matrix () matrix.M [int ] {
43
46
return m .mat
44
47
}
45
48
46
49
// Get returns the number of directed edges from a source vertex to a target
47
50
// vertex (including self-loops, if any).
48
51
func (m AdjacencyMatrix ) Get (source , target VertexIndex ) int {
49
- if int (max (source , target )) > m .Width ( ) { return 0 }
52
+ if int (max (source , target )) >= m .mat . Length ( 'x' ) { return 0 }
50
53
idx := m .mat .Index (int (source ), int (target ))
51
54
return m .mat .Get (idx )
52
55
}
53
56
54
57
// Set stores the number of directed edges from a source vertex to a target
55
58
// vertex (including self-loops, if any).
56
- func (m AdjacencyMatrix ) Set (source , target VertexIndex , count int ) {
59
+ //
60
+ // THe matrix is automatically resized, if necessary.
61
+ func (m * AdjacencyMatrix ) Set (source , target VertexIndex , count int ) {
57
62
largest := max (source , target )
58
- m .Resize (int (largest ))
63
+ m .Resize (int (largest ) + 1 )
59
64
idx := m .mat .Index (int (source ), int (target ))
60
65
m .mat .Set (idx , count )
61
66
}
62
67
63
- // Width returns the width of the adjacency matrix. Note that if VertexIndexes
64
- // are sparsely distributed, width may be greater the number of vertexes
65
- // produced by iteration.
66
- func (m AdjacencyMatrix ) Width () int {
67
- return m .mat .Length (0 )
68
- }
69
-
70
68
// CountEdges returns the total number of edges in the adjacency matrix.
71
69
func (m AdjacencyMatrix ) CountEdges () int {
70
+ // walk the matrix sparsely
72
71
sum := 0
73
-
74
- // optimisation: walk the matrix sparsely
75
72
for idx , ok := - 1 , true ; ok ; idx , ok = m .mat .Next (idx ) {
76
73
if idx < 0 { continue }
77
74
sum += m .mat .Get (idx )
78
75
}
79
-
80
76
return sum
81
77
}
82
78
@@ -86,19 +82,16 @@ func (m AdjacencyMatrix) Clear() {
86
82
87
83
// Resize updates the adjacency matrix, if necessary, so that it has at least
88
84
// capacity for width elements in each dimension.
89
- func (m AdjacencyMatrix ) Resize (width int ) {
90
- if m .Width () <= width { return }
85
+ func (m * AdjacencyMatrix ) Resize (width int ) {
86
+ if m .mat . Length ( 'x' ) > width { return }
91
87
width = int (integer .AlignPowTwo (uint (width )))
92
88
93
- // TODO move this into matrix itself
94
-
95
- var mcons matrix.M [int ]
89
+ var dest matrix.M [int ]
96
90
if m .multi {
97
- mcons = matrix .NewGrid [int ](width , width )
91
+ dest = matrix .NewGrid [int ](width , width )
98
92
} else {
99
- mcons = matrix .NewBit [ int ] (width , width )
93
+ dest = matrix .NewBit (width , width )
100
94
}
101
- dest := mcons
102
95
matrix .Copy (dest , m .mat )
103
96
m .mat = dest
104
97
}
@@ -110,7 +103,7 @@ func (m AdjacencyMatrix) Resize(width int) {
110
103
// constant time.
111
104
func (m AdjacencyMatrix ) Indegree (target VertexIndex ) int {
112
105
var sum = 0
113
- for i := 0 ; i < m .Width ( ); i ++ {
106
+ for i := 0 ; i < m .mat . Length ( 'x' ); i ++ {
114
107
idx := m .mat .Index (i , int (target ))
115
108
sum += m .mat .Get (idx )
116
109
}
@@ -124,7 +117,7 @@ func (m AdjacencyMatrix) Indegree(target VertexIndex) int {
124
117
// constant time.
125
118
func (m AdjacencyMatrix ) Outdegree (source VertexIndex ) int {
126
119
var sum = 0
127
- for i := 0 ; i < m .Width ( ); i ++ {
120
+ for i := 0 ; i < m .mat . Length ( 'x' ); i ++ {
128
121
idx := m .mat .Index (int (source ), i )
129
122
sum += m .mat .Get (idx )
130
123
}
@@ -140,10 +133,10 @@ func (m AdjacencyMatrix) Degree(source VertexIndex) int {
140
133
return m .Indegree (source ) + m .Outdegree (source )
141
134
}
142
135
143
- // Vertexes implements the graph [Iterator] Vertexes method. Every vertex will
144
- // have at least one edge (in either direction).
136
+ // Vertexes implements the graph [Iterator] Vertexes method. An AdjacencyMatrix
137
+ // is a graph of every vertex that has at least one edge (in either direction).
145
138
func (m AdjacencyMatrix ) Vertexes () func () (VertexIndex , bool ) {
146
- i , width := 0 , m .Width ( )
139
+ i , width := 0 , m .mat . Length ( 'x' )
147
140
return func () (_ VertexIndex , _ bool ) {
148
141
for {
149
142
if i >= width { return }
@@ -157,7 +150,7 @@ func (m AdjacencyMatrix) Vertexes() func() (VertexIndex, bool) {
157
150
158
151
// Edges implements the graph [Iterator] Edges method.
159
152
func (m AdjacencyMatrix ) Edges (source VertexIndex ) func () (VertexIndex , int , bool ) {
160
- i , width := 0 , m . Width ( )
153
+ i , width := 0 , m . mat . Length ( 'x' )
161
154
return func () (_ VertexIndex , _ int , _ bool ) {
162
155
for {
163
156
if i >= width { return }
@@ -186,7 +179,7 @@ func (m AdjacencyMatrix) Weight(source, target VertexIndex) Weight {
186
179
// Each vertex index in the adjacency matrix corresponds to a matching index
187
180
// in graph g. Once an adjacency matrix has been constructed, it is not
188
181
// affected by future changes to graph g.
189
- func (m AdjacencyMatrix ) Calculate (g Iterator ) {
182
+ func (m * AdjacencyMatrix ) Calculate (g Iterator ) {
190
183
width := int (vertexIndexLimit (g .Vertexes ))
191
184
m .Resize (width )
192
185
m .Clear ()
0 commit comments