@@ -27,9 +27,9 @@ function substitute_aliases(diffeqs, dict)
27
27
lhss (diffeqs) .~ fixpoint_sub .(rhss (diffeqs), (dict,))
28
28
end
29
29
30
- isvar (s:: Sym ) = ! isparameter (s)
31
- isvar (s:: Term ) = isvar (s. op)
32
- isvar (s:: Any ) = false
30
+ isvar (s:: Sym ; param = false ) = param ? true : ! isparameter (s)
31
+ isvar (s:: Term ; param = false ) = isvar (s. op; param = param )
32
+ isvar (s:: Any ;param = false ) = false
33
33
34
34
function filterexpr (f, s)
35
35
vs = []
@@ -84,15 +84,15 @@ function alias_elimination(sys::ODESystem)
84
84
end
85
85
86
86
function get_α_x (αx)
87
- if isvar (αx)
88
- return αx, 1
87
+ if isvar (αx, param = true )
88
+ return 1 , αx
89
89
elseif αx isa Term && operation (αx) === (* )
90
90
args = arguments (αx)
91
91
nums = filter (! isvar, args)
92
92
syms = filter (isvar, args)
93
93
94
94
if length (syms) == 1
95
- return syms[ 1 ], prod (nums)
95
+ return prod (nums), syms[ 1 ]
96
96
end
97
97
else
98
98
return nothing
@@ -105,51 +105,68 @@ function alias_elimination2(sys)
105
105
subs = Pair[]
106
106
# Case 1: Right hand side is a constant
107
107
ii = findall (eqs) do eq
108
- (eq . lhs isa Sym || (eq . lhs isa Term && ! (eq . lhs . op isa Differential))) && ! (eq. rhs isa Symbolic)
108
+ ! (eq. rhs isa Symbolic)
109
109
end
110
110
for eq in eqs[ii]
111
- substitution_dict[eq . lhs] = eq. rhs
112
- push! (subs, eq . lhs => eq. rhs)
111
+ α,x = get_α_x ( eq. lhs)
112
+ push! (subs, x => isone (α) ? eq. rhs : eq . rhs / α )
113
113
end
114
114
deleteat! (eqs, ii) # remove them
115
115
116
116
# Case 2: One side is a differentiated var, the other is an algebraic var
117
117
# substitute the algebraic var with the diff var
118
- diff_vars = findall (eqs) do eq
119
- if eq. lhs isa Term && eq. lhs. op isa Differential
120
- eq. lhs. args[1 ]
121
- else
122
- nothing
123
- end
124
- end
118
+ diff_vars = filter ( ! isnothing, map (eqs) do eq
119
+ if eq. lhs isa Term && eq. lhs. op isa Differential
120
+ eq. lhs. args[1 ]
121
+ else
122
+ nothing
123
+ end
124
+ end ) |> Set
125
125
126
- for eq in eqs
126
+ del = Int[]
127
+ for (i, eq) in enumerate (eqs)
127
128
res_left = get_α_x (eq. lhs)
128
- if ! isnothing (res)
129
+ if ! isnothing (res_left)
130
+ α, x = res_left
129
131
res_right = get_α_x (eq. rhs)
130
- β, y = res
131
- if y in diff_vars && ! (x in diff_vars)
132
- multiple = β / α
133
- push! (subs, x => isone (multiple) ? y : multiple * y)
134
- elseif x in diff_vars && ! (y in diff_vars)
135
- multiple = α / β
136
- push! (subs, y => isone (multiple) ? y : multiple * y)
132
+ if ! isnothing (res_right)
133
+ β, y = res_right
134
+ if y in diff_vars && ! (x in diff_vars)
135
+ multiple = β / α
136
+ push! (subs, x => isone (multiple) ? y : multiple * y)
137
+ push! (del, i)
138
+ elseif x in diff_vars && ! (y in diff_vars)
139
+ multiple = α / β
140
+ push! (subs, y => isone (multiple) ? x : multiple * x)
141
+ push! (del, i)
142
+ end
137
143
end
138
144
end
139
145
end
146
+ deleteat! (eqs, del)
140
147
141
148
# Case 3: Explicit substitutions
142
- for eq in eqs
149
+ del = Int[]
150
+ for (i, eq) in enumerate (eqs)
143
151
res_left = get_α_x (eq. lhs)
144
- if ! isnothing (res)
152
+ if ! isnothing (res_left)
153
+ α, x = res_left
145
154
res_right = get_α_x (eq. rhs)
146
- β, y = res
147
- multiple = β / α
148
- push! (subs, x => isone (multiple) ? x : multiple * x)
155
+ if ! isnothing (res_right)
156
+ β, y = res_right
157
+ multiple = β / α
158
+ push! (subs, x => _isone (multiple) ? x : multiple * x)
159
+ push! (del, i)
160
+ end
149
161
end
150
162
end
163
+ deleteat! (eqs, del)
151
164
152
165
diffeqs = filter (eq -> eq. lhs isa Term && eq. lhs. op isa Differential, eqs)
153
166
diffeqs′ = substitute_aliases (diffeqs, Dict (subs))
167
+
168
+ newstates = map (diffeqs) do eq
169
+ eq. lhs. args[1 ]
170
+ end
154
171
ODESystem (diffeqs′, sys. iv, newstates, parameters (sys), observed= first .(subs) .~ last .(subs))
155
172
end
0 commit comments