Skip to content

Commit 85fb196

Browse files
committed
alias elimination simplified
1 parent 46b95cc commit 85fb196

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

src/systems/reduction.jl

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,73 @@ function alias_elimination(sys::ODESystem)
8383
ODESystem(diffeqs′, sys.iv, newstates, parameters(sys), observed=eliminate .~ outputs)
8484
end
8585

86+
function get_α_x(αx)
87+
if isvar(αx)
88+
return αx, 1
89+
elseif αx isa Term && operation(αx) === (*)
90+
args = arguments(αx)
91+
nums = filter(!isvar, args)
92+
syms = filter(isvar, args)
93+
94+
if length(syms) == 1
95+
return syms[1], prod(nums)
96+
end
97+
else
98+
return nothing
99+
end
100+
end
101+
102+
function alias_elimination2(sys)
103+
eqs = vcat(equations(sys), observed(sys))
104+
105+
subs = Pair[]
106+
# Case 1: Right hand side is a constant
107+
ii = findall(eqs) do eq
108+
(eq.lhs isa Sym || (eq.lhs isa Term && !(eq.lhs.op isa Differential))) && !(eq.rhs isa Symbolic)
109+
end
110+
for eq in eqs[ii]
111+
substitution_dict[eq.lhs] = eq.rhs
112+
push!(subs, eq.lhs => eq.rhs)
113+
end
114+
deleteat!(eqs, ii) # remove them
115+
116+
# Case 2: One side is a differentiated var, the other is an algebraic var
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
125+
126+
for eq in eqs
127+
res_left = get_α_x(eq.lhs)
128+
if !isnothing(res)
129+
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)
137+
end
138+
end
139+
end
140+
141+
# Case 3: Explicit substitutions
142+
for eq in eqs
143+
res_left = get_α_x(eq.lhs)
144+
if !isnothing(res)
145+
res_right = get_α_x(eq.rhs)
146+
β, y = res
147+
multiple = β / α
148+
push!(subs, x => isone(multiple) ? x : multiple * x)
149+
end
150+
end
151+
152+
diffeqs = filter(eq -> eq.lhs isa Term && eq.lhs.op isa Differential, eqs)
153+
diffeqs′ = substitute_aliases(diffeqs, Dict(subs))
154+
ODESystem(diffeqs′, sys.iv, newstates, parameters(sys), observed=first.(subs) .~ last.(subs))
155+
end

0 commit comments

Comments
 (0)