MATLAB Answers

Trying to supply fsolve with system's Jacobian but receiving error ''check for incorrect argument data type"

10 views (last 30 days)
Mark
Mark on 14 Sep 2021
Commented: Mark on 18 Sep 2021
Hello,
I am trying to solve a system of approximately 600 non-linear equations in MATLAB with the help of fsolve. While I managed to get the programme I am writing to provide a solution to said system, I am currently attempting to supply the system's Jacobian to fsolve, in order to improve efficiency as well as accuracy. However, so far I have been prevented from doing so by the following error:
Check for incorrect argument data type or missing argument in call to function 'jacobian'.
Error in fun_name (line 509)
JAC = jacobian(xss,x);
Error in
File_name>@(x)fun_name(x,inputs) (line 712)
sol = @(x)fun_name(x,inputs)
Error in fsolve (line 269)
[fuser,JAC] = feval(funfcn{3},x,varargin{:});
Error in File_name(line 731)
[xss(ITER,:),x(ITER,:),exitflag,output,jacobian] = fsolve(sol,x0,options);
Here is the relevant (simplified) code I used:
clear;
close all;
%%% CALIBRATION, ETC. %%%
options = optimoptions('fsolve','Display','iter','Algorithm','Levenberg-Marquardt','MaxFunEval',1.0e+08,...
'SpecifyObjectiveGradient',true,'Jacobian','on');
maxiter = 3; % could be anything
%%% Section initialising endogenous variables and any variables that become
%%% updated so that solution values from each iteration can be saved
for ITER=1:maxiter
% Vector of initialised variables
if ITER == 1
x0 = [list of initialised endogenous variables]; % about 600
elseif ITER > 1
x0 = xss(ITER-1,:); % Use the current solution as initial guess for the next period
end
sol = @(x)fun_name(x,inputs); % function handle in separate file [this is the (line 712) mentioned in the error]
a = sym('EV',[1 593]); % EV = Endogenous Variables; create a symbolic vector
FUN = sol(a);
[xss(ITER,:),x(ITER,:),exitflag,output,jacobian] = fsolve(sol,x0,options); % [This is the (line 731) mentioned in the error]
% Some more (unrelated) code
end
The function containing the equations and the udpate mechanism is then as follows:
function [xss,JAC] = fun_name(x,inputs)
% A. Endogenous variables. For instance:
A = x(1:a_given_length); CT = a_given_length;
B = x(CT+1:CT+another_length); CT = CT+another_length;
.
.
.
%%% B. Section with updating procedures for certain variables %%%
% Reshape any matrices that have been vectorised at beginning of function
%%% C. Equations. For instance:
xss1 = A.*B; xss{1} = xss1;
.
.
.
xss = horzcat(xss{:});
% Supplying the system's Jacobian
if nargout(@fun_name) > 1
JAC = jacobian(xss,x); % This is the (line 509) mentioned in the error
end
% some more code, including e.g.
assignin('base','A',A);
% to save updated values from each iteration
end
Having tried to debug the programme, I think I know what the issue is: while the function 'jacobian' requires symbolic inputs, due to some mistake I am making in the code the function ends up being called at JAC with 'double'-type data as inputs. I checked this by running
class(x)
and
class(xss)
before it, and I saw both are 'double'. Having placed a breakpoint at JAC = jacobian(xss,x); the first time it is reached, however, I also noticed that my attempt at creating symbolic variables through a and FUN does create a symbolic JAC matrix of the required dimensions, but when fsolve comes around both xss and x are already both of type 'double' again. How can I get fsolve to solve with its Jacobian in this settings? And, on a related note, is it worth doing so in my case? On my laptop it takes approximately 3 minutes to solve three iterations, so if it takes a long time to create the symbolic variables then I might not see enough gains anyway. And would there be a 'visible' improvement in terms of solution accuracy, in your opinion? Thank you all for the help!

Accepted Answer

Matt J
Matt J on 14 Sep 2021
Edited: Matt J on 14 Sep 2021
It is not clear (from what you posted), why you are using symbolic variable manipulation at all. fsolve is a numerical solver, not a symbolic solver.
If you need the Symbolic Math Toolbox to derive the analytical expression for some part of the Jacobian calculation, that's fine. However, you should not be repeating the symbolic analysis in every iteration of fsolve. The normal and efficient workflow is to derive any symbolic formulas that you need once and once only, and to do it prior to the optimization. Before running hte optimization, you would use matlabFunction() to convert your symbolic functions to an ordinary numerical function which the objective function code fun_name() can then use.
  7 Comments
Mark
Mark on 18 Sep 2021
I see -- as I said, unfortunately I cannot share more of the code. Thank you anyways: your suggestions were useful in making the programme run, at least!

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!