@@ -19,57 +19,35 @@ function aag_bareiss(sys::AbstractSystem)
19
19
return aag_bareiss! (state. structure. graph, complete (state. structure. var_to_diff), mm)
20
20
end
21
21
22
- function extreme_var (var_to_diff, v, level = nothing , :: Val{descend} = Val (true )) where descend
22
+ function extreme_var (var_to_diff, v, level = nothing , :: Val{descend} = Val (true ); callback = _ -> nothing ) where descend
23
23
g = descend ? invview (var_to_diff) : var_to_diff
24
+ callback (v)
24
25
while (v′ = g[v]) != = nothing
25
- v = v′
26
+ v:: Int = v′
27
+ callback (v)
26
28
if level != = nothing
27
29
descend ? (level -= 1 ) : (level += 1 )
28
30
end
29
31
end
30
32
level === nothing ? v : (v => level)
31
33
end
32
34
33
- function neighbor_branches! (visited, (ag, invag), var_to_diff, v, level = 0 )
34
- ns = Pair{Int, Int}[]
35
- visited[v] && return ns
36
- v′:: Union{Nothing, Int} = v
37
- diff_to_var = invview (var_to_diff)
38
- while (v′ = diff_to_var[v]) != = nothing
39
- v = v′
40
- level -= 1
41
- end
42
- while true
43
- if (_n = get (ag, v, nothing )) != = nothing
44
- n = _n[2 ]
45
- visited[n] || push! (ns, n => level)
46
- end
47
- for n in neighbors (invag, v)
48
- visited[n] || push! (ns, n => level)
49
- end
50
- visited[v] = true
51
- (v′ = var_to_diff[v]) === nothing && break
52
- v = v′
53
- level += 1
54
- end
55
- ns
56
- end
57
-
58
- function walk_to_root! (visited, ags, var_to_diff, v:: Integer , level = 0 )
59
- brs = neighbor_branches! (visited, ags, var_to_diff, v, level)
35
+ function walk_to_root! (iag, v:: Integer , level = 0 )
36
+ brs = neighbors (iag, v)
60
37
min_var_level = v => level
61
- isempty (brs) && return extreme_var (var_to_diff, min_var_level ... )
62
- for (x, lv) in brs
63
- x, lv = walk_to_root! (visited, ags, var_to_diff , x, lv)
38
+ for (x, lv′) in brs
39
+ lv = lv′ + level
40
+ x, lv = walk_to_root! (iag , x, lv)
64
41
if min_var_level[2 ] > lv
65
42
min_var_level = x => lv
66
43
end
67
44
end
68
- return extreme_var (var_to_diff, min_var_level... )
45
+ return extreme_var (iag . var_to_diff, min_var_level... )
69
46
end
70
47
71
48
function alias_elimination (sys)
72
49
state = TearingState (sys; quick_cancel = true )
50
+ Main. _state[] = state
73
51
ag, mm = alias_eliminate_graph! (state)
74
52
ag === nothing && return sys
75
53
@@ -108,15 +86,16 @@ function alias_elimination(sys)
108
86
end
109
87
Main. _a[] = ag, invag
110
88
processed = falses (nvars)
111
- visited = falses (nvars )
89
+ iag = InducedAliasGraph (ag, invag, var_to_diff, processed )
112
90
newag = AliasGraph (nvars)
113
91
for (v, dv) in enumerate (var_to_diff)
114
92
processed[v] && continue
115
93
(dv === nothing && diff_to_var[v] === nothing ) && continue
116
94
117
95
# TODO : use an iterator, and get a relative level vector for `processed`
118
96
# variabels.
119
- r, lv = walk_to_root! (processed, (ag, invag), var_to_diff, v)
97
+ r, lv = walk_to_root! (iag, v)
98
+ fill! (processed, false )
120
99
# lv = extreme_var(var_to_diff, v, -lv, Val(false))
121
100
lv′ = extreme_var (var_to_diff, v, 0 , Val (false ))[2 ]
122
101
let
@@ -330,6 +309,70 @@ function Base.in(i::Int, agk::AliasGraphKeySet)
330
309
1 <= i <= length (aliasto) && aliasto[i] != = nothing
331
310
end
332
311
312
+ struct InducedAliasGraph
313
+ ag:: AliasGraph
314
+ invag:: SimpleDiGraph{Int}
315
+ var_to_diff:: DiffGraph
316
+ visited:: BitVector
317
+ end
318
+
319
+ InducedAliasGraph (ag, invag, var_to_diff) = InducedAliasGraph (ag, invag, var_to_diff, falses (nv (invag)))
320
+
321
+ struct IAGNeighbors
322
+ iag:: InducedAliasGraph
323
+ v:: Int
324
+ end
325
+
326
+ function Base. iterate (it:: IAGNeighbors , state = nothing )
327
+ @unpack ag, invag, var_to_diff, visited = it. iag
328
+ callback! = let visited = visited
329
+ var -> visited[var] = true
330
+ end
331
+ if state === nothing
332
+ v, lv = extreme_var (var_to_diff, it. v, 0 )
333
+ used_ag = false
334
+ nb = neighbors (invag, v)
335
+ nit = iterate (nb)
336
+ state = (v, lv, used_ag, nb, nit)
337
+ end
338
+
339
+ v, level, used_ag, nb, nit = state
340
+ visited[v] && return nothing
341
+ while true
342
+ @label TRYAGIN
343
+ if used_ag
344
+ if nit != = nothing
345
+ n, ns = nit
346
+ if ! visited[n]
347
+ n, lv = extreme_var (var_to_diff, n, level)
348
+ extreme_var (var_to_diff, n, nothing , Val (false ), callback = callback!)
349
+ nit = iterate (nb, ns)
350
+ return n => lv, (v, level, used_ag, nb, nit)
351
+ end
352
+ end
353
+ else
354
+ used_ag = true
355
+ if (_n = get (ag, v, nothing )) != = nothing
356
+ n = _n[2 ]
357
+ if ! visited[n]
358
+ n, lv = extreme_var (var_to_diff, n, level)
359
+ extreme_var (var_to_diff, n, nothing , Val (false ), callback = callback!)
360
+ return n => lv, (v, level, used_ag, nb, nit)
361
+ end
362
+ else
363
+ @goto TRYAGIN
364
+ end
365
+ end
366
+ visited[v] = true
367
+ (v′ = var_to_diff[v]) === nothing && return nothing
368
+ v:: Int = v′
369
+ level += 1
370
+ used_ag = false
371
+ end
372
+ end
373
+
374
+ Graphs. neighbors (iag:: InducedAliasGraph , v:: Integer ) = IAGNeighbors (iag, v)
375
+
333
376
count_nonzeros (a:: AbstractArray ) = count (! iszero, a)
334
377
335
378
# N.B.: Ordinarily sparse vectors allow zero stored elements.
0 commit comments