aboutsummaryrefslogtreecommitdiff
path: root/src/internal/dag/alg.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/dag/alg.go')
-rw-r--r--src/internal/dag/alg.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/internal/dag/alg.go b/src/internal/dag/alg.go
new file mode 100644
index 0000000000..88002797c0
--- /dev/null
+++ b/src/internal/dag/alg.go
@@ -0,0 +1,63 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dag
+
+// Transpose reverses all edges in g.
+func (g *Graph) Transpose() {
+ old := g.edges
+
+ g.edges = make(map[string]map[string]bool)
+ for _, n := range g.Nodes {
+ g.edges[n] = make(map[string]bool)
+ }
+
+ for from, tos := range old {
+ for to := range tos {
+ g.edges[to][from] = true
+ }
+ }
+}
+
+// Topo returns a topological sort of g. This function is deterministic.
+func (g *Graph) Topo() []string {
+ topo := make([]string, 0, len(g.Nodes))
+ marks := make(map[string]bool)
+
+ var visit func(n string)
+ visit = func(n string) {
+ if marks[n] {
+ return
+ }
+ for _, to := range g.Edges(n) {
+ visit(to)
+ }
+ marks[n] = true
+ topo = append(topo, n)
+ }
+ for _, root := range g.Nodes {
+ visit(root)
+ }
+ for i, j := 0, len(topo)-1; i < j; i, j = i+1, j-1 {
+ topo[i], topo[j] = topo[j], topo[i]
+ }
+ return topo
+}
+
+// TransitiveReduction removes edges from g that are transitively
+// reachable. g must be transitively closed.
+func (g *Graph) TransitiveReduction() {
+ // For i -> j -> k, if i -> k exists, delete it.
+ for _, i := range g.Nodes {
+ for _, j := range g.Nodes {
+ if g.HasEdge(i, j) {
+ for _, k := range g.Nodes {
+ if g.HasEdge(j, k) {
+ g.DelEdge(i, k)
+ }
+ }
+ }
+ }
+ }
+}