Skip to content

Commit ad15802

Browse files
substitute using SymbolicUtils
Fixes #339 MWE: ```julia using ModelingToolkit @parameters α β γ δ s = α => γ expr = (((1 / β - 1) + δ) / α) ^ (1 / (α - 1)) ModelingToolkit.substitute(expr, s) new = (((1 / β - 1) + δ) / γ) ^ (1 / (γ - 1)) isequal(expr, new) ```
1 parent 2d9e975 commit ad15802

File tree

7 files changed

+46
-27
lines changed

7 files changed

+46
-27
lines changed

src/ModelingToolkit.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import GeneralizedGenerated
1313
using DocStringExtensions
1414
using Base: RefValue
1515

16+
import SymbolicUtils
17+
import SymbolicUtils: to_symbolic, FnType, simplify
18+
1619
import TreeViews
1720

1821
"""
@@ -112,17 +115,18 @@ export Reaction, ReactionSystem
112115
export Differential, expand_derivatives, @derivatives
113116
export IntervalDomain, ProductDomain, , CircleDomain
114117
export Equation, ConstrainedEquation
115-
export simplify_constants
116-
117118
export Operation, Expression, Variable
119+
export independent_variable, states, parameters, equations
120+
118121
export calculate_jacobian, generate_jacobian, generate_function
119122
export calculate_tgrad, generate_tgrad
120123
export calculate_gradient, generate_gradient
121124
export calculate_factorized_W, generate_factorized_W
122125
export calculate_hessian, generate_hessian
123126
export calculate_massmatrix, generate_diffusion_function
124-
export independent_variable, states, parameters, equations
125-
export simplified_expr, rename, get_variables, substitute_expr!
127+
128+
export simplified_expr, rename, get_variables
129+
export simplify, substitute
126130
export build_function
127131
export @register
128132
export modelingtoolkitize

src/differentials.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ function expand_derivatives(O::Operation)
4949

5050
return sum(1:length(o.args)) do i
5151
derivative(o, i) * expand_derivatives(D(o.args[i]))
52-
end |> simplify_constants
52+
end |> simplify
5353
end
5454

55-
return simplify_constants(O)
55+
return simplify(O)
5656
end
5757
expand_derivatives(x) = x
5858

src/direct.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ an array of variable expressions.
88
"""
99
function gradient(O::Expression, vars::AbstractVector{<:Expression}; simplify = true)
1010
out = [expand_derivatives(Differential(v)(O)) for v in vars]
11-
simplify ? simplify_constants.(out) : out
11+
simplify ? simplify.(out) : out
1212
end
1313

1414
"""
@@ -21,7 +21,7 @@ an array of variable expressions.
2121
"""
2222
function jacobian(ops::AbstractVector{<:Expression}, vars::AbstractVector{<:Expression}; simplify = true)
2323
out = [expand_derivatives(Differential(v)(O)) for O in ops, v in vars]
24-
simplify ? simplify_constants.(out) : out
24+
simplify ? simplify.(out) : out
2525
end
2626

2727
"""
@@ -34,7 +34,7 @@ an array of variable expressions.
3434
"""
3535
function hessian(O::Expression, vars::AbstractVector{<:Expression}; simplify = true)
3636
out = [expand_derivatives(Differential(v2)(Differential(v1)(O))) for v1 in vars, v2 in vars]
37-
simplify ? simplify_constants.(out) : out
37+
simplify ? simplify.(out) : out
3838
end
3939

4040
function simplified_expr(O::Operation)

src/simplify.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import SymbolicUtils
2-
import SymbolicUtils: FnType
3-
41
# ModelingToolkit -> SymbolicUtils
52
SymbolicUtils.istree(x::Operation) = true
63
function SymbolicUtils.operation(x::Operation)
@@ -38,10 +35,12 @@ SymbolicUtils.symtype(x::Expression) = Number
3835

3936
# SymbolicUtils -> ModelingToolkit
4037

41-
function simplify_constants(expr)
38+
function SymbolicUtils.simplify(expr::Expression)
4239
SymbolicUtils.simplify(expr) |> to_mtk
4340
end
4441

42+
@deprecate simplify_constants(ex) simplify(ex)
43+
4544
to_mtk(x) = x
4645
to_mtk(x::Number) = Constant(x)
4746
to_mtk(v::SymbolicUtils.Sym{T}) where {T} = Variable{T}(nameof(v))

src/systems/diffeqs/abstractodesystem.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ function calculate_factorized_W(sys::AbstractODESystem, simplify=true)
6969
Wfact = lu(W, Val(false), check=false).factors
7070

7171
if simplify
72-
Wfact = simplify_constants.(Wfact)
72+
Wfact = simplify.(Wfact)
7373
end
7474

7575
W_t = - LinearAlgebra.I/gam + jac
7676
Wfact_t = lu(W_t, Val(false), check=false).factors
7777
if simplify
78-
Wfact_t = simplify_constants.(Wfact_t)
78+
Wfact_t = simplify.(Wfact_t)
7979
end
8080
sys.Wfact[] = Wfact
8181
sys.Wfact_t[] = Wfact_t
@@ -113,7 +113,7 @@ function calculate_massmatrix(sys::AbstractODESystem, simplify=true)
113113
error("Only semi-explicit constant mass matrices are currently supported")
114114
end
115115
end
116-
M = simplify ? simplify_constants.(M) : M
116+
M = simplify ? simplify.(M) : M
117117
# M should only contain concrete numbers
118118
M = map(x->x isa Constant ? x.value : x, M)
119119
M == I ? I : M

src/utils.jl

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,32 @@ end
100100

101101
# variable substitution
102102
"""
103-
substitute_expr!(expr::Operation, s::Pair{Operation, Operation})
103+
substitute(expr::Operation, s::Pair{Operation, Operation})
104+
substitute(expr::Operation, s::Dict{Operation, Operation})
105+
substitute(expr::Operation, s::Vector{Pair{Operation, Operation}})
104106
105107
Performs the substitution `Operation => Operation` on the `expr` Operation.
106108
"""
107-
substitute_expr!(expr::Constant, s::Pair{Operation, Operation}) = nothing
108-
function substitute_expr!(expr::Operation, s::Pair{Operation, Operation})
109-
if !is_singleton(expr)
110-
expr.args .= replace(expr.args, s)
111-
for arg in expr.args
112-
substitute_expr!(arg, s)
113-
end
114-
end
115-
return nothing
109+
substitute(expr::Constant, s) = nothing
110+
111+
function substitute(expr::Operation, s::Pair{Operation, Operation})
112+
substitute(expr,Dict(to_symbolic(s[1]) => to_symbolic(s[2])))
113+
end
114+
115+
function substitute(expr::Operation, dict::Dict{Operation,Operation})
116+
substitute(expr,Dict(map(Pair,
117+
map(to_symbolic, keys(dict)),
118+
map(to_symbolic, values(dict)))))
116119
end
120+
121+
function substitute(expr::Operation, s::Vector)
122+
substitute(expr,Dict(map(Pair,
123+
map(to_symbolic, first.(s)),
124+
map(to_symbolic, last.(s)))))
125+
end
126+
127+
function substitute(expr::Operation, s::Dict{<:SymbolicUtils.Term,<:SymbolicUtils.Term})
128+
SymbolicUtils.RuleSet([SymbolicUtils.@rule(~x::(x->haskey(s, x)) => s[~x])])(expr) |> to_mtk
129+
end
130+
131+
@deprecate substitute_expr!(expr,s) substitute(expr,s)

test/variable_utils.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ sol = ModelingToolkit.get_variables(expr)
77

88
@parameters γ
99
s = α => γ
10+
expr = (((1 / β - 1) + δ) / α) ^ (1 /- 1))
11+
ModelingToolkit.substitute(expr, s)
1012
new = (((1 / β - 1) + δ) / γ) ^ (1 /- 1))
11-
ModelingToolkit.substitute_expr!(expr, s)
1213
@test isequal(expr, new)

0 commit comments

Comments
 (0)