@@ -67,6 +67,8 @@ func (l nodelist) println(sep string) {
67
67
68
68
type nodeset map [string ]bool
69
69
70
+ func singleton (x string ) nodeset { return nodeset {x : true } }
71
+
70
72
func (s nodeset ) sort () nodelist {
71
73
nodes := make (nodelist , len (s ))
72
74
var i int
@@ -191,26 +193,17 @@ func (g graph) sccs() []nodeset {
191
193
}
192
194
193
195
func (g graph ) allpaths (from , to string ) error {
194
- // Mark all nodes to "to".
195
- seen := make (nodeset ) // value of seen[x] indicates whether x is on some path to "to"
196
- var visit func (node string ) bool
197
- visit = func (node string ) bool {
198
- reachesTo , ok := seen [node ]
199
- if ! ok {
200
- reachesTo = node == to
201
- seen [node ] = reachesTo
202
- for e := range g [node ] {
203
- if visit (e ) {
204
- reachesTo = true
205
- }
206
- }
207
- if reachesTo && node != to {
208
- seen [node ] = true
209
- }
196
+ // We intersect the forward closure of 'from' with
197
+ // the reverse closure of 'to'. This is not the most
198
+ // efficient implementation, but it's the clearest,
199
+ // and the previous one had bugs.
200
+ seen := g .reachableFrom (singleton (from ))
201
+ rev := g .transpose ().reachableFrom (singleton (to ))
202
+ for n := range seen {
203
+ if ! rev [n ] {
204
+ delete (seen , n )
210
205
}
211
- return reachesTo
212
206
}
213
- visit (from )
214
207
215
208
// For each marked node, collect its marked successors.
216
209
var edges []string
@@ -241,7 +234,7 @@ func (g graph) somepath(from, to string) error {
241
234
tail * path
242
235
}
243
236
244
- seen := nodeset { from : true }
237
+ seen := singleton ( from )
245
238
246
239
var queue []* path
247
240
queue = append (queue , & path {node : from , tail : nil })
@@ -469,14 +462,14 @@ func digraph(cmd string, args []string) error {
469
462
}
470
463
471
464
edges := make (map [string ]struct {})
472
- for from := range g .reachableFrom (nodeset { node : true } ) {
465
+ for from := range g .reachableFrom (singleton ( node ) ) {
473
466
for to := range g [from ] {
474
467
edges [fmt .Sprintf ("%s %s" , from , to )] = struct {}{}
475
468
}
476
469
}
477
470
478
471
gtrans := g .transpose ()
479
- for from := range gtrans .reachableFrom (nodeset { node : true } ) {
472
+ for from := range gtrans .reachableFrom (singleton ( node ) ) {
480
473
for to := range gtrans [from ] {
481
474
edges [fmt .Sprintf ("%s %s" , to , from )] = struct {}{}
482
475
}
0 commit comments