@@ -19,56 +19,53 @@ 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 walk_to_root (ag, var_to_diff, v:: Integer )
23
- diff_to_var = invview (var_to_diff)
22
+ function extreme_var (var_to_diff, v, level = nothing , :: Val{descend} = Val (true )) where descend
23
+ g = descend ? invview (var_to_diff) : var_to_diff
24
+ while (v′ = g[v]) != = nothing
25
+ v = v′
26
+ if level != = nothing
27
+ descend ? (level -= 1 ) : (level += 1 )
28
+ end
29
+ end
30
+ level === nothing ? v : (v => level)
31
+ end
24
32
33
+ function neighbor_branches! (visited, (ag, invag), var_to_diff, v, level = 0 )
34
+ ns = Pair{Int, Int}[]
35
+ visited[v] && return ns
25
36
v′:: Union{Nothing, Int} = v
26
- @label HAS_BRANCH
37
+ diff_to_var = invview (var_to_diff)
27
38
while (v′ = diff_to_var[v]) != = nothing
28
39
v = v′
40
+ level -= 1
29
41
end
30
- # `v` is now not differentiated in the current chain.
31
- # Now we recursively walk to root variable's chain.
32
42
while true
33
- next_v = get (ag, v, nothing )
34
- next_v === nothing || (v = next_v[2 ]; @goto HAS_BRANCH)
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
35
51
(v′ = var_to_diff[v]) === nothing && break
36
52
v = v′
53
+ level += 1
37
54
end
38
-
39
- # Descend to the root from the chain
40
- while (v′ = diff_to_var[v]) != = nothing
41
- v = v′
42
- end
43
- v
55
+ ns
44
56
end
45
57
46
- function visit_differential_aliases! (ag, level_to_var, processed, invag, var_to_diff, v, level= 0 )
47
- processed[v] && return nothing
48
- for n in neighbors (invag, v)
49
- # TODO : we currently only handle `coeff == 1`
50
- if isone (ag[n][1 ])
51
- visit_differential_aliases! (ag, level_to_var, processed, invag, var_to_diff, n, level)
52
- end
53
- end
54
- # Note that we don't need to update `invag`
55
- if 1 <= level + 1 <= length (level_to_var)
56
- root_var = level_to_var[level + 1 ]
57
- if v != root_var
58
- ag[v] = 1 => root_var
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)
60
+ 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)
64
+ if min_var_level[2 ] > lv
65
+ min_var_level = x => lv
59
66
end
60
- else
61
- @assert length (level_to_var) == level
62
- push! (level_to_var, v)
63
67
end
64
- processed[v] = true
65
- if (dv = var_to_diff[v]) != = nothing
66
- visit_differential_aliases! (ag, level_to_var, processed, invag, var_to_diff, dv, level + 1 )
67
- end
68
- if (iv = invview (var_to_diff)[v]) != = nothing
69
- visit_differential_aliases! (ag, level_to_var, processed, invag, var_to_diff, iv, level - 1 )
70
- end
71
- return nothing
68
+ return extreme_var (var_to_diff, min_var_level... )
72
69
end
73
70
74
71
function alias_elimination (sys)
@@ -86,7 +83,7 @@ function alias_elimination(sys)
86
83
# ⇓ ⇑
87
84
# ⇓ x_t --> D(x_t)
88
85
# ⇓ |---------------|
89
- # z --> D(z) --> D(D(z)) |--> D(D(D(z))) |
86
+ # z --> D(z) --> D(D(z)) |--> D(D(D(z))) |
90
87
# ⇑ |---------------|
91
88
# k --> D(k)
92
89
#
@@ -102,26 +99,38 @@ function alias_elimination(sys)
102
99
# with a tie breaking strategy. The root variable (in this case `z`) is
103
100
# always uniquely determined. Thus, the result is well-defined.
104
101
D = has_iv (sys) ? Differential (get_iv (sys)) : nothing
102
+ nvars = length (fullvars)
105
103
diff_to_var = invview (var_to_diff)
106
- invag = SimpleDiGraph (length (fullvars) )
104
+ invag = SimpleDiGraph (nvars )
107
105
for (v, (coeff, alias)) in pairs (ag)
108
106
iszero (coeff) && continue
109
107
add_edge! (invag, alias, v)
110
108
end
111
- processed = falses (length (var_to_diff))
109
+ Main. _a[] = ag, invag
110
+ processed = falses (nvars)
111
+ visited = falses (nvars)
112
+ newag = AliasGraph (nvars)
112
113
for (v, dv) in enumerate (var_to_diff)
113
114
processed[v] && continue
114
115
(dv === nothing && diff_to_var[v] === nothing ) && continue
115
116
116
- r = walk_to_root (ag, var_to_diff, v)
117
+ # TODO : use an iterator, and get a relative level vector for `processed`
118
+ # variabels.
119
+ r, lv = walk_to_root! (processed, (ag, invag), var_to_diff, v)
120
+ # lv = extreme_var(var_to_diff, v, -lv, Val(false))
121
+ lv′ = extreme_var (var_to_diff, v, 0 , Val (false ))[2 ]
122
+ let
123
+ sv = fullvars[v]
124
+ root = fullvars[r]
125
+ @warn " " sv => root level = lv levelv = lv′
126
+ end
117
127
level_to_var = Int[r]
118
128
v′′:: Union{Nothing, Int} = v′:: Int = r
119
129
while (v′′ = var_to_diff[v′]) != = nothing
120
130
v′ = v′′
121
131
push! (level_to_var, v′)
122
132
end
123
133
nlevels = length (level_to_var)
124
- visit_differential_aliases! (ag, level_to_var, processed, invag, var_to_diff, r)
125
134
if nlevels < (new_nlevels = length (level_to_var))
126
135
@assert ! (D isa Nothing)
127
136
for i in (nlevels + 1 ): new_nlevels
@@ -502,6 +511,7 @@ function locally_structure_simplify!(adj_row, pivot_var, ag, var_to_diff)
502
511
if alias_candidate isa Pair
503
512
alias_val, alias_var = alias_candidate
504
513
# preferred_var = pivot_var
514
+ #=
505
515
switch = false # we prefer `alias_var` by default, unless we switch
506
516
diff_to_var = invview(var_to_diff)
507
517
pivot_var′′::Union{Nothing, Int} = pivot_var′::Int = pivot_var
@@ -525,6 +535,7 @@ function locally_structure_simplify!(adj_row, pivot_var, ag, var_to_diff)
525
535
pivot_var, alias_var = alias_var, pivot_var
526
536
pivot_val, alias_val = alias_val, pivot_val
527
537
end
538
+ =#
528
539
529
540
# `p` is the pivot variable, `a` is the alias variable, `v` and `c` are
530
541
# their coefficients.
0 commit comments