fsolve handling a composition of functions gives the error, "not enough input arguments"

4 views (last 30 days)
Noob on 8 Sep 2020
Edited: Noob on 9 Sep 2020
I'm having some trouble using fsolve on a composition of functions.
I've tried fsolve on a much simpler composition, and it worked just fine, so my code for the "real" problem probably needs to be tweaked.
My real problem starts with a Matlab function, f, that embeds nonlinear modeling code and the solutions gotten from the ode45 solver, and gives me as output only certain ODE solutions I'm interested in, e.g. solutions at the end, time T.
Then, in a separate function file, I write a function, g, that's a difference mapping that uses the outputs from f. So, it's g composed with f.
(The function g has the same inputs as the function f, and gives differences as outputs.)
Now I want to find multivariable roots of the difference mapping g, i.e. solving g = 0, using fsolve; however, I've been getting the message, "not enough input arguments".
Here's the gist of the code from my script file that's calling fsolve:
g = @DifferenceMap;
f = @ODE_solutions_time_T;
% An initial guess at a multivariable root:
xdot_0 = 5;
ydot_0 = 8;
thetadot_0 = 1;
% Multivariable root finding via the fsolve algorithm:
[ xdot_0, ydot_0, thetadot_0] = fsolve( g( f ) , [ xdot_0, ydot_0, thetadot_0 ] );
What am I missing?
Noob on 8 Sep 2020
Hi Walter, I think "yes" to all your questions except for the second-to-last one: DifferenceMap's function handle will be a function of, say, three variables, and output three variables. It has the same number of inputs and outputs. (Same inputs as the function, f)

Sign in to comment.

Accepted Answer

Steven Lord
Steven Lord on 8 Sep 2020
attempts to call the function handle stored in f with 0 input arguments and 1 output argument then call the function handle stored in g with the output argument from f as input. You don't want to call the function handles yourself and pass their outputs into fsolve.
@(x) g(f(x))
defines an anonymous function to be called with 1 input argument. When it is called with an input argument, it calls f with that same input argument and 1 output argument. The output argument from that call to f is then passed into g as its input argument.
g = @sin;
f = @cos;
h = @(x) g(f(x));
% Try calling h
check = [h(5); sin(cos(5))]
check(1) == check(2) % true
Noob on 9 Sep 2020
Hi Steve,
Also, now I see that in g_composed_with_f, I was composing functions g and f, when this composition was already defined in the function file for g (the difference mapping). That was another bug too -- it would be like calling f twice, I think, and probably made Matlab throw those "initial objective function evaluation" error messages.
I simply needed an anonymous function for g, with one input.
Thanks again,

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 8 Sep 2020
Edited: Walter Roberson on 8 Sep 2020
fsolve() needs to be passed a function handle that accepts one input and returns one output.
If you have a function that returns multiple separate outputs (as opposed to returning a vector with multiple values) then to use the function with fsolve, you need to construct a true function (cannot be done with an anonymous function) that does something like
function single_output = gather_outputs(fun, varargin)
n = nargout(fun);
[outputs{1:n}] = fun(varargin{:});
single_output = cell2mat(outputs);
and then you would
outputs = fsolve(@(x) gather_outputs(@YourFunction, x), [ xdot_0, ydot_0, thetadot_0 ]);
xdot_0 = outputs(1);
ydot_0 = outputs(2);
thetadot_0 = outputs(3);
Notice that the output from fsolve() is not a list of variable values: the first output from fsolve is a vector of values, and the second output is a the value of the function at that final location, and the third output is the exit flag giving status information.
The function handle you pass in as the first parameter to fsolve must be of a function that expects a vector as input. If you are calling a function that expects individual parameters, then you can break them up in an anonymous function, such as
outputs = fsolve(@(x) gather_outputs(@YourFunction, x(1), x(2), x(3)), [ xdot_0, ydot_0, thetadot_0 ]);
... But if you have choice, we would recommend that you rewrite the functions to expect a vector of input and return a vector output.
Noob on 9 Sep 2020
Hi Walter,
My code seems to run fine now.
I'll play with the fsolve program now to see how it works, and start making some initial guesses for the program to find a multivariable root, solving g = 0.
Thanks for your help and patience,

Sign in to comment.





Community Treasure Hunt

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

Start Hunting!

Translated by