|
1 |
| -function partial_state_selection_graph!(state::TransformationState) |
2 |
| - find_solvables!(state; allow_symbolic = true) |
3 |
| - var_eq_matching = complete(pantelides!(state)) |
4 |
| - complete!(state.structure) |
5 |
| - partial_state_selection_graph!(state.structure, var_eq_matching) |
6 |
| -end |
7 |
| - |
8 |
| -function ascend_dg(xs, dg, level) |
9 |
| - while level > 0 |
10 |
| - xs = Int[dg[x] for x in xs] |
11 |
| - level -= 1 |
12 |
| - end |
13 |
| - return xs |
14 |
| -end |
15 |
| - |
16 |
| -function ascend_dg_all(xs, dg, level, maxlevel) |
17 |
| - r = Int[] |
18 |
| - while true |
19 |
| - if level <= 0 |
20 |
| - append!(r, xs) |
21 |
| - end |
22 |
| - maxlevel <= 0 && break |
23 |
| - xs = Int[dg[x] for x in xs if dg[x] !== nothing] |
24 |
| - level -= 1 |
25 |
| - maxlevel -= 1 |
26 |
| - end |
27 |
| - return r |
28 |
| -end |
29 |
| - |
30 |
| -function pss_graph_modia!(structure::SystemStructure, maximal_top_matching, varlevel, |
31 |
| - inv_varlevel, inv_eqlevel) |
32 |
| - @unpack eq_to_diff, var_to_diff, graph, solvable_graph = structure |
33 |
| - |
34 |
| - # var_eq_matching is a maximal matching on the top-differentiated variables. |
35 |
| - # Find Strongly connected components. Note that after pantelides, we expect |
36 |
| - # a balanced system, so a maximal matching should be possible. |
37 |
| - var_sccs::Vector{Union{Vector{Int}, Int}} = find_var_sccs(graph, maximal_top_matching) |
38 |
| - var_eq_matching = Matching{Union{Unassigned, SelectedState}}(ndsts(graph)) |
39 |
| - for vars in var_sccs |
40 |
| - # TODO: We should have a way to not have the scc code look at unassigned vars. |
41 |
| - if length(vars) == 1 && maximal_top_matching[vars[1]] === unassigned |
42 |
| - continue |
43 |
| - end |
44 |
| - |
45 |
| - # Now proceed level by level from lowest to highest and tear the graph. |
46 |
| - eqs = [maximal_top_matching[var] |
47 |
| - for var in vars if maximal_top_matching[var] !== unassigned] |
48 |
| - isempty(eqs) && continue |
49 |
| - maxeqlevel = maximum(map(x -> inv_eqlevel[x], eqs)) |
50 |
| - maxvarlevel = level = maximum(map(x -> inv_varlevel[x], vars)) |
51 |
| - old_level_vars = () |
52 |
| - ict = IncrementalCycleTracker( |
53 |
| - DiCMOBiGraph{true}(graph, |
54 |
| - complete(Matching(ndsts(graph)), nsrcs(graph))), |
55 |
| - dir = :in) |
56 |
| - |
57 |
| - while level >= 0 |
58 |
| - to_tear_eqs_toplevel = filter(eq -> inv_eqlevel[eq] >= level, eqs) |
59 |
| - to_tear_eqs = ascend_dg(to_tear_eqs_toplevel, invview(eq_to_diff), level) |
60 |
| - |
61 |
| - to_tear_vars_toplevel = filter(var -> inv_varlevel[var] >= level, vars) |
62 |
| - to_tear_vars = ascend_dg(to_tear_vars_toplevel, invview(var_to_diff), level) |
63 |
| - |
64 |
| - assigned_eqs = Int[] |
65 |
| - |
66 |
| - if old_level_vars !== () |
67 |
| - # Inherit constraints from previous level. |
68 |
| - # TODO: Is this actually a good idea or do we want full freedom |
69 |
| - # to tear differently on each level? Does it make a difference |
70 |
| - # whether we're using heuristic or optimal tearing? |
71 |
| - removed_eqs = Int[] |
72 |
| - removed_vars = Int[] |
73 |
| - for var in old_level_vars |
74 |
| - old_assign = var_eq_matching[var] |
75 |
| - if isa(old_assign, SelectedState) |
76 |
| - push!(removed_vars, var) |
77 |
| - continue |
78 |
| - elseif !isa(old_assign, Int) || |
79 |
| - ict.graph.matching[var_to_diff[var]] !== unassigned |
80 |
| - continue |
81 |
| - end |
82 |
| - # Make sure the ict knows about this edge, so it doesn't accidentally introduce |
83 |
| - # a cycle. |
84 |
| - assgned_eq = eq_to_diff[old_assign] |
85 |
| - ok = try_assign_eq!(ict, var_to_diff[var], assgned_eq) |
86 |
| - @assert ok |
87 |
| - var_eq_matching[var_to_diff[var]] = assgned_eq |
88 |
| - push!(removed_eqs, eq_to_diff[ict.graph.matching[var]]) |
89 |
| - push!(removed_vars, var_to_diff[var]) |
90 |
| - push!(removed_vars, var) |
91 |
| - end |
92 |
| - to_tear_eqs = setdiff(to_tear_eqs, removed_eqs) |
93 |
| - to_tear_vars = setdiff(to_tear_vars, removed_vars) |
94 |
| - end |
95 |
| - tearEquations!(ict, solvable_graph.fadjlist, to_tear_eqs, BitSet(to_tear_vars), |
96 |
| - nothing) |
97 |
| - |
98 |
| - for var in to_tear_vars |
99 |
| - @assert var_eq_matching[var] === unassigned |
100 |
| - assgned_eq = ict.graph.matching[var] |
101 |
| - var_eq_matching[var] = assgned_eq |
102 |
| - isa(assgned_eq, Int) && push!(assigned_eqs, assgned_eq) |
103 |
| - end |
104 |
| - |
105 |
| - if level != 0 |
106 |
| - remaining_vars = collect(v |
107 |
| - for v in to_tear_vars |
108 |
| - if var_eq_matching[v] === unassigned) |
109 |
| - if !isempty(remaining_vars) |
110 |
| - remaining_eqs = setdiff(to_tear_eqs, assigned_eqs) |
111 |
| - nlsolve_matching = maximal_matching(graph, |
112 |
| - Base.Fix2(in, remaining_eqs), |
113 |
| - Base.Fix2(in, remaining_vars)) |
114 |
| - for var in remaining_vars |
115 |
| - if nlsolve_matching[var] === unassigned && |
116 |
| - var_eq_matching[var] === unassigned |
117 |
| - var_eq_matching[var] = SelectedState() |
118 |
| - end |
119 |
| - end |
120 |
| - end |
121 |
| - end |
122 |
| - |
123 |
| - old_level_vars = to_tear_vars |
124 |
| - level -= 1 |
125 |
| - end |
126 |
| - end |
127 |
| - return complete(var_eq_matching, nsrcs(graph)) |
128 |
| -end |
129 |
| - |
130 | 1 | struct SelectedState end
|
131 |
| -function partial_state_selection_graph!(structure::SystemStructure, var_eq_matching) |
132 |
| - @unpack eq_to_diff, var_to_diff, graph, solvable_graph = structure |
133 |
| - eq_to_diff = complete(eq_to_diff) |
134 |
| - |
135 |
| - inv_eqlevel = map(1:nsrcs(graph)) do eq |
136 |
| - level = 0 |
137 |
| - while invview(eq_to_diff)[eq] !== nothing |
138 |
| - eq = invview(eq_to_diff)[eq] |
139 |
| - level += 1 |
140 |
| - end |
141 |
| - level |
142 |
| - end |
143 |
| - |
144 |
| - varlevel = map(1:ndsts(graph)) do var |
145 |
| - graph_level = level = 0 |
146 |
| - while var_to_diff[var] !== nothing |
147 |
| - var = var_to_diff[var] |
148 |
| - level += 1 |
149 |
| - if !isempty(𝑑neighbors(graph, var)) |
150 |
| - graph_level = level |
151 |
| - end |
152 |
| - end |
153 |
| - graph_level |
154 |
| - end |
155 |
| - |
156 |
| - inv_varlevel = map(1:ndsts(graph)) do var |
157 |
| - level = 0 |
158 |
| - while invview(var_to_diff)[var] !== nothing |
159 |
| - var = invview(var_to_diff)[var] |
160 |
| - level += 1 |
161 |
| - end |
162 |
| - level |
163 |
| - end |
164 |
| - |
165 |
| - var_eq_matching = pss_graph_modia!(structure, |
166 |
| - complete(var_eq_matching), varlevel, inv_varlevel, |
167 |
| - inv_eqlevel) |
168 |
| - |
169 |
| - var_eq_matching |
170 |
| -end |
171 | 2 |
|
172 | 3 | function dummy_derivative_graph!(state::TransformationState, jac = nothing;
|
173 | 4 | state_priority = nothing, log = Val(false), kwargs...)
|
@@ -343,11 +174,7 @@ function dummy_derivative_graph!(
|
343 | 174 | end
|
344 | 175 |
|
345 | 176 | ret = tearing_with_dummy_derivatives(structure, BitSet(dummy_derivatives))
|
346 |
| - if log |
347 |
| - (ret..., DummyDerivativeSummary(var_dummy_scc, var_state_priority)) |
348 |
| - else |
349 |
| - ret[1] |
350 |
| - end |
| 177 | + (ret..., DummyDerivativeSummary(var_dummy_scc, var_state_priority)) |
351 | 178 | end
|
352 | 179 |
|
353 | 180 | function is_present(structure, v)::Bool
|
|
0 commit comments