I am trying to use Symbolics to define and manipulate my problem before moving to numerical methods to actually solve my problem.
After initial manipulations, I want to replace all symbolic variables with their actual values. This worked well for me as long as I used matrices of scalar symbolic variables. I am now trying to move to symbolic arrays, and substitute no longer substitutes all symbolic variables. I tried build_function which managed better, but which also seems to only work on sufficiently simple expressions.
The behaviour I expected is that all symbolic variables are replaced by numerical values in all cases.
I fail to solve my problem using either of substitute or build_function, with build_function managing more complicated expressions, but not the ones I need it for.
I would appreciate any help.
The following is the smallest test case I have showing the issue:
import Pkg
Pkg.activate(".")
Pkg.add("Symbolics")
Pkg.status(outdated=true)
import Symbolics
import Symbolics: @variables, get_variables, substitute, build_function
@variables K[1:2, 1:2]
exprs = [ -K[1,1] -(K[1,1]) (-K)[1,1] ]
subs = Dict(K[1,1] => 1)
for expr in exprs
println("------------------------")
@show expr get_variables(expr)
try
@show substitute(expr, subs)
catch e
@show e
end
f = build_function(expr, K, expression = false)
@show f([1 2; 3 4])
end
@variables A[1:2, 1:2] B[1:2, 1:1] P[1:2, 1:2]
Pre1 = A*[1.0 0.0 0.0; 0.0 1.0 0.0]
Pre2 = broadcast(+, A*[1.0 0.0 0.0; 0.0 1.0 0.0], B*[0.0 0.0 1.0])
Post = Symbolics.Num[1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.0 (broadcast(-, K))[1, 1] (broadcast(-, K))[1, 2]]
for expr in [ Pre1, Pre2, Post, Pre1*Post, Pre2*Post ]
println("---------------------------")
@show expr
fs = build_function(expr, A, B, K, P, expression=false)
for f in fs
try
value = f(randn(2,2), randn(2,1), randn(1,2), randn(2,2))
@show value unique(vcat(get_variables.(value)...))
catch e
end
end
end
The output I get is
Status `~/Workspace/Project.toml`
⌅ [0c5d862f] Symbolics v5.14.1 (<v5.16.1): julia
------------------------
expr = -K[1, 1]
get_variables(expr) = Any[K[1, 1]]
substitute(expr, subs) = -1
f([1 2; 3 4]) = -1
------------------------
expr = -K[1, 1]
get_variables(expr) = Any[K[1, 1]]
substitute(expr, subs) = -1
f([1 2; 3 4]) = -1
------------------------
expr = (broadcast(-, K))[1, 1]
get_variables(expr) = Any[(broadcast(-, K))[1, 1]]
e = MethodError(Core.kwcall, ((metadata = nothing,), SymbolicUtils.similarterm, broadcast(-, K), broadcast, Any[-, K], AbstractMatrix{Real}), 0x0000000000008337)
f([1 2; 3 4]) = -1
---------------------------
expr = (A*[1.0 0.0 0.0; 0.0 1.0 0.0])[Base.OneTo(2),Base.OneTo(3)]
value = [0.8426921154384049 1.3855828533066428 0.0; 2.245360817652516 0.45372334877928383 0.0]
unique(vcat(get_variables.(value)...)) = Any[]
---------------------------
expr = (broadcast(+, A*[1.0 0.0 0.0; 0.0 1.0 0.0], B*[0.0 0.0 1.0]))[Base.OneTo(2),Base.OneTo(3)]
value = [1.3634561500672868 -1.1694430577347337 1.6690534965623611; 1.581800165321597 1.1989213984343103 0.8634154223268747]
unique(vcat(get_variables.(value)...)) = Any[]
---------------------------
expr = Symbolics.Num[1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.0 (broadcast(-, K))[1, 1] (broadcast(-, K))[1, 2]]
value = [1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.0 -0.4432466306968838 0.3592732607253264]
unique(vcat(get_variables.(value)...)) = Any[]
---------------------------
expr = ((A*[1.0 0.0 0.0; 0.0 1.0 0.0])*Symbolics.Num[1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.0 (broadcast(-, K))[1, 1] (broadcast(-, K))[1, 2]])[Base.OneTo(2),Base.OneTo(4)]
value = Symbolics.Num[-1.873960325836164 1.416262070648973 0.0 0.0; -1.4423420994229887 -0.31731200550770267 0.0 0.0]
unique(vcat(get_variables.(value)...)) = Any[]
---------------------------
expr = (broadcast(+, A*[1.0 0.0 0.0; 0.0 1.0 0.0], B*[0.0 0.0 1.0])*Symbolics.Num[1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.0 (broadcast(-, K))[1, 1] (broadcast(-, K))[1, 2]])[Base.OneTo(2),Base.OneTo(4)]
value = Symbolics.Num[0.45315331007912363 -1.367295212832985 0.20383264427229145(broadcast(-, K))[1, 1] 0.20383264427229145(broadcast(-, K))[1, 2]; -1.3151182967142874 -1.1121032853446047 -0.25979763416747165(broadcast(-, K))[1, 1] -0.25979763416747165(broadcast(-, K))[1, 2]]
unique(vcat(get_variables.(value)...)) = Any[(broadcast(-, K))[1, 1], (broadcast(-, K))[1, 2]]
The first part of the output shows that substitute works for me in some cases, but fails as soon as broadcast is introduced into the expressions.
The second part of the output shows that build_function manages to replace all symbolic variables in the expressions Pre1, Pre2, Post and Pre1*Post, but fails in Pre2*Post.