cmd/digraph: use graph.Transpose Change-Id: Ie27bb2dd6bdf211860fd271d060d0bcfcc5628e2 Reviewed-on: https://go-review.googlesource.com/c/tools/+/747368 Reviewed-by: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/cmd/digraph/digraph.go b/cmd/digraph/digraph.go index 2a9ac84..a31e13e 100644 --- a/cmd/digraph/digraph.go +++ b/cmd/digraph/digraph.go
@@ -84,12 +84,6 @@ return nodes } -func (s nodeset) addAll(x nodeset) { - for node := range x { - s[node] = true - } -} - // A digraph maps nodes to the non-nil set of their immediate successors. type digraph map[string]nodeset @@ -129,17 +123,6 @@ return nodelist(slices.Collect(g.Nodes())) } -func (g digraph) transpose() digraph { - rev := make(digraph) - for node, edges := range g { - rev.addNode(node) - for succ := range edges { - rev.addEdges(succ, node) - } - } - return rev -} - func (g digraph) sccs() []nodeset { var sccs []nodeset for _, comp := range graph.SCCs(g) { @@ -260,9 +243,13 @@ for node := range g { nodes[node] = true } - rev := g.transpose() + rev := graph.Transpose(g) for _, node := range nodes.sort() { - fmt.Fprintf(stdout, "%d\t%d\t%s\n", len(rev[node]), len(g[node]), node) + inDegree := 0 + for range rev.Out(node) { + inDegree++ + } + fmt.Fprintf(stdout, "%d\t%d\t%s\n", inDegree, len(g[node]), node) } case "transpose": @@ -270,8 +257,9 @@ return fmt.Errorf("usage: digraph transpose") } var revEdges []string - for node, succs := range g.transpose() { - for succ := range succs { + rev := graph.Transpose(g) + for node := range rev.Nodes() { + for succ := range rev.Out(node) { revEdges = append(revEdges, fmt.Sprintf("%s %s", node, succ)) } } @@ -284,17 +272,18 @@ if len(args) == 0 { return fmt.Errorf("usage: digraph %s <node> ... ", cmd) } - g := g + var gr graph.Graph[string] = g if cmd == "preds" { - g = g.transpose() + gr = graph.Transpose(g) } result := make(nodeset) for _, root := range args { - edges := g[root] - if edges == nil { + if g[root] == nil { return fmt.Errorf("no such node %q", root) } - result.addAll(edges) + for succ := range gr.Out(root) { + result[succ] = true + } } result.sort().println("\n") @@ -309,11 +298,11 @@ } roots[root] = true } - g := g + var gr graph.Graph[string] = g if cmd == "reverse" { - g = g.transpose() + gr = graph.Transpose(g) } - nodeset(graph.Reachable(g, roots.sort()...)).sort().println("\n") + nodeset(graph.Reachable(gr, roots.sort()...)).sort().println("\n") case "somepath": if len(args) != 2 { @@ -391,9 +380,9 @@ } } - gtrans := g.transpose() + gtrans := graph.Transpose(g) for from := range graph.Reachable(gtrans, node) { - for to := range gtrans[from] { + for to := range gtrans.Out(from) { edges[fmt.Sprintf("%s %s", to, from)] = struct{}{} } }