github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/flow/control_flow_test.go (about) 1 // Copyright ©2017 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package flow 6 7 import ( 8 "reflect" 9 "sort" 10 "testing" 11 12 "github.com/jingcheng-WU/gonum/graph" 13 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 14 "github.com/jingcheng-WU/gonum/graph/simple" 15 ) 16 17 var dominatorsTests = []struct { 18 n graph.Node 19 edges []simple.Edge 20 21 want DominatorTree 22 }{ 23 { // Example from Lengauer and Tarjan http://www.dtic.mil/dtic/tr/fulltext/u2/a054144.pdf fig 1. 24 n: char('R'), 25 edges: []simple.Edge{ 26 {F: char('A'), T: char('D')}, 27 {F: char('B'), T: char('A')}, 28 {F: char('B'), T: char('D')}, 29 {F: char('B'), T: char('E')}, 30 {F: char('C'), T: char('F')}, 31 {F: char('C'), T: char('G')}, 32 {F: char('D'), T: char('L')}, 33 {F: char('E'), T: char('H')}, 34 {F: char('F'), T: char('I')}, 35 {F: char('G'), T: char('I')}, 36 {F: char('G'), T: char('J')}, 37 {F: char('H'), T: char('E')}, 38 {F: char('H'), T: char('K')}, 39 {F: char('I'), T: char('K')}, 40 {F: char('J'), T: char('I')}, 41 {F: char('K'), T: char('I')}, 42 {F: char('K'), T: char('R')}, 43 {F: char('L'), T: char('H')}, 44 {F: char('R'), T: char('A')}, 45 {F: char('R'), T: char('B')}, 46 {F: char('R'), T: char('C')}, 47 }, 48 49 want: DominatorTree{ 50 root: char('R'), 51 dominatorOf: map[int64]graph.Node{ 52 'A': char('R'), 53 'B': char('R'), 54 'C': char('R'), 55 'D': char('R'), 56 'E': char('R'), 57 'F': char('C'), 58 'G': char('C'), 59 'H': char('R'), 60 'I': char('R'), 61 'J': char('G'), 62 'K': char('R'), 63 'L': char('D'), 64 }, 65 dominatedBy: map[int64][]graph.Node{ 66 'C': {char('F'), char('G')}, 67 'D': {char('L')}, 68 'G': {char('J')}, 69 'R': {char('A'), char('B'), char('C'), char('D'), char('E'), char('H'), char('I'), char('K')}, 70 }, 71 }, 72 }, 73 { // WP example: https://en.wikipedia.org/w/index.php?title=Dominator_(graph_theory)&oldid=758099236. 74 n: simple.Node(1), 75 edges: []simple.Edge{ 76 {F: simple.Node(1), T: simple.Node(2)}, 77 {F: simple.Node(2), T: simple.Node(3)}, 78 {F: simple.Node(2), T: simple.Node(4)}, 79 {F: simple.Node(2), T: simple.Node(6)}, 80 {F: simple.Node(3), T: simple.Node(5)}, 81 {F: simple.Node(4), T: simple.Node(5)}, 82 {F: simple.Node(5), T: simple.Node(2)}, 83 }, 84 85 want: DominatorTree{ 86 root: simple.Node(1), 87 dominatorOf: map[int64]graph.Node{ 88 2: simple.Node(1), 89 3: simple.Node(2), 90 4: simple.Node(2), 91 5: simple.Node(2), 92 6: simple.Node(2), 93 }, 94 dominatedBy: map[int64][]graph.Node{ 95 1: {simple.Node(2)}, 96 2: {simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6)}, 97 }, 98 }, 99 }, 100 { // WP example with node IDs decremented by 1. 101 n: simple.Node(0), 102 edges: []simple.Edge{ 103 {F: simple.Node(0), T: simple.Node(1)}, 104 {F: simple.Node(1), T: simple.Node(2)}, 105 {F: simple.Node(1), T: simple.Node(3)}, 106 {F: simple.Node(1), T: simple.Node(5)}, 107 {F: simple.Node(2), T: simple.Node(4)}, 108 {F: simple.Node(3), T: simple.Node(4)}, 109 {F: simple.Node(4), T: simple.Node(1)}, 110 }, 111 112 want: DominatorTree{ 113 root: simple.Node(0), 114 dominatorOf: map[int64]graph.Node{ 115 1: simple.Node(0), 116 2: simple.Node(1), 117 3: simple.Node(1), 118 4: simple.Node(1), 119 5: simple.Node(1), 120 }, 121 dominatedBy: map[int64][]graph.Node{ 122 0: {simple.Node(1)}, 123 1: {simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5)}, 124 }, 125 }, 126 }, 127 } 128 129 type char rune 130 131 func (n char) ID() int64 { return int64(n) } 132 func (n char) String() string { return string(n) } 133 134 func TestDominators(t *testing.T) { 135 for _, test := range dominatorsTests { 136 g := simple.NewDirectedGraph() 137 for _, e := range test.edges { 138 g.SetEdge(e) 139 } 140 141 for _, alg := range []struct { 142 name string 143 fn func(graph.Node, graph.Directed) DominatorTree 144 }{ 145 {"Dominators", Dominators}, 146 {"DominatorsSLT", DominatorsSLT}, 147 } { 148 got := alg.fn(test.n, g) 149 150 if !reflect.DeepEqual(got.Root(), test.want.root) { 151 t.Errorf("unexpected dominator tree root from %s: got:%v want:%v", 152 alg.name, got.root, test.want.root) 153 } 154 155 if !reflect.DeepEqual(got.dominatorOf, test.want.dominatorOf) { 156 t.Errorf("unexpected dominator tree from %s: got:%v want:%v", 157 alg.name, got.dominatorOf, test.want.dominatorOf) 158 } 159 160 for q, want := range test.want.dominatorOf { 161 node := got.DominatorOf(q) 162 if node != want { 163 t.Errorf("unexpected dominator tree result from %s dominated of %v: got:%v want:%v", 164 alg.name, q, node, want) 165 } 166 } 167 168 for _, nodes := range got.dominatedBy { 169 sort.Sort(ordered.ByID(nodes)) 170 } 171 172 if !reflect.DeepEqual(got.dominatedBy, test.want.dominatedBy) { 173 t.Errorf("unexpected dominator tree from %s: got:%v want:%v", 174 alg.name, got.dominatedBy, test.want.dominatedBy) 175 } 176 177 for q, want := range test.want.dominatedBy { 178 nodes := got.DominatedBy(q) 179 if !reflect.DeepEqual(nodes, want) { 180 t.Errorf("unexpected dominator tree result from %s dominated by %v: got:%v want:%v", 181 alg.name, q, nodes, want) 182 } 183 } 184 } 185 } 186 }