11 views (last 30 days)

Show older comments

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!

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.

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

Start Hunting!