@@ -569,7 +569,6 @@ function collect_vars!(unknowns, parameters, p::Pair, iv; depth = 0, op = Differ
569569 return nothing
570570end
571571
572-
573572function collect_var! (unknowns, parameters, var, iv; depth = 0 )
574573 isequal (var, iv) && return nothing
575574 check_scope_depth (getmetadata (var, SymScope, LocalScope ()), depth) || return nothing
@@ -1002,6 +1001,11 @@ end
10021001diff2term_with_unit (x, t) = _with_unit (diff2term, x, t)
10031002lower_varname_with_unit (var, iv, order) = _with_unit (lower_varname, var, iv, iv, order)
10041003
1004+ """
1005+ $(TYPEDSIGNATURES)
1006+
1007+ Check if `sym` represents a symbolic floating point number or array of such numbers.
1008+ """
10051009function is_variable_floatingpoint (sym)
10061010 sym = unwrap (sym)
10071011 T = symtype (sym)
@@ -1053,3 +1057,87 @@ function observed_equations_used_by(sys::AbstractSystem, exprs)
10531057 sort! (obsidxs)
10541058 return obsidxs
10551059end
1060+
1061+ """
1062+ $(TYPEDSIGNATURES)
1063+
1064+ Given an expression `expr`, return a dictionary mapping subexpressions of `expr` that do
1065+ not involve variables in `vars` to anonymous symbolic variables. Also return the modified
1066+ `expr` with the substitutions indicated by the dictionary. If `expr` is a function
1067+ of only `vars`, then all of the returned subexpressions can be precomputed.
1068+
1069+ Note that this will only process subexpressions floating point value. Additionally,
1070+ array variables must be passed in both scalarized and non-scalarized forms in `vars`.
1071+ """
1072+ function subexpressions_not_involving_vars (expr, vars)
1073+ expr = unwrap (expr)
1074+ vars = map (unwrap, vars)
1075+ state = Dict ()
1076+ newexpr = subexpressions_not_involving_vars! (expr, vars, state)
1077+ return state, newexpr
1078+ end
1079+
1080+ """
1081+ $(TYPEDSIGNATURES)
1082+
1083+ Mutating version of `subexpressions_not_involving_vars` which writes to `state`. Only
1084+ returns the modified `expr`.
1085+ """
1086+ function subexpressions_not_involving_vars! (expr, vars, state:: Dict{Any, Any} )
1087+ expr = unwrap (expr)
1088+ symbolic_type (expr) == NotSymbolic () && return expr
1089+ iscall (expr) || return expr
1090+ is_variable_floatingpoint (expr) || return expr
1091+ symtype (expr) <: Union{Real, AbstractArray{<:Real}} || return expr
1092+ Symbolics. shape (expr) == Symbolics. Unknown () && return expr
1093+ haskey (state, expr) && return state[expr]
1094+ vs = ModelingToolkit. vars (expr)
1095+ intersect! (vs, vars)
1096+ if isempty (vs)
1097+ sym = gensym (:subexpr )
1098+ stype = symtype (expr)
1099+ var = similar_variable (expr, sym)
1100+ state[expr] = var
1101+ return var
1102+ end
1103+ op = operation (expr)
1104+ args = arguments (expr)
1105+ if (op == (+ ) || op == (* )) && symbolic_type (expr) != = ArraySymbolic ()
1106+ indep_args = []
1107+ dep_args = []
1108+ for arg in args
1109+ _vs = ModelingToolkit. vars (arg)
1110+ intersect! (_vs, vars)
1111+ if ! isempty (_vs)
1112+ push! (dep_args, subexpressions_not_involving_vars! (arg, vars, state))
1113+ else
1114+ push! (indep_args, arg)
1115+ end
1116+ end
1117+ indep_term = reduce (op, indep_args; init = Int (op == (* )))
1118+ indep_term = subexpressions_not_involving_vars! (indep_term, vars, state)
1119+ dep_term = reduce (op, dep_args; init = Int (op == (* )))
1120+ return op (indep_term, dep_term)
1121+ end
1122+ newargs = map (args) do arg
1123+ symbolic_type (arg) != NotSymbolic () || is_array_of_symbolics (arg) || return arg
1124+ subexpressions_not_involving_vars! (arg, vars, state)
1125+ end
1126+ return maketerm (typeof (expr), op, newargs, metadata (expr))
1127+ end
1128+
1129+ """
1130+ $(TYPEDSIGNATURES)
1131+
1132+ Create an anonymous symbolic variable of the same shape, size and symtype as `var`, with
1133+ name `gensym(name)`. Does not support unsized array symbolics.
1134+ """
1135+ function similar_variable (var:: BasicSymbolic , name = :anon )
1136+ name = gensym (name)
1137+ stype = symtype (var)
1138+ sym = Symbolics. variable (name; T = stype)
1139+ if size (var) != = ()
1140+ sym = setmetadata (sym, Symbolics. ArrayShapeCtx, map (Base. OneTo, size (var)))
1141+ end
1142+ return sym
1143+ end
0 commit comments