2023-09-15 10:06:49 +02:00
function mcheck = mode_check ( fun,xparam,hessian_mat,options_,M_,estim_params_,bayestopt_,bounds,isMinimum, varargin)
% function mcheck = mode_check(fun,xparam,hessian_mat,options_,M_,estim_params_,bayestopt_,bounds,isMinimum, varargin)
% -------------------------------------------------------------------------
% Checks the estimated ML or Posterior mode/minimum by plotting sections of
% the likelihood/posterior kernel. Each plot shows the variation of the
% function implied by the variations of a single parameter ( ceteris paribus)
2023-09-19 13:16:49 +02:00
% -------------------------------------------------------------------------
2023-09-15 10:06:49 +02:00
% INPUTS
% - fun: [func_handle] objective function
% - xparam: [vector] estimated mode/minimum
% - hessian_mat: [matrix] hessian of the objective function at the estimated mode/minimum
% - options_: [structure] Dynare options structure
% - M_: [structure] Dynare model structure
% - estim_params_: [structure] Dynare estimated parameters structure
% - bayestopt_: [structure] information on the priors
% - bounds: [structure] information on the bounds
% - isMinimum: [boolean] true if xparam is a minimum, false if it is a mode
% - varargin: [cell] additional arguments to be passed to fun
% -------------------------------------------------------------------------
% OUTPUTS
% - mcheck: [structure] structure containing the data for the check plots
% - Saves the plots in the graphs folder and the data in a mat file
% -------------------------------------------------------------------------
% This function is called by
% - dynare_estimation_1
% - mom.run
% -------------------------------------------------------------------------
2023-09-19 13:16:49 +02:00
2023-09-15 10:06:49 +02:00
% Copyright © 2023 Dynare Team
2008-08-01 14:40:33 +02:00
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
2021-06-09 17:33:48 +02:00
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
2008-01-21 12:51:09 +01:00
2023-09-15 10:06:49 +02:00
tolBounds = 1e-8 ;
2011-09-22 11:17:31 +02:00
2023-09-15 10:06:49 +02:00
fval = feval ( fun , xparam , varargin { : } ) ;
2011-05-13 12:46:11 +02:00
2017-05-16 12:42:01 +02:00
if ~ isempty ( hessian_mat )
2023-09-15 10:06:49 +02:00
[ s_min , k ] = min ( diag ( hessian_mat ) ) ;
if isMinimum
fprintf ( ' \nMINIMUM CHECK\n\nFval obtained by the optimization routine: %f\n' , fval )
else
fprintf ( ' \nMODE CHECK\n\nFval obtained by the optimization routine: %f\n' , fval )
end
2011-05-13 12:46:11 +02:00
if s_min < eps
2023-09-15 10:06:49 +02:00
fprintf ( ' Most negative variance %f for parameter %d (%s = %f)\n' , s_min , k , bayestopt_ . name { k } , xparam ( k ) ) ;
2011-05-13 12:46:11 +02:00
end
2009-04-06 16:48:30 +02:00
end
2005-02-18 20:54:39 +01:00
2023-09-15 10:06:49 +02:00
[ nbplt , nr , nc , ~ , ~ , nstar ] = pltorg ( length ( xparam ) ) ;
2005-02-18 20:54:39 +01:00
2023-09-15 10:06:49 +02:00
graphsFolder = CheckPath ( ' graphs' , M_ . dname ) ;
latexFolder = CheckPath ( ' latex' , M_ . dname ) ;
if options_ . TeX && any ( strcmp ( ' eps' , cellstr ( options_ . graph_format ) ) )
fidTeX = fopen ( [ latexFolder filesep M_ . fname ' _CheckPlots.tex' ] , ' w' ) ;
2005-02-18 20:54:39 +01:00
fprintf ( fidTeX , ' %% TeX eps-loader file generated by mode_check.m (Dynare).\n' ) ;
fprintf ( fidTeX , [ ' %% ' datestr ( now , 0 ) ' \n' ] ) ;
fprintf ( fidTeX , ' \n' ) ;
end
2023-09-15 10:06:49 +02:00
ll = options_ . mode_check . neighbourhood_size ;
2017-05-16 12:42:01 +02:00
if isinf ( ll )
2023-09-15 10:06:49 +02:00
options_ . mode_check . symmetric_plots = false ;
2013-06-18 22:30:49 +02:00
end
2012-03-05 15:03:55 +01:00
2023-09-15 10:06:49 +02:00
if isMinimum
mcheck = struct ( ' cross' , struct ( ) , ' emin' , struct ( ) ) ;
else
mcheck = struct ( ' cross' , struct ( ) , ' emode' , struct ( ) ) ;
end
2015-07-08 16:05:38 +02:00
2017-05-16 12:42:01 +02:00
for plt = 1 : nbplt
2023-09-15 10:06:49 +02:00
if options_ . TeX
2005-02-18 20:54:39 +01:00
NAMES = [ ] ;
TeXNAMES = [ ] ;
end
2023-09-15 10:06:49 +02:00
if isMinimum
hh_fig = dyn_figure ( options_ . nodisplay , ' Name' , ' Minimum check plots' ) ;
else
hh_fig = dyn_figure ( options_ . nodisplay , ' Name' , ' Mode check plots' ) ;
end
for k = 1 : min ( nstar , length ( xparam ) - ( plt - 1 ) * nstar )
2009-06-19 10:54:40 +02:00
subplot ( nr , nc , k )
kk = ( plt - 1 ) * nstar + k ;
2023-09-15 10:06:49 +02:00
[ name , texname ] = get_the_name ( kk , options_ . TeX , M_ , estim_params_ , options_ ) ;
xx = xparam ;
if xparam ( kk ) ~= 0 && ~ isinf ( bounds . lb ( kk ) ) && ~ isinf ( bounds . ub ( kk ) )
l1 = max ( bounds . lb ( kk ) , ( 1 - sign ( xparam ( kk ) ) * ll ) * xparam ( kk ) ) ; m1 = 0 ; % lower bound
l2 = min ( bounds . ub ( kk ) , ( 1 + sign ( xparam ( kk ) ) * ll ) * xparam ( kk ) ) ; % upper bound
2017-09-15 18:41:41 +02:00
else
2023-09-15 10:06:49 +02:00
% size info for 0 parameter is missing, use prior standard deviation
upper_bound = bounds . lb ( kk ) ;
2017-11-22 11:05:12 +01:00
if isinf ( upper_bound )
2023-09-15 10:06:49 +02:00
upper_bound = - 1e-6 * options_ . huge_number ;
2017-11-22 11:05:12 +01:00
end
2023-09-15 10:06:49 +02:00
lower_bound = bounds . ub ( kk ) ;
2017-11-22 11:05:12 +01:00
if isinf ( lower_bound )
2023-09-15 10:06:49 +02:00
lower_bound = - 1e-6 * options_ . huge_number ;
2017-11-22 11:05:12 +01:00
end
2023-09-15 10:06:49 +02:00
l1 = max ( lower_bound , - bayestopt_ . p2 ( kk ) ) ; m1 = 0 ; % lower bound
l2 = min ( upper_bound , bayestopt_ . p2 ( kk ) ) ; % upper bound
2019-12-20 16:28:06 +01:00
end
2023-09-15 10:06:49 +02:00
binding_lower_bound = 0 ;
binding_upper_bound = 0 ;
if abs ( xparam ( kk ) - bounds . lb ( kk ) ) < tolBounds
binding_lower_bound = 1 ;
bound_value = bounds . lb ( kk ) ;
elseif abs ( xparam ( kk ) - bounds . ub ( kk ) ) < tolBounds
binding_upper_bound = 1 ;
bound_value = bounds . ub ( kk ) ;
2017-05-16 15:10:20 +02:00
end
2023-09-15 10:06:49 +02:00
if options_ . mode_check . symmetric_plots && ~ binding_lower_bound && ~ binding_upper_bound
if l2 < ( 1 + ll ) * xparam ( kk ) % test whether upper bound is too small due to prior binding
l1 = xparam ( kk ) - ( l2 - xparam ( kk ) ) ; % adjust lower bound to become closer
2013-06-18 22:30:49 +02:00
m1 = 1 ;
end
2023-09-15 10:06:49 +02:00
if ~ m1 && ( l1 > ( 1 - ll ) * xparam ( kk ) ) && ( xparam ( kk ) + ( xparam ( kk ) - l1 ) < bounds . ub ( kk ) ) % if lower bound was truncated and using difference from lower bound does not violate upper bound
l2 = xparam ( kk ) + ( xparam ( kk ) - l1 ) ; % set upper bound to same distance as lower bound
2013-06-18 22:30:49 +02:00
end
2012-03-05 15:03:55 +01:00
end
2023-09-15 10:06:49 +02:00
z1 = l1 : ( ( xparam ( kk ) - l1 ) / ( options_ . mode_check . number_of_points / 2 ) ) : xparam ( kk ) ;
z2 = xparam ( kk ) : ( ( l2 - xparam ( kk ) ) / ( options_ . mode_check . number_of_points / 2 ) ) : l2 ;
2012-03-05 15:03:55 +01:00
z = union ( z1 , z2 ) ;
2023-09-15 10:06:49 +02:00
if ~ options_ . mode_check . nolik
2009-12-16 18:17:34 +01:00
y = zeros ( length ( z ) , 2 ) ;
2023-09-15 10:06:49 +02:00
if isfield ( options_ , ' mom' ) && ( ( strcmp ( options_ . mom . mom_method , ' GMM' ) || strcmp ( options_ . mom . mom_method , ' SMM' ) ) && options_ . mom . penalized_estimator )
dy = ( xx - bayestopt_ . p1 ) ' / diag ( bayestopt_ . p2 .^ 2 ) * ( xx - bayestopt_ . p1 ) ;
else
dy = priordens ( xx , bayestopt_ . pshape , bayestopt_ . p6 , bayestopt_ . p7 , bayestopt_ . p3 , bayestopt_ . p4 ) ;
end
2009-06-19 10:54:40 +02:00
end
2023-09-15 10:06:49 +02:00
for i = 1 : length ( z )
2005-02-18 20:54:39 +01:00
xx ( kk ) = z ( i ) ;
2023-09-15 10:06:49 +02:00
[ fval , info , exit_flag ] = feval ( fun , xx , varargin { : } ) ;
2011-09-22 11:17:31 +02:00
if exit_flag
y ( i , 1 ) = fval ;
2007-06-22 11:23:45 +02:00
else
2011-09-22 11:17:31 +02:00
y ( i , 1 ) = NaN ;
2023-09-15 10:06:49 +02:00
if options_ . debug
fprintf ( ' mode_check:: could not solve model for parameter %s at value %4.3f, error code: %u (%s)\n' , name , z ( i ) , info ( 1 ) , get_error_message ( info , options_ ) ) ;
2016-10-09 22:16:26 +02:00
end
2009-06-19 10:54:40 +02:00
end
2023-09-15 10:06:49 +02:00
if ~ options_ . mode_check . nolik
if isfield ( options_ , ' mom' ) && ( ( strcmp ( options_ . mom . mom_method , ' GMM' ) || strcmp ( options_ . mom . mom_method , ' SMM' ) ) && options_ . mom . penalized_estimator )
lnprior = ( xx - bayestopt_ . p1 ) ' / diag ( bayestopt_ . p2 .^ 2 ) * ( xx - bayestopt_ . p1 ) ;
else
lnprior = priordens ( xx , bayestopt_ . pshape , bayestopt_ . p6 , bayestopt_ . p7 , bayestopt_ . p3 , bayestopt_ . p4 ) ;
end
2009-07-08 12:11:38 +02:00
y ( i , 2 ) = ( y ( i , 1 ) + lnprior - dy ) ;
2009-06-19 10:54:40 +02:00
end
2005-02-18 20:54:39 +01:00
end
2023-09-15 10:06:49 +02:00
if isMinimum
mcheck . cross = setfield ( mcheck . cross , name , [ transpose ( z ) , y ] ) ; % keep y
mcheck . emin = setfield ( mcheck . emin , name , xparam ( kk ) ) ; % store as min
fighandle = plot ( z , y ) ;
else
mcheck . cross = setfield ( mcheck . cross , name , [ transpose ( z ) , - y ] ) ; % multiply y by -1
mcheck . emode = setfield ( mcheck . emode , name , xparam ( kk ) ) ; % store as mode
fighandle = plot ( z , - y ) ;
end
2005-02-18 20:54:39 +01:00
hold on
2023-09-15 10:06:49 +02:00
yl = get ( gca , ' ylim' ) ;
plot ( [ xparam ( kk ) xparam ( kk ) ] , yl , ' c' , ' LineWidth' , 1 ) ;
2009-07-08 12:11:38 +02:00
NaN_index = find ( isnan ( y ( : , 1 ) ) ) ;
zNaN = z ( NaN_index ) ;
yNaN = yl ( 1 ) * ones ( size ( NaN_index ) ) ;
plot ( zNaN , yNaN , ' o' , ' MarkerEdgeColor' , ' r' , ' MarkerFaceColor' , ' r' , ' MarkerSize' , 6 ) ;
2023-09-15 10:06:49 +02:00
if options_ . TeX
2020-06-17 20:23:49 +02:00
title ( texname , ' interpreter' , ' latex' )
else
title ( name , ' interpreter' , ' none' )
end
2009-07-08 12:11:38 +02:00
axis tight
2013-07-05 23:46:05 +02:00
if binding_lower_bound || binding_upper_bound
2023-09-15 10:06:49 +02:00
xl = get ( gca , ' xlim' ) ;
plot ( [ bound_value bound_value ] , yl , ' r--' , ' LineWidth' , 1 ) ;
xlim ( [ xl ( 1 ) - 0.5 * binding_lower_bound * ( xl ( 2 ) - xl ( 1 ) ) xl ( 2 ) + 0.5 * binding_upper_bound * ( xl ( 2 ) - xl ( 1 ) ) ] ) ;
2013-07-05 23:46:05 +02:00
end
hold off
2005-02-18 20:54:39 +01:00
drawnow
end
2023-09-15 10:06:49 +02:00
if ~ options_ . mode_check . nolik
2013-11-04 10:54:45 +01:00
if isoctave
2023-09-15 10:06:49 +02:00
axes ( ' outerposition' , [ 0.3 0.93 0.42 0.07 ] , ' box' , ' on' ) ;
2009-06-19 10:54:40 +02:00
else
2023-09-15 10:06:49 +02:00
axes ( ' position' , [ 0.3 0.01 0.42 0.05 ] , ' box' , ' on' ) ;
2009-06-19 10:54:40 +02:00
end
2015-04-02 20:52:49 +02:00
line_color = get ( fighandle , ' color' ) ;
2023-09-15 10:06:49 +02:00
plot ( [ 0.48 0.68 ] , [ 0.5 0.5 ] , ' color' , line_color { 2 } ) ;
hold on ;
plot ( [ 0.04 0.24 ] , [ 0.5 0.5 ] , ' color' , line_color { 1 } ) ;
set ( gca , ' xlim' , [ 0 1 ] , ' ylim' , [ 0 1 ] , ' xtick' , [ ] , ' ytick' , [ ] ) ;
if isMinimum
text ( 0.25 , 0.5 , ' log-post' ) ;
text ( 0.69 , 0.5 , ' log-dist kernel' ) ;
else
text ( 0.25 , 0.5 , ' log-post' ) ;
text ( 0.69 , 0.5 , ' log-lik kernel' ) ;
end
2009-06-19 10:54:40 +02:00
end
2023-09-15 10:06:49 +02:00
dyn_saveas ( hh_fig , [ graphsFolder filesep M_ . fname ' _CheckPlots' int2str ( plt ) ] , options_ . nodisplay , options_ . graph_format ) ;
if options_ . TeX && any ( strcmp ( ' eps' , cellstr ( options_ . graph_format ) ) )
2009-06-19 10:54:40 +02:00
% TeX eps loader file
2005-02-18 20:54:39 +01:00
fprintf ( fidTeX , ' \\begin{figure}[H]\n' ) ;
fprintf ( fidTeX , ' \\centering \n' ) ;
2023-09-15 10:06:49 +02:00
fprintf ( fidTeX , ' \\includegraphics[width=%2.2f\\textwidth]{%s_CheckPlots%s}\n' , options_ . figures . textwidth * min ( k / nc , 1 ) , [ graphsFolder filesep M_ . fname ] , int2str ( plt ) ) ;
2005-02-18 20:54:39 +01:00
fprintf ( fidTeX , ' \\caption{Check plots.}' ) ;
2009-06-19 10:54:40 +02:00
fprintf ( fidTeX , ' \\label{Fig:CheckPlots:%s}\n' , int2str ( plt ) ) ;
2005-02-18 20:54:39 +01:00
fprintf ( fidTeX , ' \\end{figure}\n' ) ;
fprintf ( fidTeX , ' \n' ) ;
end
2015-07-08 16:05:38 +02:00
end
2023-09-15 10:06:49 +02:00
if options_ . TeX && any ( strcmp ( ' eps' , cellstr ( options_ . graph_format ) ) )
2017-05-16 15:10:20 +02:00
fclose ( fidTeX ) ;
2015-11-28 14:07:36 +01:00
end
2015-07-08 16:05:38 +02:00
2023-09-15 10:06:49 +02:00
save ( [ graphsFolder filesep M_ . fname ' _check_plot_data.mat' ] , ' mcheck' ) ;