@@ -57,23 +57,26 @@ internal static class Util
57
57
}
58
58
}
59
59
60
- public class DomRelation < Node >
60
+ public class DomRelation < TNode >
61
61
{
62
62
// doms maps (unique) node numbers to the node numbers of the immediate dominator
63
63
// to use it on Nodes, one needs the two way mapping between nodes and their numbers.
64
- private int [ ] doms ; // 0 is unused: means undefined
64
+ private int [ ] nodeNumberToImmediateDominator ; // 0 is unused: means undefined
65
65
66
66
// here are the two mappings
67
- private Node [ ] postOrderNumberToNode ;
68
- private Dictionary < Node , int > nodeToPostOrderNumber ;
67
+ private TNode [ ] postOrderNumberToNode ;
68
+ private Dictionary < TNode , int > nodeToPostOrderNumber ;
69
69
private int sourceNum ; // (number for) root of the graph
70
- private Node source ; // root of the graph
71
- private Graph < Node > graph ;
72
- private Dictionary < Node , List < Node > > immediateDominatorMap ;
70
+ private TNode source ; // root of the graph
71
+ private Graph < TNode > graph ;
72
+ private Dictionary < TNode , List < TNode > > immediateDominatorMap ;
73
73
74
74
[ NotDelayed ]
75
- internal DomRelation ( Graph < Node > g , Node source )
75
+ internal DomRelation ( Graph < TNode > g , TNode source )
76
76
{
77
+ // TODO should we enable saying that the graph is a DAG, to enable an O(N) dominance algorithm?
78
+ // Or is the algorithm already O(N) for DAG graphs?
79
+
77
80
this . graph = g ;
78
81
// slot 0 not used: nodes are numbered from 1 to n so zero
79
82
// can represent undefined.
@@ -82,7 +85,7 @@ internal DomRelation(Graph<Node> g, Node source)
82
85
this . NewComputeDominators ( ) ;
83
86
}
84
87
85
- public Dictionary < Node , List < Node > > ImmediateDominatorMap
88
+ public Dictionary < TNode , List < TNode > > ImmediateDominatorMap
86
89
{
87
90
get
88
91
{
@@ -91,60 +94,57 @@ public Dictionary<Node, List<Node>> ImmediateDominatorMap
91
94
}
92
95
}
93
96
94
- public bool DominatedBy ( Node dominee , Node dominator , List < Node > path = null )
97
+ public bool DominatedBy ( TNode dominee , TNode dominator , List < TNode > path = null )
95
98
{
96
99
Contract . Assume ( this . nodeToPostOrderNumber != null ) ;
97
- Contract . Assume ( this . doms != null ) ;
100
+ Contract . Assume ( this . nodeNumberToImmediateDominator != null ) ;
98
101
int domineeNum = this . nodeToPostOrderNumber [ dominee ] ;
99
102
int dominatorNum = this . nodeToPostOrderNumber [ dominator ] ;
100
103
if ( domineeNum == dominatorNum )
101
104
{
102
105
return true ;
103
106
}
104
107
105
- int currentNodeNum = this . doms [ domineeNum ] ;
108
+ int currentDominator = nodeNumberToImmediateDominator [ domineeNum ] ;
106
109
while ( true )
107
110
{
108
- if ( currentNodeNum == dominatorNum )
111
+ if ( currentDominator == dominatorNum )
109
112
{
110
113
return true ;
111
114
}
112
115
113
- if ( currentNodeNum == this . sourceNum )
116
+ if ( currentDominator == sourceNum )
114
117
{
115
118
return false ;
116
119
}
117
120
118
- if ( path != null )
119
- {
120
- path . Add ( postOrderNumberToNode [ currentNodeNum ] ) ;
121
- }
121
+ path ? . Add ( postOrderNumberToNode [ currentDominator ] ) ;
122
122
123
- currentNodeNum = this . doms [ currentNodeNum ] ;
123
+ currentDominator = nodeNumberToImmediateDominator [ currentDominator ] ;
124
124
}
125
125
}
126
126
127
- private Dictionary < Node , List < Node > > domMap = null ;
127
+ private Dictionary < TNode , List < TNode > > domMap = null ;
128
128
129
129
[ Pure ]
130
130
public override string ToString ( )
131
131
{
132
- Contract . Assume ( this . doms != null ) ;
133
- int [ ] localDoms = this . doms ;
132
+ Contract . Assume ( this . nodeNumberToImmediateDominator != null ) ;
133
+ int [ ] localDoms = this . nodeNumberToImmediateDominator ;
134
134
Contract . Assume ( this . postOrderNumberToNode != null ) ;
135
135
if ( domMap == null )
136
136
{
137
- domMap = new Dictionary < Node , List < Node > > ( ) ;
137
+ domMap = new Dictionary < TNode , List < TNode > > ( ) ;
138
138
for ( int i = 1 ; i < localDoms . Length ; i ++ )
139
139
{
140
140
// 0 slot is not used
141
141
int domineeNum = i ;
142
142
int currentNodeNum = domineeNum ;
143
- List < Node > dominators = new List < Node > ( ) ;
143
+ List < TNode > dominators = new List < TNode > ( ) ;
144
144
while ( currentNodeNum != this . sourceNum )
145
145
{
146
146
dominators . Add ( this . postOrderNumberToNode [ currentNodeNum ] ) ;
147
- currentNodeNum = this . doms [ currentNodeNum ] ;
147
+ currentNodeNum = this . nodeNumberToImmediateDominator [ currentNodeNum ] ;
148
148
}
149
149
150
150
dominators . Add ( this . postOrderNumberToNode [ this . sourceNum ] ) ;
@@ -155,14 +155,14 @@ public override string ToString()
155
155
StringBuilder sb = new StringBuilder ( ) ;
156
156
sb . Append ( "{" ) ;
157
157
bool first = true ;
158
- foreach ( KeyValuePair < Node , List < Node > > de in domMap )
158
+ foreach ( KeyValuePair < TNode , List < TNode > > de in domMap )
159
159
{
160
160
if ( ! first )
161
161
{
162
162
sb . Append ( ", " ) ;
163
163
}
164
164
165
- Contract . Assert ( ! object . Equals ( de . Key , default ( Node ) ) ) ;
165
+ Contract . Assert ( ! object . Equals ( de . Key , default ( TNode ) ) ) ;
166
166
sb . Append ( de . Key . ToString ( ) ) ;
167
167
sb . Append ( "~>" ) ;
168
168
sb . Append ( ListToString ( de . Value ) ) ;
@@ -235,18 +235,18 @@ public void PrintList<T>(IEnumerable<T> xs)
235
235
private void NewComputeDominators ( )
236
236
{
237
237
int n = this . graph . Nodes . Count ;
238
- this . postOrderNumberToNode = new Node [ n + 1 ] ;
239
- this . nodeToPostOrderNumber = new Dictionary < Node , int > ( ) ;
238
+ this . postOrderNumberToNode = new TNode [ n + 1 ] ;
239
+ this . nodeToPostOrderNumber = new Dictionary < TNode , int > ( ) ;
240
240
//HashSet<Node> visited = new HashSet<Node>();
241
241
//int currentNumber = 1;
242
242
Contract . Assume ( this . source != null ) ;
243
243
//this.PostOrderVisit(this.source, visited, ref currentNumber);
244
244
this . PostOrderVisitIterative ( this . source ) ;
245
245
this . sourceNum = this . nodeToPostOrderNumber [ source ] ;
246
246
// for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
247
- this . doms = new int [ n + 1 ] ; // 0 is unused: means undefined
248
- Node start_node = this . source ;
249
- this . doms [ this . nodeToPostOrderNumber [ start_node ] ] = this . nodeToPostOrderNumber [ start_node ] ;
247
+ this . nodeNumberToImmediateDominator = new int [ n + 1 ] ; // 0 is unused: means undefined
248
+ TNode start_node = this . source ;
249
+ this . nodeNumberToImmediateDominator [ this . nodeToPostOrderNumber [ start_node ] ] = this . nodeToPostOrderNumber [ start_node ] ;
250
250
bool changed = true ;
251
251
// PrintIntArray(doms);
252
252
while ( changed )
@@ -255,18 +255,18 @@ private void NewComputeDominators()
255
255
// for all nodes, b, in reverse postorder (except start_node)
256
256
for ( int nodeNum = n - 1 ; 1 <= nodeNum ; nodeNum -- )
257
257
{
258
- Node b = this . postOrderNumberToNode [ nodeNum ] ;
259
- IEnumerable < Node > predecessors = this . graph . Predecessors ( b ) ;
258
+ TNode b = this . postOrderNumberToNode [ nodeNum ] ;
259
+ IEnumerable < TNode > predecessors = this . graph . Predecessors ( b ) ;
260
260
// find a predecessor (i.e., a higher number) for which
261
261
// the doms array has been set
262
262
int new_idom = 0 ;
263
263
int first_processed_predecessor = 0 ;
264
264
265
265
#region new_idom <- number of first (processed) predecessor of b (pick one)
266
266
267
- foreach ( Node p in predecessors )
267
+ foreach ( TNode p in predecessors )
268
268
{
269
- if ( this . doms [ this . nodeToPostOrderNumber [ p ] ] != 0 )
269
+ if ( this . nodeNumberToImmediateDominator [ this . nodeToPostOrderNumber [ p ] ] != 0 )
270
270
{
271
271
int x = this . nodeToPostOrderNumber [ p ] ;
272
272
new_idom = x ;
@@ -279,24 +279,24 @@ private void NewComputeDominators()
279
279
280
280
#region for all other predecessors, p, of b
281
281
282
- foreach ( Node p in predecessors )
282
+ foreach ( TNode p in predecessors )
283
283
{
284
284
if ( this . nodeToPostOrderNumber [ p ] == first_processed_predecessor )
285
285
{
286
286
continue ;
287
287
}
288
288
289
- if ( this . doms [ this . nodeToPostOrderNumber [ p ] ] != 0 )
289
+ if ( this . nodeNumberToImmediateDominator [ this . nodeToPostOrderNumber [ p ] ] != 0 )
290
290
{
291
- new_idom = intersect ( this . nodeToPostOrderNumber [ p ] , new_idom , this . doms ) ;
291
+ new_idom = Intersect ( this . nodeToPostOrderNumber [ p ] , new_idom , this . nodeNumberToImmediateDominator ) ;
292
292
}
293
293
}
294
294
295
295
#endregion
296
296
297
- if ( this . doms [ this . nodeToPostOrderNumber [ b ] ] != new_idom )
297
+ if ( this . nodeNumberToImmediateDominator [ this . nodeToPostOrderNumber [ b ] ] != new_idom )
298
298
{
299
- this . doms [ this . nodeToPostOrderNumber [ b ] ] = new_idom ;
299
+ this . nodeNumberToImmediateDominator [ this . nodeToPostOrderNumber [ b ] ] = new_idom ;
300
300
changed = true ;
301
301
}
302
302
}
@@ -305,12 +305,12 @@ private void NewComputeDominators()
305
305
#region Populate the Immediate Dominator Map
306
306
307
307
int sourceNum = this . nodeToPostOrderNumber [ this . source ] ;
308
- immediateDominatorMap = new Dictionary < Node , List < Node > > ( ) ;
308
+ immediateDominatorMap = new Dictionary < TNode , List < TNode > > ( ) ;
309
309
for ( int i = 1 ; i <= n ; i ++ )
310
310
{
311
- Node node = this . postOrderNumberToNode [ i ] ;
312
- Node idomNode = this . postOrderNumberToNode [ this . doms [ i ] ] ;
313
- if ( i == sourceNum && this . doms [ i ] == sourceNum )
311
+ TNode node = this . postOrderNumberToNode [ i ] ;
312
+ TNode idomNode = this . postOrderNumberToNode [ this . nodeNumberToImmediateDominator [ i ] ] ;
313
+ if ( i == sourceNum && this . nodeNumberToImmediateDominator [ i ] == sourceNum )
314
314
{
315
315
continue ;
316
316
}
@@ -321,7 +321,7 @@ private void NewComputeDominators()
321
321
}
322
322
else
323
323
{
324
- List < Node > l = new List < Node > ( ) ;
324
+ List < TNode > l = new List < TNode > ( ) ;
325
325
l . Add ( node ) ;
326
326
immediateDominatorMap . Add ( idomNode , l ) ;
327
327
}
@@ -330,7 +330,7 @@ private void NewComputeDominators()
330
330
#endregion
331
331
}
332
332
333
- private int intersect ( int b1 , int b2 , int [ ] doms )
333
+ private int Intersect ( int b1 , int b2 , int [ ] doms )
334
334
{
335
335
int finger1 = b1 ;
336
336
int finger2 = b2 ;
@@ -350,7 +350,7 @@ private int intersect(int b1, int b2, int[] doms)
350
350
return finger1 ;
351
351
}
352
352
353
- private void PostOrderVisit ( Node /*!*/ n , HashSet < Node > visited , ref int currentNumber )
353
+ private void PostOrderVisit ( TNode /*!*/ n , HashSet < TNode > visited , ref int currentNumber )
354
354
{
355
355
Contract . Requires ( n != null ) ;
356
356
if ( visited . Contains ( n ) )
@@ -359,7 +359,7 @@ private void PostOrderVisit(Node /*!*/ n, HashSet<Node> visited, ref int current
359
359
}
360
360
361
361
visited . Add ( n ) ;
362
- foreach ( Node /*!*/ child in this . graph . Successors ( n ) )
362
+ foreach ( TNode /*!*/ child in this . graph . Successors ( n ) )
363
363
{
364
364
Contract . Assert ( child != null ) ;
365
365
PostOrderVisit ( child , visited , ref currentNumber ) ;
@@ -374,12 +374,12 @@ private void PostOrderVisit(Node /*!*/ n, HashSet<Node> visited, ref int current
374
374
}
375
375
376
376
// Iterative version: mimics the above recursive procedure
377
- private void PostOrderVisitIterative ( Node n )
377
+ private void PostOrderVisitIterative ( TNode n )
378
378
{
379
379
Contract . Requires ( n != null ) ;
380
- var visited = new HashSet < Node > ( ) ;
381
- var grey = new HashSet < Node > ( ) ;
382
- var stack = new Stack < Node > ( ) ;
380
+ var visited = new HashSet < TNode > ( ) ;
381
+ var grey = new HashSet < TNode > ( ) ;
382
+ var stack = new Stack < TNode > ( ) ;
383
383
384
384
int currentNumber = 1 ;
385
385
@@ -402,7 +402,7 @@ private void PostOrderVisitIterative(Node n)
402
402
{
403
403
grey . Add ( curr ) ;
404
404
stack . Push ( curr ) ;
405
- foreach ( Node /*!*/ child in this . graph . Successors ( curr ) )
405
+ foreach ( TNode /*!*/ child in this . graph . Successors ( curr ) )
406
406
{
407
407
Contract . Assert ( child != null ) ;
408
408
if ( ! visited . Contains ( child ) )
@@ -415,10 +415,10 @@ private void PostOrderVisitIterative(Node n)
415
415
}
416
416
}
417
417
418
- public Node LeastCommonAncestor ( Node n1 , Node n2 )
418
+ public TNode LeastCommonAncestor ( TNode n1 , TNode n2 )
419
419
{
420
420
int num1 = nodeToPostOrderNumber [ n1 ] , num2 = nodeToPostOrderNumber [ n2 ] ;
421
- int lca = intersect ( num1 , num2 , this . doms ) ;
421
+ int lca = Intersect ( num1 , num2 , this . nodeNumberToImmediateDominator ) ;
422
422
return postOrderNumberToNode [ lca ] ;
423
423
}
424
424
}
@@ -661,7 +661,7 @@ public static HashSet<T> Intersection<T>(IEnumerable<ISet<T>> sets) {
661
661
}
662
662
663
663
if ( result == null ) {
664
- return ImmutableHashSet < T > . Empty ;
664
+ return new HashSet < T > ( ) ;
665
665
}
666
666
667
667
return result ;
@@ -710,10 +710,10 @@ public List<Node> ImmediatelyDominatedBy(Node /*!*/ n)
710
710
{
711
711
Contract . Requires ( n != null ) ;
712
712
this . ImmediateDominatorMap . TryGetValue ( n , out var dominees ) ;
713
- return dominees == null ? new List < Node > ( ) : dominees ;
713
+ return dominees ?? new List < Node > ( ) ;
714
714
}
715
715
716
- public IEnumerable < Node /*?*/ > TopologicalSort ( bool reversed = false )
716
+ public List < Node > TopologicalSort ( bool reversed = false )
717
717
{
718
718
TarjanTopSort ( out var acyclic , out var sortedList , reversed ) ;
719
719
return acyclic ? sortedList : new List < Node > ( ) ;
0 commit comments