@@ -69,6 +69,86 @@ function pantelides_reassemble(state::TearingState, var_eq_matching)
69
69
return sys
70
70
end
71
71
72
+ """
73
+ computed_highest_diff_variables(var_to_diff, ag)
74
+
75
+ Computes which variables are the "highest-differentiated" for purposes of
76
+ pantelides. Ordinarily this is relatively straightforward. However, in our
77
+ case, there are two complicating conditions:
78
+
79
+ 1. We allow variables in the structure graph that don't appear in the
80
+ system at all. What we are interested in is the highest-differentiated
81
+ variable that actually appears in the system.
82
+
83
+ 2. We have an alias graph. The alias graph implicitly contributes an
84
+ alias equation, so it doesn't actually whitelist any additional variables,
85
+ but it may change which variable is considered the highest differentiated one.
86
+ Consider the following situation:
87
+
88
+ Vars: x, y
89
+ Eqs: 0 = f(x)
90
+ Alias: ẋ = ẏ
91
+
92
+ In the absence of the alias, we would consider `x` to be the highest
93
+ differentiated variable. However, because of the alias (and because there
94
+ is no alias for `x=y`), we actually need to take `ẋ` as the highest
95
+ differentiated variable.
96
+
97
+ This function takes care of these complications are returns a boolean array
98
+ for every variable, indicating whether it is considered "highest-differentiated".
99
+ """
100
+ function computed_highest_diff_variables (structure, ag:: Union{AliasGraph, Nothing} )
101
+ @unpack graph, var_to_diff = structure
102
+
103
+ nvars = length (var_to_diff)
104
+ varwhitelist = falses (nvars)
105
+ for var in 1 : nvars
106
+ if var_to_diff[var] === nothing && ! varwhitelist[var]
107
+ while isempty (𝑑neighbors (graph, var)) && (ag === nothing || ! haskey (ag, var))
108
+ var′ = invview (var_to_diff)[var]
109
+ var′ === nothing && break
110
+ var = var′
111
+ end
112
+ if ag != = nothing && haskey (ag, var)
113
+ (_, stem) = ag[var]
114
+ stem == 0 && continue
115
+ # Ascend the stem
116
+ while isempty (𝑑neighbors (graph, var))
117
+ var′ = invview (var_to_diff)[var]
118
+ var′ === nothing && break
119
+ stem′ = invview (var_to_diff)[var]
120
+ # Invariant from alias elimination: Stem is chosen to have
121
+ # the highest differentiation order.
122
+ @assert stem′ != = nothing
123
+ if ! haskey (ag, var′) || ag[var′][2 ] != stem′
124
+ varwhitelist[stem] = true
125
+ break
126
+ end
127
+ stem = stem′
128
+ var = var′
129
+ end
130
+ else
131
+ varwhitelist[var] = true
132
+ end
133
+ end
134
+ end
135
+
136
+ # Remove any variables from the varwhitelist for whom a higher-differentiated
137
+ # var is already on the whitelist
138
+ for var in 1 : nvars
139
+ varwhitelist[var] || continue
140
+ var′ = var
141
+ while (var′ = var_to_diff[var′]) != = nothing
142
+ if varwhitelist[var′]
143
+ varwhitelist[var] = false
144
+ break
145
+ end
146
+ end
147
+ end
148
+
149
+ return varwhitelist
150
+ end
151
+
72
152
"""
73
153
pantelides!(state::TransformationState; kwargs...)
74
154
@@ -86,27 +166,7 @@ function pantelides!(state::TransformationState, ag::Union{AliasGraph, Nothing}
86
166
nnonemptyeqs = count (eq -> ! isempty (𝑠neighbors (graph, eq)) && eq_to_diff[eq] === nothing ,
87
167
1 : neqs′)
88
168
89
- # Allow matching for the highest differentiated variable that
90
- # currently appears in an equation (or implicit equation in a side ag)
91
- varwhitelist = falses (nvars)
92
- for var in 1 : nvars
93
- if var_to_diff[var] === nothing && ! varwhitelist[var]
94
- while isempty (𝑑neighbors (graph, var)) && (ag === nothing || ! haskey (ag, var))
95
- var′ = invview (var_to_diff)[var]
96
- var′ === nothing && break
97
- var = var′
98
- end
99
- if ! isempty (𝑑neighbors (graph, var))
100
- if ag != = nothing && haskey (ag, var)
101
- # TODO : remove lower diff vars from whitelist
102
- c, a = ag[var]
103
- iszero (c) || (varwhitelist[a] = true )
104
- else
105
- varwhitelist[var] = true
106
- end
107
- end
108
- end
109
- end
169
+ varwhitelist = computed_highest_diff_variables (state. structure, ag)
110
170
111
171
if nnonemptyeqs > count (varwhitelist)
112
172
throw (InvalidSystemException (" System is structurally singular" ))
0 commit comments