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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
|
// Copyright 2014 Sonia Keys
// License MIT: http://opensource.org/licenses/MIT
package graph
// adj_RO.go is code generated from adj_cg.go by directives in graph.go.
// Editing adj_cg.go is okay.
// DO NOT EDIT adj_RO.go. The RO is for Read Only.
import (
"math/rand"
"time"
)
// ArcSize returns the number of arcs in g.
//
// Note that for an undirected graph without loops, the number of undirected
// edges -- the traditional meaning of graph size -- will be ArcSize()/2.
// On the other hand, if g is an undirected graph that has or may have loops,
// g.ArcSize()/2 is not a meaningful quantity.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) ArcSize() int {
m := 0
for _, to := range g {
m += len(to)
}
return m
}
// BoundsOk validates that all arcs in g stay within the slice bounds of g.
//
// BoundsOk returns true when no arcs point outside the bounds of g.
// Otherwise it returns false and an example arc that points outside of g.
//
// Most methods of this package assume the BoundsOk condition and may
// panic when they encounter an arc pointing outside of the graph. This
// function can be used to validate a graph when the BoundsOk condition
// is unknown.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) BoundsOk() (ok bool, fr NI, to Half) {
for fr, to := range g {
for _, to := range to {
if to.To < 0 || to.To >= NI(len(g)) {
return false, NI(fr), to
}
}
}
return true, -1, to
}
// BreadthFirst traverses a directed or undirected graph in breadth first order.
//
// Argument start is the start node for the traversal. If r is nil, nodes are
// visited in deterministic order. If a random number generator is supplied,
// nodes at each level are visited in random order.
//
// Argument f can be nil if you have no interest in the FromList path result.
// If FromList f is non-nil, the method populates f.Paths and sets f.MaxLen.
// It does not set f.Leaves. For convenience argument f can be a zero value
// FromList. If f.Paths is nil, the FromList is initialized first. If f.Paths
// is non-nil however, the FromList is used as is. The method uses a value of
// PathEnd.Len == 0 to indentify unvisited nodes. Existing non-zero values
// will limit the traversal.
//
// Traversal calls the visitor function v for each node starting with node
// start. If v returns true, traversal continues. If v returns false, the
// traversal terminates immediately. PathEnd Len and From values are updated
// before calling the visitor function.
//
// On return f.Paths and f.MaxLen are set but not f.Leaves.
//
// Returned is the number of nodes visited and ok = true if the traversal
// ran to completion or ok = false if it was terminated by the visitor
// function returning false.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) BreadthFirst(start NI, r *rand.Rand, f *FromList, v OkNodeVisitor) (visited int, ok bool) {
switch {
case f == nil:
e := NewFromList(len(g))
f = &e
case f.Paths == nil:
*f = NewFromList(len(g))
}
rp := f.Paths
// the frontier consists of nodes all at the same level
frontier := []NI{start}
level := 1
// assign path when node is put on frontier,
rp[start] = PathEnd{Len: level, From: -1}
for {
f.MaxLen = level
level++
var next []NI
if r == nil {
for _, n := range frontier {
visited++
if !v(n) { // visit nodes as they come off frontier
return
}
for _, nb := range g[n] {
if rp[nb.To].Len == 0 {
next = append(next, nb.To)
rp[nb.To] = PathEnd{From: n, Len: level}
}
}
}
} else { // take nodes off frontier at random
for _, i := range r.Perm(len(frontier)) {
n := frontier[i]
// remainder of block same as above
visited++
if !v(n) {
return
}
for _, nb := range g[n] {
if rp[nb.To].Len == 0 {
next = append(next, nb.To)
rp[nb.To] = PathEnd{From: n, Len: level}
}
}
}
}
if len(next) == 0 {
break
}
frontier = next
}
return visited, true
}
// BreadthFirstPath finds a single path from start to end with a minimum
// number of nodes.
//
// Returned is the path as list of nodes.
// The result is nil if no path was found.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) BreadthFirstPath(start, end NI) []NI {
var f FromList
g.BreadthFirst(start, nil, &f, func(n NI) bool { return n != end })
return f.PathTo(end, nil)
}
// Copy makes a deep copy of g.
// Copy also computes the arc size ma, the number of arcs.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) Copy() (c LabeledAdjacencyList, ma int) {
c = make(LabeledAdjacencyList, len(g))
for n, to := range g {
c[n] = append([]Half{}, to...)
ma += len(to)
}
return
}
// DepthFirst traverses a graph depth first.
//
// As it traverses it calls visitor function v for each node. If v returns
// false at any point, the traversal is terminated immediately and DepthFirst
// returns false. Otherwise DepthFirst returns true.
//
// DepthFirst uses argument bm is used as a bitmap to guide the traversal.
// For a complete traversal, bm should be 0 initially. During the
// traversal, bits are set corresponding to each node visited.
// The bit is set before calling the visitor function.
//
// Argument bm can be nil if you have no need for it.
// In this case a bitmap is created internally for one-time use.
//
// Alternatively v can be nil. In this case traversal still proceeds and
// updates the bitmap, which can be a useful result.
// DepthFirst always returns true in this case.
//
// It makes no sense for both bm and v to be nil. In this case DepthFirst
// returns false immediately.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) DepthFirst(start NI, bm *Bits, v OkNodeVisitor) (ok bool) {
if bm == nil {
if v == nil {
return false
}
bm = &Bits{}
}
var df func(n NI) bool
df = func(n NI) bool {
if bm.Bit(n) == 1 {
return true
}
bm.SetBit(n, 1)
if v != nil && !v(n) {
return false
}
for _, nb := range g[n] {
if !df(nb.To) {
return false
}
}
return true
}
return df(start)
}
// DepthFirstRandom traverses a graph depth first, but following arcs in
// random order among arcs from a single node.
//
// If Rand r is nil, the method creates a new source and generator for
// one-time use.
//
// Usage is otherwise like the DepthFirst method. See DepthFirst.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) DepthFirstRandom(start NI, bm *Bits, v OkNodeVisitor, r *rand.Rand) (ok bool) {
if bm == nil {
if v == nil {
return false
}
bm = &Bits{}
}
if r == nil {
r = rand.New(rand.NewSource(time.Now().UnixNano()))
}
var df func(n NI) bool
df = func(n NI) bool {
if bm.Bit(n) == 1 {
return true
}
bm.SetBit(n, 1)
if v != nil && !v(n) {
return false
}
to := g[n]
for _, i := range r.Perm(len(to)) {
if !df(to[i].To) {
return false
}
}
return true
}
return df(start)
}
// HasArc returns true if g has any arc from node fr to node to.
//
// Also returned is the index within the slice of arcs from node fr.
// If no arc from fr to to is present, HasArc returns false, -1.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) HasArc(fr, to NI) (bool, int) {
for x, h := range g[fr] {
if h.To == to {
return true, x
}
}
return false, -1
}
// HasLoop identifies if a graph contains a loop, an arc that leads from a
// a node back to the same node.
//
// If the graph has a loop, the result is an example node that has a loop.
//
// If g contains a loop, the method returns true and an example of a node
// with a loop. If there are no loops in g, the method returns false, -1.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) HasLoop() (bool, NI) {
for fr, to := range g {
for _, to := range to {
if NI(fr) == to.To {
return true, to.To
}
}
}
return false, -1
}
// HasParallelMap identifies if a graph contains parallel arcs, multiple arcs
// that lead from a node to the same node.
//
// If the graph has parallel arcs, the method returns true and
// results fr and to represent an example where there are parallel arcs
// from node fr to node to.
//
// If there are no parallel arcs, the method returns false, -1 -1.
//
// Multiple loops on a node count as parallel arcs.
//
// "Map" in the method name indicates that a Go map is used to detect parallel
// arcs. Compared to method HasParallelSort, this gives better asymtotic
// performance for large dense graphs but may have increased overhead for
// small or sparse graphs.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) HasParallelMap() (has bool, fr, to NI) {
for n, to := range g {
if len(to) == 0 {
continue
}
m := map[NI]struct{}{}
for _, to := range to {
if _, ok := m[to.To]; ok {
return true, NI(n), to.To
}
m[to.To] = struct{}{}
}
}
return false, -1, -1
}
// IsSimple checks for loops and parallel arcs.
//
// A graph is "simple" if it has no loops or parallel arcs.
//
// IsSimple returns true, -1 for simple graphs. If a loop or parallel arc is
// found, simple returns false and a node that represents a counterexample
// to the graph being simple.
//
// See also separate methods HasLoop and HasParallel.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) IsSimple() (ok bool, n NI) {
if lp, n := g.HasLoop(); lp {
return false, n
}
if pa, n, _ := g.HasParallelSort(); pa {
return false, n
}
return true, -1
}
// IsolatedNodes returns a bitmap of isolated nodes in receiver graph g.
//
// An isolated node is one with no arcs going to or from it.
//
// There are equivalent labeled and unlabeled versions of this method.
func (g LabeledAdjacencyList) IsolatedNodes() (i Bits) {
i.SetAll(len(g))
for fr, to := range g {
if len(to) > 0 {
i.SetBit(NI(fr), 0)
for _, to := range to {
i.SetBit(to.To, 0)
}
}
}
return
}
/*
MaxmimalClique finds a maximal clique containing the node n.
Not sure this is good for anything. It produces a single maximal clique
but there can be multiple maximal cliques containing a given node.
This algorithm just returns one of them, not even necessarily the
largest one.
func (g LabeledAdjacencyList) MaximalClique(n int) []int {
c := []int{n}
var m bitset.BitSet
m.Set(uint(n))
for fr, to := range g {
if fr == n {
continue
}
if len(to) < len(c) {
continue
}
f := 0
for _, to := range to {
if m.Test(uint(to.To)) {
f++
if f == len(c) {
c = append(c, to.To)
m.Set(uint(to.To))
break
}
}
}
}
return c
}
*/
|