Determining symbolic function values without using matlabFunction
2 views (last 30 days)
Show older comments
Hello all, I am trying to evaluate a symbolic matrix at a certain point. The symbolic functions are as follows:
clc, clear all
x=sym("x",[1 3]);
f(1,1)=x(1)^2 + 2*x(2) +x(3);
f(2,1)=2*x(1) + x(2)^3 + x(2)^2;
f(3,1)=x(1) + x(2) + 2*x(3)^2;
% Finding the jacobian
for i=1:length(f)
for j=1:length(f)
jac(i,j)=diff(f(i), x(j));
end
end
Now, I would like to evaluate the jac at x=[1 2 3].
x=[1 2 3]; % point where jac will be evaluated
It can be done by several ways.
First method:
fv1=tic;
jac_n=matlabFunction(jac);
x_n=num2cell(x);
J1=jac_n(x_n{:})
t_fv1=toc(fv1)
time taken = 0.2255 s.
Second method:
fv2=tic;
J2=[2*x(1) 2 1; 2 3*x(2)^2 2*x(3); 1 1 2] % jac matrix is written manually
t_fv2=toc(fv2
time taken = 4.2230e-04 s
First method takes way longer time than the second method. Also, the first method may not work if all x variables are not present in jac. Now, I want to use the second method as it takes very less time. But I have to write the expressions of jac manually. Is there any way that I can write the expressions of jac automatically? Also, it would be great if anybody can suggest any method faster than those two mentioned. Thank you.
0 Comments
Accepted Answer
Star Strider
on 2 May 2020
You are creating ‘jac_n’ inside the timing block in the code you posted, and creating a cell array from ‘x’.
If you create the function first, and define the ‘x’ values as a vector (they appear in order as ‘in1’ in ‘jac_n’ in my code here), the code is much faster:
jac_n = matlabFunction(jac, 'Vars',{[x]})
x=[1 2 3];
fv1 = tic
J1 = jac_n(x)
fv2 = toc(fv1)
with:
fv2 =
4.436000000000000e-04
and:
in1 = x;
fv3 = tic
out = reshape([in1(:,1).*2.0,2.0,1.0,2.0,in1(:,2).*2.0+in1(:,2).^2.*3.0,1.0,1.0,0.0,in1(:,3).*4.0],[3,3]);
fv4 = toc(fv3)
with:
fv2 =
1.782000000000000e-04
Function calls are always going to be a bit slower than running the code ourside the function. The times I get are nowhere near as disparate as yours.
Running this:
jac_n = matlabFunction(jac, 'Vars',{[x]})
x=[1 2 3];
for k = 1:100
fv1 = tic
J1 = jac_n(x)
fv2 = toc(fv1)
in1 = x;
fv3 = tic
out = reshape([in1(:,1).*2.0,2.0,1.0,2.0,in1(:,2).*2.0+in1(:,2).^2.*3.0,1.0,1.0,0.0,in1(:,3).*4.0],[3,3]);
fv4 = toc(fv3)
ratio(k) = fv2 / fv4;
end
ratio_stats = [mean(ratio) std(ratio)]
produces:
ratio_stats =
3.146795126810789e+00 8.189169834987492e+00
so the direct code is about three times faster than the function, however there is wide variation.
.
3 Comments
Star Strider
on 2 May 2020
As always, my pleasure!
Creating the function using matlabFunction does take time, however it only needs to be done once.
More Answers (1)
Walter Roberson
on 2 May 2020
without having done the x=[1 2 3];
xv = [1 2 3];
subs(jac, x, xv)
time about 0.0157 on my system.
0 Comments
See Also
Categories
Find more on Workspace Variables and MAT-Files in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!