functions retuning functions, fsolve

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.

2 Comments

Solved it.
I modified the example a little bit.
h1 = @(x) 2*x + 1;
h2 = @(x) x + 2;
[z1,z2] = fun(h1,h2);
F = @(x) z1(x) + z2(x);
x0 = 1;
solu = fsolve(F,x0)
The function fun looks like:
function [z1,z2] = fun(a,b)
z1 = @(a) sin(a);
z2 = @(b) cos(b);
end
But now i would like to know if there is a way to reformulate the example in a way such that the function fun looks like:
function [z1,z2] = fun(a,b)
z1 = sin(a);
z2 = cos(b);
end
Any ideas?

Sign in to comment.

Answers (4)

function z = F
syms x
[z1, z2] = fun(x,x)
z = matlabFunction(z1 + z2);

7 Comments

Hallo Walter, thanks for your answer. It works for me, but do you know a way to formulate the function fun without using handles inside fun?
function [z1,z2] = fun(a,b)
z1 = sin(a);
z2 = cos(b);
end
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.
Ah ok, now i understand. Thank you! :) The Problem was that i didn't cleaned my workspace so i got some errors and i had to put back the handles to cos and sin but now it works without handles. :)
What would you say regarding efficiency. Should i better use my solution with function handles or your solution with the symbolic variable? The reason i ask is that i would like to expand this problem to lets say 200 equations(h1,h2).
Regarding efficiency i mean computation time.
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.
Thank you for your support! Your suggestions are really helpfull! A last question to your note about "clear": Is this what you meant (see the following code)?
v = F;
x0 = 1;
solu = fsolve(v,x0)
Where fun is:
function [z1,z2] = fun(a,b)
z1 = sin(a);
z2 = cos(b);
end
matlab
function out = F
syms x
h1 = 2*x + 1;
h2 = cos(x) + 2;
[z1, z2] = fun(h1,h2);
z = matlabFunction(z1 + z2,'File','myfile');
clear myfile
out = @myfile;
end
Yes, that should work with respect to clear.

Sign in to comment.

Meanwhile i expanded my problem a little bit but when it comes to fsolve, i run into the error:
Error using symengine
Array sizes must match.
Error in sym/privBinaryOp (line 937)
Csym = mupadmex(op,args{1}.s, args{2}.s, varargin{:});
Error in + (line 7)
X = privBinaryOp(A, B, 'symobj::zip', '_plus');
Error in F (line 10)
matlabFunction(M*x + z1 + z2,'File','myfile');
Error in Test_1 (line 9)
v = F(c1,c2);
Here is what i did:
c1 = [1 2 0 0];
c2 = [2 0 0 0];
v = F(c1,c2);
x0 = [2 1 0 0]';
solu = fsolve(v,x0)
F:
function out = F(c1,c2)
syms x
h1 = 2*c1 + 4*x;
h2 = c2 + x;
[z1, z2, M] = fun(h1,h2);
matlabFunction(M*x + z1 + z2,'File','myfile');
clear myfile
out = @myfile;
end
fun:
function [z1,z2,M] = fun(a,b)
I = diag([1 1 1]);
E = @(a) [-a(2) a(1) a(4) -a(3);
-a(3) -a(4) a(1) a(2);
-a(4) a(3) -a(2) a(1)];
Gbar = 2*E(a);
M = Gbar'*I*Gbar
z1 = sin(a);
z2 = sin(b);
end
Where did i made a mistake? :/

1 Comment

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.

Sign in to comment.

Hey Walter i solved it. :)
Here is the code of a minimum working example, if anyone else is interested:
c1 = [1 2]';
c2 = [2 0]';
v = F(c1,c2);
x0 = [1 1]';
solu = fsolve(v,x0)
Function F:
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});
clear myfile
out = @myfile;
end
and f:
function [z1,z2] = fun(a,b)
z1 = [a(1) a(2);
a(2) a(1)];
z2 = [a(1)*b(1) a(2)*b(2);
a(2)*b(1) a(1)*b(2)];
end

11 Comments

I expanded my solution to a more complex equation system within fun. F is called in a for loop and now the computation is very slow. It seems that the symbolic stuff needs much time. Are there any other clues like 'clear' to improve computation performance?
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
Hm could you maybe give me a example how to do this, I'm not sure if i understand this procedure.
The generell structure of my loop is:
for i = 1:length(time)
c1(:,1) = c01; % c01...const.
c2(:,1) = c02; % c02...const.
solu(:,1) = solu0; % solu0...const.
v = F(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
Could i be that using sym causes a little loss of accuracy in the calculation results?
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.)
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.
Thank you Walter, this is a huge speed up! :) I set:
C1 = sym('C1',size(c01));
C2 = sym('C2',size(c02));
generalF = F(C1, C2);
I've noticed that C1 and C2 in sym('C1'...), sym('C2'...) must have different names otherwise the calculated fsolve solutions are "wrong". I thought those symbolics are only dummys for what comes later within the loop?
So the last thing i would like to do is to vectorize the for-loop. I've done some simple mathworks examples but i don't get it how to do this with my for loop. Could yoo give me a hint?
You cannot vectorize an fsolve()
Hm, I thought so. Is it possible to vectorize a loop like this? If yes, how? :P
c01 = [1 1]';
c02 = [2 2]';
for i = 1:10;
c1(:,1) = c01;
c2(:,1) = c02;
c1(:,i+1) = 2*c1(:,i);
c2(:,i+1) = 3*c2(:,i);
end
c1 = bsxfun( @times, c01, 2.^(0:10) );
bsxfun seems to be an interesting function. :) thanks!

Sign in to comment.

Expand f(z) = z^8 e^3z

Asked:

on 2 Aug 2016

Commented:

on 13 Feb 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!