|
16 | 16 | # For debug purposes
|
17 | 17 | function aag_bareiss(sys::AbstractSystem)
|
18 | 18 | state = TearingState(sys)
|
| 19 | + complete!(state.structure) |
19 | 20 | mm = linear_subsys_adjmat(state)
|
20 |
| - return aag_bareiss!(state.structure.graph, complete(state.structure.var_to_diff), mm) |
| 21 | + return aag_bareiss!(state.structure.graph, state.structure.var_to_diff, mm) |
21 | 22 | end
|
22 | 23 |
|
23 | 24 | function extreme_var(var_to_diff, v, level = nothing, ::Val{descend} = Val(true);
|
@@ -441,8 +442,6 @@ function aag_bareiss!(graph, var_to_diff, mm_orig::SparseMatrixCLIL, irreducible
|
441 | 442 | for v in irreducibles
|
442 | 443 | is_reducible[v] = false
|
443 | 444 | end
|
444 |
| - # TODO/FIXME: This needs a proper recursion to compute the transitive |
445 |
| - # closure. |
446 | 445 | is_linear_variables = find_linear_variables(graph, linear_equations, var_to_diff,
|
447 | 446 | irreducibles)
|
448 | 447 | solvable_variables = findall(is_linear_variables)
|
@@ -652,16 +651,51 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
|
652 | 651 | end
|
653 | 652 | end
|
654 | 653 | end
|
| 654 | + # If a non-differentiated variable equals to 0, then we can eliminate |
| 655 | + # the whole differentiation chain. Otherwise, we can have to keep the |
| 656 | + # lowest differentiate variable in the differentiation chain. |
| 657 | + # E.g. |
| 658 | + # ``` |
| 659 | + # D(x) ~ 0 |
| 660 | + # D(D(x)) ~ y |
| 661 | + # ``` |
| 662 | + # reduces to |
| 663 | + # ``` |
| 664 | + # D(x) ~ 0 |
| 665 | + # y := 0 |
| 666 | + # ``` |
| 667 | + # but |
| 668 | + # ``` |
| 669 | + # x ~ 0 |
| 670 | + # D(x) ~ y |
| 671 | + # ``` |
| 672 | + # reduces to |
| 673 | + # ``` |
| 674 | + # x := 0 |
| 675 | + # y := 0 |
| 676 | + # ``` |
| 677 | + zero_vars_set = BitSet() |
655 | 678 | for v in zero_vars
|
656 | 679 | for a in Iterators.flatten((v, outneighbors(eqg, v)))
|
657 | 680 | while true
|
658 |
| - dag[a] = 0 |
659 |
| - da = var_to_diff[a] |
660 |
| - da === nothing && break |
661 |
| - a = da |
| 681 | + push!(zero_vars_set, a) |
| 682 | + a = var_to_diff[a] |
| 683 | + a === nothing && break |
662 | 684 | end
|
663 | 685 | end
|
664 | 686 | end
|
| 687 | + for v in zero_vars_set |
| 688 | + while (iv = diff_to_var[v]) in zero_vars_set |
| 689 | + v = iv |
| 690 | + end |
| 691 | + if diff_to_var[v] === nothing # `v` is reducible |
| 692 | + dag[v] = 0 |
| 693 | + end |
| 694 | + # reducible after v |
| 695 | + while (v = var_to_diff[v]) !== nothing |
| 696 | + dag[v] = 0 |
| 697 | + end |
| 698 | + end |
665 | 699 |
|
666 | 700 | # clean up
|
667 | 701 | for v in dls.visited
|
@@ -715,10 +749,17 @@ function alias_eliminate_graph!(graph, var_to_diff, mm_orig::SparseMatrixCLIL)
|
715 | 749 | end
|
716 | 750 | update_graph_neighbors!(graph, ag)
|
717 | 751 | finalag = AliasGraph(nvars)
|
718 |
| - # RHS must still exist in the system to be valid aliases. |
| 752 | + # RHS or its derivaitves must still exist in the system to be valid aliases. |
719 | 753 | needs_update = false
|
| 754 | + function contains_v_or_dv(var_to_diff, graph, v) |
| 755 | + while true |
| 756 | + isempty(𝑑neighbors(graph, v)) || return true |
| 757 | + v = var_to_diff[v] |
| 758 | + v === nothing && return false |
| 759 | + end |
| 760 | + end |
720 | 761 | for (v, (c, a)) in ag
|
721 |
| - if iszero(a) || !isempty(𝑑neighbors(graph, a)) |
| 762 | + if iszero(a) || contains_v_or_dv(var_to_diff, graph, a) |
722 | 763 | finalag[v] = c => a
|
723 | 764 | else
|
724 | 765 | needs_update = true
|
|
0 commit comments