@@ -497,12 +497,76 @@ count_nonzeros(a::AbstractArray) = count(!iszero, a)
497
497
# Here we have a guarantee that they won't, so we can make this identification
498
498
count_nonzeros (a:: SparseVector ) = nnz (a)
499
499
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
+
500
567
function aag_bareiss! (graph, var_to_diff, mm_orig:: SparseMatrixCLIL , irreducibles = ())
501
568
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
506
570
507
571
# If linear highest differentiated variables cannot be assigned to a pivot,
508
572
# 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
513
577
# For all the other variables, we can update the original system with
514
578
# Bareiss'ed coefficients as Gaussian elimination is nullspace perserving
515
579
# and we are only working on linear homogeneous subsystem.
516
- is_linear_variables = isnothing .(var_to_diff)
517
580
is_reducible = trues (length (var_to_diff))
518
581
for v in irreducibles
519
- is_linear_variables[v] = false
520
582
is_reducible[v] = false
521
583
end
522
584
# TODO /FIXME : This needs a proper recursion to compute the transitive
523
585
# 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)
540
587
solvable_variables = findall (is_linear_variables)
541
588
542
589
function do_bareiss! (M, Mold = nothing )
0 commit comments