functions retuning functions, fsolve
Show older comments
Hallo Matlab friends,
I need some help with functions returning functions. I would like to solve nonlinear equations with fsolve for x. My Problem is, how can i put functions(x) into a function which returns functions(x) that i can use in fsolve?
Here is my Problem:
y1 = @(x) 2.*x;
y2 = @(x) x.^2;
[z1,z2] = @(x) fun(y1,y2);
F = @(x) z1(x) + z2(x)
x0 = [0 0 0]';
solu = fsolve(F,x0);
The function fun looks like
function [z1,z2] = fun(y1,y2)
z1 = 4.*y1.^2;
z2 = y2.^3;
end
If i run my code i get the error message:
Only functions can return multiple values.
How can i solve such a problem? I really need some help.
Answers (4)
Walter Roberson
on 2 Aug 2016
function z = F
syms x
[z1, z2] = fun(x,x)
z = matlabFunction(z1 + z2);
7 Comments
Stefan Holzinger
on 2 Aug 2016
Walter Roberson
on 2 Aug 2016
The code I gave does not use handles inside fun. It calls sin() and cos() passing in the symbolic variable x that I created in F, returning symbolic expressions out of fun, not function handles. Then F converts the symbolic expressions to a function handle.
This is a hack way to take a function that was written for numeric arguments and treat the function as a formula that can be manipulated outside the function.
Stefan Holzinger
on 2 Aug 2016
Edited: Stefan Holzinger
on 2 Aug 2016
Stefan Holzinger
on 2 Aug 2016
Walter Roberson
on 3 Aug 2016
It is common to construct the expression symbolically and then use matlabFunction to convert the symbolic expression into a function handle.
If you have a relatively straight-forward expression then more efficient would be to just directly construct the single function handle with the complete expression, and thus eliminating the bit of time to set up the symbolic expression and convert it to a function handle.
However with 200 equations you probably do not have anything nearly that straight forward. Using function handles inside each of the equations is perhaps easier to program (and removes the computation time to set up the symbolic expression and convert it to a function handle) but since you will be calling F many times, the time spent calling all of those function handles inside F is going to add up and you would probably gain in efficiency by going the symbolic -> matlabFunction route.
Depending on what your expressions are like, you might possibly also gain some efficiency by using simplify() on the symbolic expression before turning it into a function handle, but that is not certain.
You can take advantage of common sub-expression elimination by using the form of matlabFunction that writes code to a .m file as that optimizes by default. However, the time it takes to do that optimization can add up. The more often you are going to execute F, the more it becomes worthwhile to do that step.
Note: if you do tell matlabFunction to write to a .m file, then immediately after you do that, you should use "clear" on the name of the function that was just written. Doing so will flush out any previous definition of a function with that name. This is crucial whenever you write new .m inside a loop and then expect to execute the new code.
Stefan Holzinger
on 3 Aug 2016
Walter Roberson
on 3 Aug 2016
Yes, that should work with respect to clear.
Stefan Holzinger
on 3 Aug 2016
Edited: Stefan Holzinger
on 3 Aug 2016
1 Comment
Walter Roberson
on 3 Aug 2016
Your M is 4 x 4, your z1 and z2 are 1 x 4. You have M*x + z1 + z2 . MATLAB always treats (resolved) symbolic names as scalars, so M*x is 4 x 4, and you cannot add 1 x 4 to that. It is not possible in MATLAB to say "in the following, assume that the symbolic name x is a matrix of appropriate size to make all of the operations work out". And even if it did, because M is 4 by 4, no matter what size x was, M*x would have to have a leading dimension of 4 and that is not going to be something you can add to the row vectors z1 and z2.
If you need x to be a matrix in F then you need to use something like
x = sym('x', 4, 1);
h1 = 2*c1.' + 4*x;
h2 = c2.' + x;
You will probably also want to http://www.mathworks.com/help/symbolic/matlabfunction.html#zmw57dd0e96800 and pay attention to the way to have a list of variables be incorporated into an input vector instead of having to appear as individual arguments.
Stefan Holzinger
on 4 Aug 2016
11 Comments
Stefan Holzinger
on 4 Aug 2016
Walter Roberson
on 4 Aug 2016
I recommend using all-symbolic c1 and c2 and calling F once outside the loop to create the general form, with c1 and c2 as parameters. Then in the loop that needs to use F with different c1 and c2, use http://www.mathworks.com/help/matlab/math/parameterizing-functions.html
Stefan Holzinger
on 4 Aug 2016
Stefan Holzinger
on 4 Aug 2016
Walter Roberson
on 4 Aug 2016
Could i be that using sym causes a little loss of accuracy in the calculation results?
No. By default, symbolic computations are calculated to 32 decimal places, whereas double() are calculated to 15 to 16 decimal places. Symbolic computations are more precise, not less precise (unless you lower the Digits setting.)
Walter Roberson
on 4 Aug 2016
function out = F(c1, c2)
x = sym('x',size(c1));
h1 = 2*c1 + 4*x;
h2 = c2 + x;
[z1,z2] = fun(h1,h2);
DG = z1*x + z2*x + z2*h1;
matlabFunction(DG,'File','myfile','Vars',{x, c1, c2});
clear myfile
out = @myfile;
end
and in the place you have the loop:
syms C1 C2
generalF = F(C1, C2);
for i = 1:length(time)
c1(:,1) = c01; % c01...const.
c2(:,1) = c02; % c02...const.
solu(:,1) = solu0; % solu0...const.
v = @(x) generalF(x, c1(:,i),c2(:,i));
solu(:,i+1) = fsolve(v, solu(:,i));
c1(:,i+1) = 4*solu(:,i+1);
c2(:,i+1) = 5*solu(:,i+1);
end
Now the symbolic calculation is done only once and a parameterized function handle is constructed that specializes the general case to particular c1 and c2 values.
Stefan Holzinger
on 6 Aug 2016
Walter Roberson
on 6 Aug 2016
You cannot vectorize an fsolve()
Stefan Holzinger
on 6 Aug 2016
Walter Roberson
on 6 Aug 2016
c1 = bsxfun( @times, c01, 2.^(0:10) );
Stefan Holzinger
on 6 Aug 2016
Victoria Thomas
on 13 Feb 2022
0 votes
Expand f(z) = z^8 e^3z
1 Comment
Victoria Thomas
on 13 Feb 2022
I need solution to my question
Categories
Find more on Code Performance 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!