Skip to content

Commit bd143a5

Browse files
committed
Add find_linear_variables
1 parent 9297318 commit bd143a5

File tree

1 file changed

+69
-22
lines changed

1 file changed

+69
-22
lines changed

src/systems/alias_elimination.jl

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -497,12 +497,76 @@ count_nonzeros(a::AbstractArray) = count(!iszero, a)
497497
# Here we have a guarantee that they won't, so we can make this identification
498498
count_nonzeros(a::SparseVector) = nnz(a)
499499

500+
# Linear variables are variables that only appear in linear equations with only
501+
# linear variables. Also, if a variable's any derivaitves is nonlinear, then all
502+
# of them are not linear variables.
503+
function find_linear_variables(graph, linear_equations, var_to_diff, irreducibles)
504+
fullvars = Main._state[].fullvars
505+
stack = Int[]
506+
linear_variables = falses(length(var_to_diff))
507+
var_to_lineq = Dict{Int, BitSet}()
508+
mark_not_linear! = let linear_variables = linear_variables, stack = stack,
509+
var_to_lineq = var_to_lineq
510+
v -> begin
511+
linear_variables[v] = false
512+
push!(stack, v)
513+
while !isempty(stack)
514+
v = pop!(stack)
515+
eqs = get(var_to_lineq, v, nothing)
516+
eqs === nothing && continue
517+
for eq in eqs, v′ in 𝑠neighbors(graph, eq)
518+
if linear_variables[v′]
519+
@show v′, fullvars[v′]
520+
linear_variables[v′] = false
521+
push!(stack, v′)
522+
end
523+
end
524+
end
525+
end
526+
end
527+
for eq in linear_equations, v in 𝑠neighbors(graph, eq)
528+
linear_variables[v] = true
529+
vlineqs = get!(()->BitSet(), var_to_lineq, v)
530+
push!(vlineqs, eq)
531+
end
532+
for v in irreducibles
533+
lv = extreme_var(var_to_diff, v)
534+
while true
535+
mark_not_linear!(lv)
536+
lv = var_to_diff[lv]
537+
lv === nothing && break
538+
end
539+
end
540+
541+
linear_equations_set = BitSet(linear_equations)
542+
for (v, islinear) in enumerate(linear_variables)
543+
islinear || continue
544+
lv = extreme_var(var_to_diff, v)
545+
oldlv = lv
546+
remove = false
547+
while true
548+
for eq in 𝑑neighbors(graph, lv)
549+
if !(eq in linear_equations_set)
550+
remove = true
551+
end
552+
end
553+
lv = var_to_diff[lv]
554+
lv === nothing && break
555+
end
556+
lv = oldlv
557+
remove && while true
558+
mark_not_linear!(lv)
559+
lv = var_to_diff[lv]
560+
lv === nothing && break
561+
end
562+
end
563+
564+
return linear_variables
565+
end
566+
500567
function aag_bareiss!(graph, var_to_diff, mm_orig::SparseMatrixCLIL, irreducibles = ())
501568
mm = copy(mm_orig)
502-
is_linear_equations = falses(size(AsSubMatrix(mm_orig), 1))
503-
for e in mm_orig.nzrows
504-
is_linear_equations[e] = true
505-
end
569+
linear_equations = mm_orig.nzrows
506570

507571
# If linear highest differentiated variables cannot be assigned to a pivot,
508572
# then we can set it to zero. We use `rank1` to track this.
@@ -513,30 +577,13 @@ function aag_bareiss!(graph, var_to_diff, mm_orig::SparseMatrixCLIL, irreducible
513577
# For all the other variables, we can update the original system with
514578
# Bareiss'ed coefficients as Gaussian elimination is nullspace perserving
515579
# and we are only working on linear homogeneous subsystem.
516-
is_linear_variables = isnothing.(var_to_diff)
517580
is_reducible = trues(length(var_to_diff))
518581
for v in irreducibles
519-
is_linear_variables[v] = false
520582
is_reducible[v] = false
521583
end
522584
# TODO/FIXME: This needs a proper recursion to compute the transitive
523585
# closure.
524-
@label restart
525-
for i in 𝑠vertices(graph)
526-
is_linear_equations[i] && continue
527-
# This needs recursion
528-
for j in 𝑠neighbors(graph, i)
529-
if is_linear_variables[j]
530-
is_linear_variables[j] = false
531-
for k in 𝑑neighbors(graph, j)
532-
if is_linear_equations[k]
533-
is_linear_equations[k] = false
534-
@goto restart
535-
end
536-
end
537-
end
538-
end
539-
end
586+
is_linear_variables = find_linear_variables(graph, linear_equations, var_to_diff, irreducibles)
540587
solvable_variables = findall(is_linear_variables)
541588

542589
function do_bareiss!(M, Mold = nothing)

0 commit comments

Comments
 (0)