We occasionally have issues with singular Jacobians as in https://forum.dynare.org/t/blanchard-conditions-in-stochastic-and-deterministic-models/15980
It would be good to have a debugging options that would point to the culprit for e.g. a row or column of zeros. Maybe we could add this to model_diagnostics. Two test cases are attached, one for sim1 and one for sim1_linear.
A piece of code in model_diagnostics carries out this check for the static jacobian. It is reproduced below:
tryrank_jacob=rank(jacob);%can sometimes failcatchrank_jacob=size(jacob,1);endifrank_jacob<size(jacob,1)problem_dummy=1;singularity_problem=1;disp(['MODEL_DIAGNOSTICS: The Jacobian of the static model is '...'singular'])disp(['MODEL_DIAGNOSTICS: there is 'num2str(endo_nbr-rank_jacob)...' colinear relationships between the variables and the equations'])ncol=null(jacob);n_rel=size(ncol,2);fori=1:n_relifn_rel>1disp(['Relation 'int2str(i)])enddisp('Colinear variables:')forj=1:10k=find(abs(ncol(:,i))>10^-j);ifmax(abs(jacob(:,k)*ncol(k,i)))<1e-6breakendendfprintf('%s\n',endo_names{k})endneq=null(jacob');n_rel=size(neq,2);fori=1:n_relifn_rel>1disp(['Relation 'int2str(i)])enddisp('Colinear equations')forj=1:10k=find(abs(neq(:,i))>10^-j);ifmax(abs(jacob(k,:)'*neq(k,i)))<1e-6breakendenddisp(k')endend
The rank function and the null function both use a SVD. Calling the null function is enough as one may infer the rank from the dimension of the kernel, and saves one SVD.
The remarks above may stem from a failure in understanding subtle things. Any enlightenment would be appreciated in that regard.
I propose to create a function that returns the rank and the dependent colums of a matrix. It would be as follow:
It could be useful for identification issues as well (e.g. dependent columns in a information matrix to detect identification issues as Iskrev does)
Adapting the piece of code above for the perfect foresight problems is not straightforward, though. The involved jacobian in the perfect foresight problem is the stacked jacobian and its link with the basic dynamic jacobian .dynamic files compute is not theoretically clear.
It does not seem natural to check the stacked jacobian in model_diagnostics.m, as it considers the basic dynamic jacobian. A solution could be to check the stacked jacobian in each method, as the considered jacobian may differ in structure (e.g. perfect-foresight-models/sim1_linear), and return the incriminated variables and equations.
model_diagnostics is not called repeatedly, so efficiency was not a major focus. That being said, factorization is always a good idea as it makes maintaining codes easier and creates efficient code for reuse. We should maybe benchmark whether the approach taken in identification_checks.m is more efficient.
It's a good question where to put such a check. model_diagnostics has no way of knowing the context, i.e. whether we are doing perfect foresight simulations. Checking the stacked Jacobian there does not seem to be a good idea.
I agree with @normann that it would better fit in the respective solvers. As a starting point, we could simply add such a check for the first iteration in an if options_.debug-clause in sim1 and sim1_linear
The idea was to display first the variables with the highest coefficients. It would be a good thing to separate computing the dependent columns and displaying the relevent information.
The stacked Jacobian is made with dynamic jacobians, but the determinacy of the stacked jacobian can't be deduced from the determinacy of the dynamic jacobian. Furthermore dynamic jacobian are rectangular matrices.
It is necessary to look at the null space of the sparse stacked jacobian. The most interesting information is with the equations or variables involved in the null space near the beginning or near the end of the stacked jacobian matrix.