32
32
33
33
# Note that we reduce parameters, too
34
34
# i.e. `2param = 3` will be reduced away
35
- isvar (s:: Sym ) = true
36
- isvar (s :: Term ) = isvar (operation (s))
37
- isvar (s :: Any ) = false
35
+ isvar (s) = s isa Sym ? true :
36
+ istree (s) ? isvar (operation (s)) :
37
+ false
38
38
39
39
function get_α_x (αx)
40
40
if isvar (αx)
@@ -55,7 +55,37 @@ function get_α_x(αx)
55
55
end
56
56
end
57
57
58
- function alias_elimination (sys:: ODESystem )
58
+ function is_univariate_expr (ex, iv)
59
+ count = 0
60
+ for var in vars (ex)
61
+ if ! isequal (iv, var) && ! isparameter (var)
62
+ count += 1
63
+ count > 1 && return false
64
+ end
65
+ end
66
+ return count <= 1
67
+ end
68
+
69
+ function is_sub_candidate (ex, iv, conservative)
70
+ conservative || return true
71
+ isvar (ex) || ex isa Number || is_univariate_expr (ex, iv)
72
+ end
73
+
74
+ function maybe_alias (lhs, rhs, diff_vars, iv, conservative)
75
+ is_sub_candidate (rhs, iv, conservative) || return false , nothing
76
+
77
+ res_left = get_α_x (lhs)
78
+ if res_left != = nothing && ! (res_left[2 ] in diff_vars)
79
+ α, x = res_left
80
+ sub = x => _isone (α) ? rhs : rhs / α
81
+ return true , sub
82
+ else
83
+ return false , nothing
84
+ end
85
+ end
86
+
87
+ function alias_elimination (sys:: ODESystem ; conservative= true )
88
+ iv = independent_variable (sys)
59
89
eqs = vcat (equations (sys), observed (sys))
60
90
diff_vars = filter (! isnothing, map (eqs) do eq
61
91
if isdiffeq (eq)
@@ -76,24 +106,15 @@ function alias_elimination(sys::ODESystem)
76
106
continue
77
107
end
78
108
79
- maybe_alias = isalias = false
80
- res_left = get_α_x (eq. lhs)
81
- if ! isnothing (res_left) && ! (res_left[2 ] in diff_vars)
82
- # `α x = rhs` => `x = rhs / α`
83
- α, x = res_left
84
- sub = x => _isone (α) ? eq. rhs : eq. rhs / α
85
- maybe_alias = true
86
- else
87
- res_right = get_α_x (eq. rhs)
88
- if ! isnothing (res_right) && ! (res_right[2 ] in diff_vars)
89
- # `lhs = β y` => `y = lhs / β`
90
- β, y = res_right
91
- sub = y => _isone (β) ? eq. lhs : β * eq. lhs
92
- maybe_alias = true
93
- end
109
+ # `α x = rhs` => `x = rhs / α`
110
+ ma, sub = maybe_alias (eq. lhs, eq. rhs, diff_vars, iv, conservative)
111
+ if ! ma
112
+ # `lhs = β y` => `y = lhs / β`
113
+ ma, sub = maybe_alias (eq. rhs, eq. lhs, diff_vars, iv, conservative)
94
114
end
95
115
96
- if maybe_alias
116
+ isalias = false
117
+ if ma
97
118
l, r = sub
98
119
# alias equations shouldn't introduce cycles
99
120
if ! (l in deps) && isempty (intersect (deps, vars (r)))
0 commit comments