@@ -501,7 +501,6 @@ count_nonzeros(a::SparseVector) = nnz(a)
501
501
# linear variables. Also, if a variable's any derivaitves is nonlinear, then all
502
502
# of them are not linear variables.
503
503
function find_linear_variables (graph, linear_equations, var_to_diff, irreducibles)
504
- fullvars = Main. _state[]. fullvars
505
504
stack = Int[]
506
505
linear_variables = falses (length (var_to_diff))
507
506
var_to_lineq = Dict {Int, BitSet} ()
@@ -516,7 +515,6 @@ function find_linear_variables(graph, linear_equations, var_to_diff, irreducible
516
515
eqs === nothing && continue
517
516
for eq in eqs, v′ in 𝑠neighbors (graph, eq)
518
517
if linear_variables[v′]
519
- @show v′, fullvars[v′]
520
518
linear_variables[v′] = false
521
519
push! (stack, v′)
522
520
end
@@ -738,6 +736,7 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
738
736
processed = falses (nvars)
739
737
iag = InducedAliasGraph (ag, invag, var_to_diff)
740
738
newag = AliasGraph (nvars)
739
+ newinvag = SimpleDiGraph (nvars)
741
740
irreducibles = BitSet ()
742
741
updated_diff_vars = Int[]
743
742
for (v, dv) in enumerate (var_to_diff)
@@ -754,14 +753,16 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
754
753
nlevels = length (level_to_var)
755
754
current_coeff_level = Ref ((0 , 0 ))
756
755
add_alias! = let current_coeff_level = current_coeff_level,
757
- level_to_var = level_to_var, newag = newag, processed = processed
756
+ level_to_var = level_to_var, newag = newag, newinvag = newinvag,
757
+ processed = processed
758
758
759
759
v -> begin
760
760
coeff, level = current_coeff_level[]
761
761
if level + 1 <= length (level_to_var)
762
762
av = level_to_var[level + 1 ]
763
763
if v != av # if the level_to_var isn't from the root branch
764
764
newag[v] = coeff => av
765
+ add_edge! (newinvag, av, v)
765
766
end
766
767
else
767
768
@assert length (level_to_var) == level
@@ -792,44 +793,48 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
792
793
set_v_zero! = let newag = newag
793
794
v -> newag[v] = 0
794
795
end
796
+ len = length (level_to_var)
795
797
for (i, v) in enumerate (level_to_var)
796
798
_alias = get (ag, v, nothing )
797
799
798
800
# if a chain starts to equal to zero, then all its descendants must
799
801
# be zero and reducible
800
802
if _alias != = nothing && iszero (_alias[1 ])
801
- if i < length (level_to_var)
803
+ if i < len
802
804
# we have `x = 0`
803
805
v = level_to_var[i + 1 ]
804
806
extreme_var (var_to_diff, v, nothing , Val (false ), callback = set_v_zero!)
805
807
end
806
808
break
807
809
end
808
810
809
- v_eqs = 𝑑neighbors (graph, v)
810
- # if an irreducible appears in only one equation, we need to make
811
- # sure that the other variables don't get eliminated
812
- if length (v_eqs) == 1
813
- eq = v_eqs[1 ]
814
- for av in 𝑠neighbors (graph, eq)
811
+ # all non-highest order differentiated variables are reducible.
812
+ if i == len
813
+ # if an irreducible alias appears in only one equation, then
814
+ # it's actually not an alias, but a proper equation. E.g.
815
+ # D(D(phi)) = a
816
+ # D(phi) = sin(t)
817
+ # `a` and `D(D(phi))` are not irreducible state.
818
+ push! (irreducibles, v)
819
+ for av in neighbors (newinvag, v)
820
+ newag[av] = nothing
815
821
push! (irreducibles, av)
816
822
end
817
- ag[v] = nothing
818
823
end
819
- push! (irreducibles, v)
820
824
end
821
- if nlevels < (new_nlevels = length (level_to_var))
822
- for i in (nlevels + 1 ): new_nlevels
825
+ if nlevels < len
826
+ for i in (nlevels + 1 ): len
823
827
li = level_to_var[i]
824
828
var_to_diff[level_to_var[i - 1 ]] = li
825
829
push! (updated_diff_vars, level_to_var[i - 1 ])
826
830
end
827
831
end
828
832
end
829
- for (v, (c, a)) in ag
833
+ for (v, (c, a)) in newag
830
834
a = a == 0 ? 0 : c * fullvars[a]
831
835
@info " differential aliases" fullvars[v] => a
832
836
end
837
+ @show fullvars[collect (irreducibles)]
833
838
834
839
if ! isempty (irreducibles)
835
840
ag = newag
0 commit comments