75 views (last 30 days)
Show older comments
Tuan Hua on 5 Jun 2023
Commented: Tuan Hua on 3 Aug 2023
I am simulating a robotic system with symbolic dynamic matrices of the robot. When I used "subs" function to substitute the symbolic variables, it took around 0.03 seconds for 1 matrix. This is relatively slow because I will need to do this a thousand times for 1 second of simulation. I also tried using matlabFunction, but it took longer to finish, around 0.5s!
So my question is is there any way to speed up the symbolic substitution?
9 Comments Show 7 older commentsHide 7 older comments
Show 7 older commentsHide 7 older comments
Torsten on 5 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2771419
The way is: don't use symbolic computations if speed is an issue.
Walter Roberson on 5 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2771434
You can create the expression symbolically then matlabFunction it, and then after that use the function handle to apply to actual values -- do not matlabFunction() inside a loop (at least not without good reason.)
Tuan Hua on 6 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2772699
Open in MATLAB Online
I did like you suggested. I created a matrix, for example M, symbolically. Then I matlabFuntion it and store in a ".mat" file:
M = matlabFunction(M,"Vars",[q1 q2 q3 q4 q5 q6]);
save('dynamic_matrices', 'M')
Then at the beginning of the simulation, I will load the .mat file in to workspace:
load('dynamic_matrices.mat')
Whenever I want to substitute the variables, I will do as below:
M = evalin('base','M');
M = double(M(q1,q2,q3,q4,q5,q6));
Tuan Hua on 6 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2772704
@Torsten Hmmm, could you please suggest an alternative way for symbolic computation?
Torsten on 6 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2772904
Edited: Torsten on 6 Jun 2023
Open in MATLAB Online
Hmmm, could you please suggest an alternative way for symbolic computation?
It depends. But often, symbolic computations can easily be completely replaced by numerical computations.
Concerning your above comment:
Why do you save and load M ? Why don't you just use and/or pass it as a usual function handle in your code ?
syms x
f = x.^2;
f = matlabFunction(f);
f(2)
ans = 4
Walter Roberson on 6 Jun 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2773634
Open in MATLAB Online
M = evalin('base','M');
What is the purpose of that?
There are two possibilities:
- At the time you did the load('dynamic_matrices.mat') you were operating in the base workspace. In that case, M would already have been "poofed" into the base workspace by the load() and the evalin('base', 'M') would just be copying the M that is already in the current workspace (by assumption: the base workspace in this case) to itself; OR
- At the time you did the load you were not operating in the base workspace. In that case, load() would not have "poofed" M into the base workspace (into the current workspace instead), and evalin('base', 'M') is not going to find the M that was loaded -- it would either error or find some other M.
The evalin('base','M') is thus either unnecessary or else incorrect.
M = double(M(q1,q2,q3,q4,q5,q6));
The output of matlabFunction() is a function handle that evaluates numerically according to the datatype of the inputs, which would typically be double . The output of executing the function handle would therefore typically be double already, so using double() on it would typically be unneeded.
Storing the result of executing with those particular parameters over-top of M is confusing to the readers, and confusing to MATLAB.
By the way, if you want to store the function long term (because you want to generate it once and use it many times) then I suggest you use
M = matlabFunction(M, "Vars", [q1 q2 q3 q4 q5 q6], 'file', 'M.m', 'optimize', false);
This would create M.m that could be called by other functions without needing to load() anything.
Tuan Hua on 2 Aug 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2837082
Hi @Walter Roberson, thanks for your suggestion, I removed the evalin function, I also save the matrix as an m-file to reuse. However, the result of the matlabFuntion is still quite slower than the subs function. I don't really know where it is wrong. Do you have any further ideas?
Walter Roberson on 3 Aug 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2837127
Open in MATLAB Online
@Tuan Hua
Sometimes when you have an expression that repeats a number of sub-expressions, then the symbolic engine might store references to the sub-expressions, and during calculation might only evaluate the common sub-expression once. However when you convert to function handle, the sub-expressions need to be evaluated each time.
For example, suppose you had the symbolic expression
(sin(gamma(x))-1)^3 + 5*(sin(gamma(x))-1)
then the symbolic engine might internally represent that as
temporary_node1 = sin(gamma(x))-1
result = temporary_node1^3 + 5*temporary_node1
but the anonymous function handle
@(x) (sin(gamma(x))-1)^3 + 5*(sin(gamma(x))-1)
would require execution of the sin(gamma(x))-1 each time.
If that is what is happening, then you can often get better numeric performance by using
h = matlabFunction(EXPRESSION, 'file', 'FileNameGoesHere.m', 'optimize', true)
which would do an analysis to find common sub-expressions and would write file FileNameGoesHere.m containing optimized code.
There are at least two problems with using this approach:
- the optimization itself to find common sub-expressions can take a long time. For longer expressions, it can take literally hours. You need to ask the question of whether faster resulting .m file is going to be executed enough times that the total time saved will make up for the minutes to hours spent trying to find the optimal version of the code;
- historically, the optimization routine has had serious bugs. I do not know if all of those bugs have been fixed.
Tuan Hua on 3 Aug 2023
Direct link to this comment
https://www.mathworks.com/matlabcentral/answers/1978404-speed-up-subs-function-or-faster-alternative-ways-for-symbolic-substitution#comment_2837352
Thanks for your help, Walter! I think it is better to use the subs function with symbolic variable in my case!
Sign in to comment.
Sign in to answer this question.
Answers (0)
Sign in to answer this question.
See Also
Categories
Mathematics and OptimizationSymbolic Math Toolbox
Find more on Symbolic Math Toolbox in Help Center and File Exchange
Tags
- subs
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- Deutsch
- English
- Français
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)
Contact your local office