23
23
// to turn on caching for any component. This gives constant time
24
24
// performance for all basic operations on that component.
25
25
//
26
- // Example usage
26
+ // Tutorial
27
27
//
28
- // The package examples show how to build graphs from standard components
29
- // using composition and filtering. They also demonstrate how to apply
30
- // a cost function to a virtual graph.
28
+ // The Euclid and Maxflow examples show how to build graphs from
29
+ // standard components using composition and filtering. They also
30
+ // demonstrate how to apply a cost function to a virtual graph.
31
31
//
32
32
package build
33
33
@@ -41,21 +41,25 @@ import (
41
41
// by composing and filtering a set of standard graphs, or by writing
42
42
// functions that describe the edges of a graph.
43
43
type Virtual struct {
44
+ // The `order` field is, in fact, a constant function.
45
+ // It returns the number of vertices in the graph.
44
46
order int
45
- // The edge and cost functions define a weighted graph without self-loops.
47
+
48
+ // The `edge` and `cost` functions define a weighted graph without self-loops.
46
49
//
47
50
// • edge(v, w) returns true whenever (v, w) belongs to the graph;
48
51
// the value is disregarded when v == w.
49
52
//
50
- // • cost(v, w) returns the cost of (v, w); the value is disregarded
51
- // when edge(v, w) is false.
53
+ // • cost(v, w) returns the cost of (v, w);
54
+ // the value is disregarded when edge(v, w) is false.
55
+ //
52
56
edge func (v , w int ) bool
53
57
cost func (v , w int ) int64
54
58
55
- // These functions can be used to improve performance.
56
- // They MUST BE CONSISTENT with edge and cost.
57
- // The generic() factory method contains a basic implementation .
58
- // The Consistent test function should be used to check compliance.
59
+ // The `degree` and `visit` functions can be used to improve performance.
60
+ // They MUST BE CONSISTENT with edge and cost. If not implemented,
61
+ // the ` generic` or `generic0` implementation is used instead .
62
+ // The ` Consistent` test function should be used to check compliance.
59
63
//
60
64
// • degree(v) returns the outdegree of vertex v.
61
65
//
@@ -64,12 +68,13 @@ type Virtual struct {
64
68
// If a call to do returns true, visit MUST ABORT the iteration
65
69
// and return true; if successful it should return false.
66
70
// Precondition: a ≥ 0.
71
+ //
67
72
degree func (v int ) int
68
73
visit func (v int , a int , do func (w int , c int64 ) (skip bool )) (aborted bool )
69
74
}
70
75
71
76
// FilterFunc is a function that tells if there is a directed edge from v to w.
72
- // The nil value represents an edge functions that always returns true.
77
+ // The nil value represents an edge function that always returns true.
73
78
type FilterFunc func (v , w int ) bool
74
79
75
80
// CostFunc is a function that computes the cost of an edge from v to w.
@@ -107,7 +112,7 @@ func max(m, n int) int {
107
112
return m
108
113
}
109
114
110
- // null is the null graph; a graph of order 0 .
115
+ // null is the null graph; a graph with no vertices .
111
116
var null = new (Virtual )
112
117
113
118
// singleton returns a graph with one vertex.
@@ -126,7 +131,7 @@ func edge() *Virtual {
126
131
g := & Virtual {
127
132
order : 2 ,
128
133
cost : zero ,
129
- edge : func ( v , w int ) bool { return v != w } ,
134
+ edge : alwaysEdge ,
130
135
degree : degreeOne ,
131
136
}
132
137
g .visit = func (v int , a int , do func (w int , c int64 ) bool ) (aborted bool ) {
@@ -260,17 +265,16 @@ func Generic(n int, edge FilterFunc) *Virtual {
260
265
return generic0 (n , edge )
261
266
}
262
267
263
- // Specific returns a cached copy of g with constant time performance
264
- // for all basic operations. It uses space proportional to
265
- // the size of the graph.
268
+ // Specific returns a cached copy of g with constant time performance for
269
+ // all basic operations. It uses space proportional to the size of the graph.
266
270
//
267
271
// This function does not accept multigraphs and graphs with self-loops.
268
272
func Specific (g graph.Iterator ) * Virtual {
269
- stats := graph .Check (g )
273
+ h := graph .Sort (g )
274
+ stats := graph .Check (h )
270
275
if stats .Multi != 0 || stats .Loops != 0 {
271
276
panic ("Virtual doesn't support multiple edges or self-loops" )
272
277
}
273
- h := graph .Sort (g )
274
278
res := & Virtual {
275
279
order : h .Order (),
276
280
edge : h .Edge ,
@@ -282,7 +286,7 @@ func Specific(g graph.Iterator) *Virtual {
282
286
return res
283
287
}
284
288
res .cost = func (v , w int ) (cost int64 ) {
285
- if ! res . edge (v , w ) {
289
+ if ! h . Edge (v , w ) {
286
290
return 0
287
291
}
288
292
h .VisitFrom (v , w , func (w int , c int64 ) (skip bool ) {
@@ -353,10 +357,7 @@ func (g *Virtual) Complement() *Virtual {
353
357
return singleton ()
354
358
}
355
359
res := generic0 (n , func (v , w int ) (edge bool ) {
356
- if v != w {
357
- return ! g .edge (v , w )
358
- }
359
- return
360
+ return v != w && ! g .edge (v , w )
360
361
})
361
362
res .degree = func (v int ) int { return n - 1 - g .degree (v ) }
362
363
res .visit = func (v int , a int , do func (w int , c int64 ) bool ) (aborted bool ) {
0 commit comments