fsolve with three anonymous functions

13 Ansichten (letzte 30 Tage)
Simon
Simon am 23 Mär. 2011
Hello everybody,
I can't see why giving a cell array of three separate anonymous as input to fsolve() doesn't work:
a = 6;
f = @(x)[sin(x);x;x*x];
g = @(x) sin(x);
h = @(x) x;
y1 = fsolve(f,a)
y2 = fsolve({g,f},a)
y3 = fsolve({f,g,h},a)
y1 and y2 will be calculated, y3 results in an error:
??? Error using ==> lsqfcnchk at 117
FUN must be a function or an inline object;
What do I miss over here? or, FUN may be a cell array that contains these type of objects.

Akzeptierte Antwort

Andrew Newell
Andrew Newell am 29 Mär. 2011
O.k., Walter thinks we haven't answered your original question, and he may be right. As his comment on your answer shows, the loop can work - but not in the form you have displayed it. If you define a function this way,
function EqSys = makeSystem(N)
EqSys = cell(1,N);
for i=1:N
EqSys{i} = @(x)x^i;
end
and then try these commands
>> EqSys = makeSystem(2)
EqSys =
@(x)(x-i)^i @(x)(x-i)^i
the output is a cell array of function handles that works as in Walter's comment - for example,
>> EqSys{2}(1)
ans =
1
Then if you type
>> fsolve(EqSys,1)
you get an answer of 0 (preceded by a lot of diagnostic statements).
But did you really get the simultaneous solution of these equations? If your function is
function EqSys = makeSystem(N)
EqSys = cell(1,N);
for i=1:N
EqSys{i} = @(x)(x-i)^i;
end
and you enter
>> EqSys = makeSystem(2);
>> fsolve(EqSys,1)
you will get an answer of 1 (which only solves the first equation).
I don't see any way of setting this up using function handles that is worth the trouble. Instead, you could create a function like this:
function y = eqnSystem(x,N)
y = zeros(N,1);
for i=1:N
y(i) = (x(i)-i)^i;
end
which, by the way, assumes that x has as many components as there are equations - a requirement for a well-defined problem. Then
>> x0 = [2 3];
>> f = @(x) eqnSystem(x,N);
>> fsolve(f,x0)
gives the answer
1.0000 2.0075
which is surprisingly inaccurate (but you can improve this by adjusting the options for fsolve).
  3 Kommentare
Andrew Newell
Andrew Newell am 29 Mär. 2011
I'm not sure what you mean. If I call EqSys = makeSystem(2), I get
EqSys =
@(x)(x-i)^i @(x)(x-i)^i
which behaves just as you described in your comment.
Walter Roberson
Walter Roberson am 29 Mär. 2011
Ah, I hadn't noticed the function definition... sorry, I was in a rush then.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (4)

Simon
Simon am 27 Mär. 2011
Well, thanks for your answer Andrew.
Still, I can make up an equation system like
EqSys = @(x)[ x^2; 3*x; sqrt(x) ]
and givt it as an argument to fsolve
fsolve(EqSys, 1)
Is there a way to convert three single equations f, g, h to a one quation system like EqSys without rewriting explicitly?
  1 Kommentar
Walter Roberson
Walter Roberson am 27 Mär. 2011
Ummm, like
EqSys = (x) [ f(x), g(x), h(x) ];

Melden Sie sich an, um zu kommentieren.


Andrew Newell
Andrew Newell am 23 Mär. 2011
The full message is
??? Error using ==> lsqfcnchk at 117
FUN must be a function or an inline object;
or, FUN may be a cell array that contains these type of objects.
The third statement is not the whole truth. I looked at the code, and lsqfcnchk only allows cell arrays of length 1 or 2. However, the documentation for fsolve does not claim that you can input cell arrays at all. So the documentation is not quite right.
Of course, you can still solve each equation separately.

Simon
Simon am 29 Mär. 2011
What I'm originally trying to do is:
If have a parameter, say N, and call a function solve(N), which shall create N functions by using a simple loop and then solve for these functions.
e.g.
EqSys = cell(1,N)
function solve(N)
for i=1:N
EqSys{i} = @(x)x^i;
end
fsolve(EqSys,x0)
This fails twice right now:
1. First I can't use the loop variable in the functions -> How to convert variables to parameters in functions?
2. Let's say, for the moment, all equations x_i in that loop were just x^2.
for i=1:N
EqSys{i} = @(x)x^2;
end
fsolve will still refuse for the cell array EqSys, telling me that FUN may be a cell array containing functions or inline objects, which I think it is, right?
It does all seem so incosistent to me right now. A recommendation for a proper tutorial or explanation on functions, function cell arrays, etc. would probably be helpful, too.
  1 Kommentar
Walter Roberson
Walter Roberson am 29 Mär. 2011
Your loop does work
>> EqSys{2}(5)
ans =
25
>> EqSys{4}(5)
ans =
625
The text representation of the function handles _does_ appear to have ^i in it, suggestive of it not having worked, but each of those "i" had its value "captured" at the time of function creation.

Melden Sie sich an, um zu kommentieren.


Simon
Simon am 29 Mär. 2011
Your suggestion with eqnSystem() does the job!
Hopefully my questions weren't to confusing. I tried to generalize my concrete problem.
I'm solving the classic multilateration problem with an arbitrary number on N receivers, producing N-1 equations through time differences of arrival (TDOA).
function y = makeEqSys(Tx,Rx,d)
N = length(Rx);
y = zeros(N-1,1);
for i=2:N
y(i-1) = sqrt((Rx(i,1)-Tx(1))^2+(Rx(i,2)-Tx(2))^2) - ...
sqrt((Rx(1,1)-Tx(1))^2+(Rx(1,2)-Tx(2))^2) - d(i,1);
end
where Tx is the unknown position [x,y] of a transmitter, N the number of receivers and Rx the given positions of the N receivers. d is the matrix of measured TDOA distance differences for each pair of receivers. As you can see, Tx is the same in each iteration, while only Rx(i) and d(i) actually depend on the iteration variable.
myRx = [ 0,0; 100,0; 0,100; 100,100]
myd = [ 0; 10; 20; 30]
f = @(x) makeEqSys(x,myRx,myd);
qrt = fsolve(f,guess)
This finds the non-linear least squares result using the Levenberg-Marquardt method as [43.3] and [36.0]. Nice!
Thanks a lot!

Kategorien

Mehr zu Function Creation finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by