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  }