This is a static copy of a profile report

Home

Function details for ff_ipwkbz_fibs_vf_vecsvThis is a static copy of a profile report

Home

ff_ipwkbz_fibs_vf_vecsv (Calls: 1, Time: 8.736 s)
Generated 15-Jul-2019 20:47:29 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_fibs\m_ipwkbz_solve\ff_ipwkbz_fibs_vf_vecsv.m
Copy to new window for comparing multiple runs

Parents (calling functions)
No parent
Lines where the most time was spent

Line NumberCodeCallsTotal Time% TimeTime Plot
248
mt_val_wkb_interpolated = f_gr...
1351.878 s21.5%
509
ffs_fibs_min_c_cost_bridge(fl_...
115801.262 s14.4%
269
ff_ipwkbz_fibs_evf(mt_val_wkb_...
1350.924 s10.6%
333
mt_w_ev_interp_z_wneg = f_inte...
20250.408 s4.7%
327
mt_w_kstar_interp_z_wneg = f_i...
20250.402 s4.6%
All other lines  3.863 s44.2%
Totals  8.736 s100% 
Children (called functions)

Function NameFunction TypeCallsTotal Time% TimeTime Plot
ffs_fibs_min_c_cost_bridgefunction115801.239 s14.2%
ff_ipwkbz_fibs_evffunction1350.907 s10.4%
...coh,bprime,kprime)(coh-kprime-bprime)anonymous function40510.038 s0.4%
linspacefunction20250.018 s0.2%
meanfunction1350.013 s0.1%
ffs_fibs_identify_discretefunction10.004 s0.0%
Self time (built-ins, overhead, etc.)  6.518 s74.6%
Totals  8.736 s100% 
Code Analyzer results
Line numberMessage
132The value assigned here to 'ar_forbrblk_r' appears to be unused. Consider replacing it by ~.
132The value assigned here to 'ar_forbrblk' appears to be unused. Consider replacing it by ~.
Coverage results
Show coverage for parent directory
Total lines in function618
Non-code lines (comments, blank lines)338
Code lines (lines that can run)280
Code lines that did run140
Code lines that did not run140
Coverage (did run/can run)50.00 %
Function listing
time 
Calls 
 line
   7 
function result_map = ff_ipwkbz_fibs_vf_vecsv(varargin)
   8 
%% FF_IPWKBZ_VF_VECSV solve infinite horizon exo shock + endo asset problem
   9 
% This is a modified version of
  10 
% <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbz/solve/html/ff_ipwkbz_vf_vecsv.html
  11 
% ff_ipwkbz_vf_vecsv>, to see how this function solves the formal and
  12 
% savings risky and safe asset problem with formal and informal choices,
  13 
% compare the code here and from
  14 
% <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbz/solve/html/ff_ipwkbz_vf_vecsv.html
  15 
% ff_ipwkbz_vf_vecsv> side by side.
  16 
%
  17 
% @param param_map container parameter container
  18 
%
  19 
% @param support_map container support container
  20 
%
  21 
% @param armt_map container container with states, choices and shocks
  22 
% grids that are inputs for grid based solution algorithm
  23 
%
  24 
% @param func_map container container with function handles for
  25 
% consumption cash-on-hand etc.
  26 
%
  27 
% @return result_map container contains policy function matrix, value
  28 
% function matrix, iteration results, and policy function, value function
  29 
% and iteration results tables.
  30 
%
  31 
% keys included in result_map:
  32 
%
  33 
% * mt_val matrix states_n by shock_n matrix of converged value function grid
  34 
% * mt_pol_a matrix states_n by shock_n matrix of converged policy function grid
  35 
% * ar_val_diff_norm array if bl_post = true it_iter_last by 1 val function
  36 
% difference between iteration
  37 
% * ar_pol_diff_norm array if bl_post = true it_iter_last by 1 policy
  38 
% function difference between iterations
  39 
% * mt_pol_perc_change matrix if bl_post = true it_iter_last by shock_n the
  40 
% proportion of grid points at which policy function changed between
  41 
% current and last iteration for each element of shock
  42 
%
  43 
% @example
  44 
%
  45 
% @include
  46 
%
  47 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbz/paramfunc/ff_ipwkbz_evf.m ff_ipwkbz_evf>
  48 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbz/paramfunc/ffs_ipwkbz_set_default_param.m ffs_ipwkbz_set_default_param>
  49 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbz/paramfunc/ffs_ipwkbz_get_funcgrid.m ffs_ipwkbz_get_funcgrid>
  50 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_akz/solvepost/ff_akz_vf_post.m ff_akz_vf_post>
  51 
%
  52 

  53 
%% Default
  54 
% * it_param_set = 1: quick test
  55 
% * it_param_set = 2: benchmark run
  56 
% * it_param_set = 3: benchmark profile
  57 
% * it_param_set = 4: press publish button
  58 

  59 
it_param_set = 3;
  60 
[param_map, support_map] = ffs_ipwkbz_fibs_set_default_param(it_param_set);
  61 

  62 
% parameters can be set inside ffs_ipwkbz_set_default_param or updated here
  63 
% param_map('it_w_perc_n') = 50;
  64 
% param_map('it_ak_perc_n') = param_map('it_w_perc_n');
  65 
% param_map('it_z_n') = 15;
  66 
% param_map('fl_coh_interp_grid_gap') = 0.025;
  67 
% param_map('it_c_interp_grid_gap') = 0.001;
  68 
% param_map('fl_w_interp_grid_gap') = 0.25;
  69 
% param_map('it_w_perc_n') = 100;
  70 
% param_map('it_ak_perc_n') = param_map('it_w_perc_n');
  71 
% param_map('it_z_n') = 11;
  72 
% param_map('fl_coh_interp_grid_gap') = 0.1;
  73 
% param_map('it_c_interp_grid_gap') = 10^-4;
  74 
% param_map('fl_w_interp_grid_gap') = 0.1;
  75 

  76 
% get armt and func map
  77 
params_len = length(varargin);
  78 
if params_len <= 2
  79 
    [armt_map, func_map] = ffs_ipwkbz_fibs_get_funcgrid(param_map, support_map); % 1 for override
  80 
    default_params = {param_map support_map armt_map func_map};
  81 
end
  82 

  83 
%% Parse Parameters 1
  84 

  85 
% if varargin only has param_map and support_map,
  86 
[default_params{1:params_len}] = varargin{:};
  87 
param_map = [param_map; default_params{1}];
  88 
support_map = [support_map; default_params{2}];
  89 
if params_len >= 1 && params_len <= 2
  90 
    % If override param_map, re-generate armt and func if they are not
  91 
    % provided
  92 
    [armt_map, func_map] = ffs_ipwkbz_fibs_get_funcgrid(param_map, support_map);
  93 
else
  94 
    % Override all
  95 
    armt_map = default_params{3};
  96 
    func_map = default_params{4};
  97 
end
  98 

  99 
% append function name
 100 
st_func_name = 'ff_ipwkbz_fibs_vf_vecsv';
 101 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 102 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 103 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 104 

 105 
%% Parse Parameters 2
 106 

 107 
% armt_map
 108 
params_group = values(armt_map, ...
 109 
    {'ar_w_perc', 'ar_w_level_full', 'ar_coh_bridge_perc', 'ar_z'});
 110 
[ar_w_perc, ar_w_level_full, ar_coh_bridge_perc, ar_z] = params_group{:};
 111 
params_group = values(armt_map, {'ar_interp_c_grid', 'ar_interp_coh_grid', ...
 112 
    'ar_a_meshk', 'ar_k_mesha', ...
 113 
    'mt_interp_coh_grid_mesh_z', 'mt_z_mesh_coh_interp_grid',...
 114 
    'mt_interp_coh_grid_mesh_w_perc',...
 115 
    'mt_w_level_neg_mesh_coh_bridge_perc', 'mt_coh_bridge_perc_mesh_w_level_neg',...
 116 
    'mt_bl_w_by_interp_coh_interp_grid_wneg', ...
 117 
    'mt_w_by_interp_coh_interp_grid_wneg', 'mt_w_by_interp_coh_interp_grid_wpos', 'mt_coh_w_perc_ratio_wneg'});
 118 
[ar_interp_c_grid, ar_interp_coh_grid, ar_a_meshk, ar_k_mesha, ...
 119 
    mt_interp_coh_grid_mesh_z, mt_z_mesh_coh_interp_grid, ...
 120 
    mt_interp_coh_grid_mesh_w_perc,...
 121 
    mt_w_level_neg_mesh_coh_bridge_perc, mt_coh_bridge_perc_mesh_w_level_neg, ...
 122 
    mt_bl_w_by_interp_coh_interp_grid_wneg, ...
 123 
    mt_w_by_interp_coh_interp_grid_wneg, mt_w_by_interp_coh_interp_grid_wpos, mt_coh_w_perc_ratio_wneg] ...
 124 
        = params_group{:};
 125 

 126 
params_group = values(armt_map, {'mt_coh_wkb', 'mt_z_mesh_coh_wkb'});
 127 
[mt_coh_wkb, mt_z_mesh_coh_wkb] = params_group{:};
 128 

 129 
% armt_map
 130 
% Formal choice Menu/Grid and Interest Rate Menu/Grid
 131 
params_group = values(armt_map, {'ar_forbrblk_r', 'ar_forbrblk'});
 132 
[ar_forbrblk_r, ar_forbrblk] = params_group{:};
 133 

 134 
% func_map
 135 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_cons'});
 136 
[f_util_log, f_util_crra, f_cons] = params_group{:};
 137 

 138 
% param_map
 139 
params_group = values(param_map, {'it_z_n', 'fl_crra', 'fl_beta', ...
 140 
    'fl_nan_replace', 'fl_c_min', 'bl_bridge', 'bl_default', 'fl_default_wprime'});
 141 
[it_z_n, fl_crra, fl_beta, fl_nan_replace, fl_c_min, bl_bridge, bl_default, fl_default_wprime] = params_group{:};
 142 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 143 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 144 

 145 
% support_map
 146 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 147 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 148 
    'bl_time', 'bl_display_defparam', 'bl_graph_evf', 'bl_display', 'it_display_every', 'bl_post'});
 149 
[bl_profile, st_profile_path, ...
 150 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 151 
    bl_time, bl_display_defparam, bl_graph_evf, bl_display, it_display_every, bl_post] = params_group{:};
 152 
params_group = values(support_map, {'it_display_summmat_rowmax', 'it_display_summmat_colmax'});
 153 
[it_display_summmat_rowmax, it_display_summmat_colmax] = params_group{:};
 154 

 155 
%% Initialize Output Matrixes
 156 

 157 
mt_val_cur = zeros(length(ar_interp_coh_grid),length(ar_z));
 158 
mt_val = mt_val_cur - 1;
 159 
mt_pol_a = zeros(length(ar_interp_coh_grid),length(ar_z));
 160 
mt_pol_a_cur = mt_pol_a - 1;
 161 
mt_pol_k = zeros(length(ar_interp_coh_grid),length(ar_z));
 162 
mt_pol_k_cur = mt_pol_k - 1;
 163 
mt_pol_idx = zeros(length(ar_interp_coh_grid),length(ar_z));
 164 

 165 
% collect optimal borrowing formal and informal choices
 166 
% mt_pol_b_with_r: cost to t+1 consumption from borrowing in t
 167 
mt_pol_b_with_r = zeros(length(ar_interp_coh_grid),length(ar_z));
 168 
mt_pol_b_bridge = zeros(length(ar_interp_coh_grid),length(ar_z));
 169 
mt_pol_inf_borr_nobridge = zeros(length(ar_interp_coh_grid),length(ar_z));
 170 
mt_pol_for_borr = zeros(length(ar_interp_coh_grid),length(ar_z));
 171 
mt_pol_for_save = zeros(length(ar_interp_coh_grid),length(ar_z));
 172 

 173 
% We did not need these in ff_oz_vf or ff_oz_vf_vec
 174 
% see
 175 
% <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 176 
% fs_u_c_partrepeat_main> for why store using cells.
 177 
cl_u_c_store = cell([it_z_n, 1]);
 178 
cl_c_valid_idx = cell([it_z_n, 1]);
 179 
cl_w_kstar_interp_z = cell([it_z_n, 1]);
 180 
for it_z_i = 1:length(ar_z)
 181 
    cl_w_kstar_interp_z{it_z_i} = zeros([length(ar_w_perc), length(ar_interp_coh_grid)]) - 1;
 182 
end
 183 

 184 
%% Initialize Convergence Conditions
 185 

 186 
bl_vfi_continue = true;
 187 
it_iter = 0;
 188 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 189 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 190 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 191 

 192 
%% Pre-calculate u(c)
 193 
% Interpolation, see
 194 
% <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 195 
% fs_u_c_partrepeat_main> for why interpolate over u(c)
 196 

 197 
% Evaluate
 198 
if (fl_crra == 1)
 199 
    ar_interp_u_of_c_grid = f_util_log(ar_interp_c_grid);
 200 
    fl_u_cmin = f_util_log(fl_c_min);
 201 
else
 202 
    ar_interp_u_of_c_grid = f_util_crra(ar_interp_c_grid);
 203 
    fl_u_cmin = f_util_crra(fl_c_min);
 204 
end
 205 
ar_interp_u_of_c_grid(ar_interp_c_grid <= fl_c_min) = fl_u_cmin;
 206 

 207 
% Get Interpolant
 208 
f_grid_interpolant_spln = griddedInterpolant(ar_interp_c_grid, ar_interp_u_of_c_grid, 'spline', 'nearest');
 209 

 210 
%% Iterate Value Function
 211 
% Loop solution with 4 nested loops
 212 
%
 213 
% # loop 1: over exogenous states
 214 
% # loop 2: over endogenous states
 215 
% # loop 3: over choices
 216 
% # loop 4: add future utility, integration--loop over future shocks
 217 
%
 218 

 219 
% Start Profile
 220 
if (bl_profile)
 221 
    close all;
 222 
    profile off;
 223 
    profile on;
< 0.001 
      1 
 224
end 
 225 

 226 
% Start Timer
< 0.001 
      1 
 227
if (bl_time) 
< 0.001 
      1 
 228
    tic; 
< 0.001 
      1 
 229
end 
 230 

 231 
% Value Function Iteration
< 0.001 
      1 
 232
while bl_vfi_continue 
< 0.001 
    135 
 233
    it_iter = it_iter + 1; 
 234 

 235 
    %% Interpolate (1) reacahble v(coh(k(w,z),b(w,z),z),z) given v(coh, z)
 236 
    % This is the same as <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbz/solve/html/ff_ipwkbz_vf_vecsv.html
 237 
    % ff_ipwkbz_vf_vecsv>. For the FIBS problem, the cash-on-hand
 238 
    % interpolation grid stays the same, and the shock grid stays the same
 239 
    % as well. The results will not be the same, for example, the coh_grid
 240 
    % max is the max of reachable cash-on-hand levels (min is however just
 241 
    % the borrowing bound).
 242 

 243 
    % Generate Interpolant for v(coh,z)
  0.049 
    135 
 244
    f_grid_interpolant_value = griddedInterpolant(... 
    135 
 245
        mt_z_mesh_coh_interp_grid', mt_interp_coh_grid_mesh_z', mt_val_cur', 'linear', 'nearest'); 
 246 

 247 
    % Interpolate for v(coh(k(w,z),b(w,z),z),z)
  1.878 
    135 
 248
    mt_val_wkb_interpolated = f_grid_interpolant_value(mt_z_mesh_coh_wkb, mt_coh_wkb); 
 249 

 250 
    %% Solve Second Stage Problem k*(w,z)
 251 
    % This is again the same as <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbz/solve/html/ff_ipwkbz_vf_vecsv.html
 252 
    % ff_ipwkbz_vf_vecsv>. But the output matrix sizes are different.
 253 
    % Previously, they were (length(ar_w_level)) by (length(ar_z)). Now
 254 
    % have this thing which is stored (length(ar_w_level_full)) by
 255 
    % (length(ar_z)). _ar_w_level_full_ includes not just different levels
 256 
    % of _ar_w_level_, but also repeats the elements of _ar_w_level_ that
 257 
    % are < 0 by _it_coh_bridge_perc_n_ times, starting with what
 258 
    % corresponds to 100 percent of w should go to cover bridge loan, until
 259 
    % 0 percent for w < 0, which then proceeds to w > 0. So the last
 260 
    % segment of _ar_w_level_full_ is the same as ar_w_level:
 261 
    % ar_w_level_full((end-length(ar_w_level)+1):end) = ar_w_level.
 262 

  0.013 
    135 
 263
    support_map('bl_graph_evf') = false; 
< 0.001 
    135 
 264
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 265
        support_map('bl_graph_evf') = bl_graph_evf; 
< 0.001 
      1 
 266
    end 
< 0.001 
    135 
 267
    bl_input_override = true; 
  0.924 
    135 
 268
    [mt_ev_condi_z_max, ~, mt_ev_condi_z_max_kp, ~] = ... 
    135 
 269
        ff_ipwkbz_fibs_evf(mt_val_wkb_interpolated, param_map, support_map, armt_map, bl_input_override); 
 270 

 271 
    %% Solve First Stage Problem w*(z) given k*(w,z)
 272 
    % Refer to
 273 
    % <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbz/solve/html/ff_ipwkbz_fibs_vf_vecsv.html
 274 
    % ff_ipwkbz_fibs_vf_vecsv> where the problem was solved without formal and
 275 
    % informal choices that allow for bridge loans to see line by line how
 276 
    % code differ. Some of the comments from that file are not here to save
 277 
    % space. Comments here address differences and are specific to formal
 278 
    % and informal choices.
 279 

 280 
    % loop 1: over exogenous states
< 0.001 
    135 
 281
    for it_z_i = 1:length(ar_z) 
 282 

 283 
        %% A. Interpolate FULL to get k*(coh_level, w_perc, z), b*(k,w) based on k*(coh_perc, w_level)
 284 
        % additionally, Interpolate FULL EV(k*(coh_level, w_perc, z), w -
 285 
        % b*|z) based on EV(k*(coh_perc, w_level))
 286 
        %
 287 
        % we solved the second period problem in ff_ipwkbz_fibs_fibs_evf.m
 288 
        % above. To use results, we need to interpolate in the following
 289 
        % way to obtain *mt_w_kstar_interp_z* as well as
 290 
        % *mt_ev_condi_z_max_interp_z*:
 291 
        %
 292 
        % # Interp STG1A: for $w > 0$, 1D interpolate over w level, given z
 293 
        % # Interp STG1B: for $w < 0$, 2D interpolate over w level and coh
 294 
        % perceng, given z
 295 
        %
 296 

 297 
        % 1. Negative Elements of w grid expanded by w percentages for bridge
  0.007 
   2025 
 298
        ar_bl_w_level_full_neg = (ar_w_level_full < 0); 
 299 

 300 
        % 2. Current Positve w and negative w optimal k choices
  0.007 
   2025 
 301
        it_wneg_mt_row = sum(ar_bl_w_level_full_neg)/length(ar_coh_bridge_perc); 
 302 
        % for mt_ev_condi_z_max_kp
  0.017 
   2025 
 303
        ar_ev_condi_z_max_kp_wpos = mt_ev_condi_z_max_kp(~ar_bl_w_level_full_neg, it_z_i)'; 
  0.013 
   2025 
 304
        ar_ev_condi_z_max_kp_wneg = mt_ev_condi_z_max_kp(ar_bl_w_level_full_neg, it_z_i)'; 
  0.006 
   2025 
 305
        mt_ev_condi_z_max_kp_wneg = reshape(ar_ev_condi_z_max_kp_wneg, [it_wneg_mt_row, length(ar_coh_bridge_perc)]); 
 306 
        % for mt_ev_condi_z_max
  0.015 
   2025 
 307
        ar_ev_condi_z_max_wpos = mt_ev_condi_z_max(~ar_bl_w_level_full_neg, it_z_i)'; 
  0.013 
   2025 
 308
        ar_ev_condi_z_max_wneg = mt_ev_condi_z_max(ar_bl_w_level_full_neg, it_z_i)'; 
  0.003 
   2025 
 309
        mt_ev_condi_z_max_wneg = reshape(ar_ev_condi_z_max_wneg, [it_wneg_mt_row, length(ar_coh_bridge_perc)]); 
 310 

 311 
        % 2. Interp STG1A for w > 0
  0.013 
   2025 
 312
        ar_w_level_full_pos = ar_w_level_full(~ar_bl_w_level_full_neg); 
 313 
        % Interpolation for mt_ev_condi_z_max_kp
  0.069 
   2025 
 314
        f_interpolante_w_level_pos_kstar_z = griddedInterpolant(ar_w_level_full_pos, ar_ev_condi_z_max_kp_wpos, 'linear', 'nearest'); 
  0.235 
   2025 
 315
        mt_w_kstar_interp_z_wpos = f_interpolante_w_level_pos_kstar_z(mt_w_by_interp_coh_interp_grid_wpos(:)); 
  0.023 
   2025 
 316
        mt_w_astar_interp_z_wpos = mt_w_by_interp_coh_interp_grid_wpos(:) - mt_w_kstar_interp_z_wpos; 
 317 
        % Interpolation for mt_ev_condi_z_max
  0.056 
   2025 
 318
        f_interpolante_w_level_pos_ev_z = griddedInterpolant(ar_w_level_full_pos, ar_ev_condi_z_max_wpos, 'linear', 'nearest'); 
  0.169 
   2025 
 319
        mt_w_ev_interp_z_wpos = f_interpolante_w_level_pos_ev_z(mt_w_by_interp_coh_interp_grid_wpos(:)); 
 320 

 321 
        % 3. Interp STG1B for w <= 0
< 0.001 
   2025 
 322
        if (bl_bridge) 
 323 
            % Interpolation for mt_ev_condi_z_max_kp
  0.083 
   2025 
 324
            f_interpolante_w_level_neg_kstar_z = griddedInterpolant(... 
   2025 
 325
                mt_coh_bridge_perc_mesh_w_level_neg', mt_w_level_neg_mesh_coh_bridge_perc', ... 
   2025 
 326
                mt_ev_condi_z_max_kp_wneg', 'linear', 'nearest'); 
  0.402 
   2025 
 327
            mt_w_kstar_interp_z_wneg = f_interpolante_w_level_neg_kstar_z(mt_coh_w_perc_ratio_wneg(:), mt_w_by_interp_coh_interp_grid_wneg(:)); 
  0.025 
   2025 
 328
            mt_w_astar_interp_z_wneg = mt_w_by_interp_coh_interp_grid_wneg(:) - mt_w_kstar_interp_z_wneg; 
 329 
            % Interpolation for mt_ev_condi_z_max
  0.086 
   2025 
 330
            f_interpolante_w_level_neg_ev_z = griddedInterpolant(... 
   2025 
 331
                mt_coh_bridge_perc_mesh_w_level_neg', mt_w_level_neg_mesh_coh_bridge_perc', ... 
   2025 
 332
                mt_ev_condi_z_max_wneg', 'linear', 'nearest'); 
  0.408 
   2025 
 333
            mt_w_ev_interp_z_wneg = f_interpolante_w_level_neg_ev_z(mt_coh_w_perc_ratio_wneg(:), mt_w_by_interp_coh_interp_grid_wneg(:)); 
 334 
        else
 335 
            ar_w_level_full_neg = ar_w_level_full(ar_bl_w_level_full_neg);
 336 
            % Interpolation for mt_ev_condi_z_max_kp
 337 
            f_interpolante_w_level_neg_kstar_z = griddedInterpolant(ar_w_level_full_neg, ar_ev_condi_z_max_kp_wneg, 'linear', 'nearest');
 338 
            mt_w_kstar_interp_z_wneg = f_interpolante_w_level_neg_kstar_z(mt_w_by_interp_coh_interp_grid_wneg(:));
 339 
            mt_w_astar_interp_z_wneg = mt_w_by_interp_coh_interp_grid_wneg(:) - mt_w_kstar_interp_z_wneg;
 340 
            % Interpolation for mt_ev_condi_z_max
 341 
            f_interpolante_w_level_neg_ev_z = griddedInterpolant(ar_w_level_full_neg, ar_ev_condi_z_max_wneg, 'linear', 'nearest');
 342 
            mt_w_ev_interp_z_wneg = f_interpolante_w_level_neg_ev_z(mt_w_by_interp_coh_interp_grid_wneg(:));
< 0.001 
   2025 
 343
        end 
 344 

 345 
        % 4. Combine positive and negative aggregate savings matrix
 346 
        % check: mt_w_by_interp_coh_interp_grid vs mt_w_astar_interp_z + mt_w_kstar_interp_z
 347 
        % combine for mt_ev_condi_z_max_kp
  0.091 
   2025 
 348
        mt_w_kstar_interp_z = zeros(size(mt_bl_w_by_interp_coh_interp_grid_wneg)); 
  0.228 
   2025 
 349
        mt_w_kstar_interp_z(~mt_bl_w_by_interp_coh_interp_grid_wneg) = mt_w_kstar_interp_z_wpos; 
  0.208 
   2025 
 350
        mt_w_kstar_interp_z(mt_bl_w_by_interp_coh_interp_grid_wneg)  = mt_w_kstar_interp_z_wneg; 
  0.144 
   2025 
 351
        mt_w_astar_interp_z = zeros(size(mt_bl_w_by_interp_coh_interp_grid_wneg)); 
  0.252 
   2025 
 352
        mt_w_astar_interp_z(~mt_bl_w_by_interp_coh_interp_grid_wneg) = mt_w_astar_interp_z_wpos; 
  0.200 
   2025 
 353
        mt_w_astar_interp_z(mt_bl_w_by_interp_coh_interp_grid_wneg)  = mt_w_astar_interp_z_wneg; 
 354 
        % combine for mt_ev_condi_z_max
  0.139 
   2025 
 355
        mt_ev_condi_z_max_interp_z = zeros(size(mt_bl_w_by_interp_coh_interp_grid_wneg)); 
  0.244 
   2025 
 356
        mt_ev_condi_z_max_interp_z(~mt_bl_w_by_interp_coh_interp_grid_wneg) = mt_w_ev_interp_z_wpos; 
  0.200 
   2025 
 357
        mt_ev_condi_z_max_interp_z(mt_bl_w_by_interp_coh_interp_grid_wneg)  = mt_w_ev_interp_z_wneg; 
 358 

 359 
        % 5. changes in w_perc kstar choices
  0.065 
   2025 
 360
        mt_w_kstar_diff_idx = (cl_w_kstar_interp_z{it_z_i} ~= mt_w_kstar_interp_z); 
 361 

 362 
        %% B. Calculate UPDATE u(c) Update: u(c(coh_level, w_perc)) given k*_interp, b*_interp
  0.212 
   2025 
 363
        ar_c = f_cons(mt_interp_coh_grid_mesh_w_perc(mt_w_kstar_diff_idx), ... 
   2025 
 364
                      mt_w_astar_interp_z(mt_w_kstar_diff_idx), ... 
   2025 
 365
                      mt_w_kstar_interp_z(mt_w_kstar_diff_idx)); 
 366 

  0.006 
   2025 
 367
        ar_it_c_valid_idx = (ar_c <= fl_c_min); 
 368 
        % EVAL current utility: N by N, f_util defined earlier
  0.139 
   2025 
 369
        ar_utility_update = f_grid_interpolant_spln(ar_c); 
 370 

 371 
        % Update Storage
< 0.001 
   2025 
 372
        if (it_iter == 1) 
< 0.001 
     15 
 373
            cl_u_c_store{it_z_i} = reshape(ar_utility_update, [length(ar_w_perc), length(ar_interp_coh_grid)]); 
< 0.001 
     15 
 374
            cl_c_valid_idx{it_z_i} = reshape(ar_it_c_valid_idx, [length(ar_w_perc), length(ar_interp_coh_grid)]); 
< 0.001 
   2010 
 375
        else 
  0.060 
   2010 
 376
            cl_u_c_store{it_z_i}(mt_w_kstar_diff_idx) = ar_utility_update; 
  0.050 
   2010 
 377
            cl_c_valid_idx{it_z_i}(mt_w_kstar_diff_idx) = ar_it_c_valid_idx; 
< 0.001 
   2025 
 378
        end 
  0.095 
   2025 
 379
        cl_w_kstar_interp_z{it_z_i} = mt_w_kstar_interp_z; 
 380 

 381 
        %% D. Compute FULL U(coh_level, w_perc, z) over all w_perc
  0.062 
   2025 
 382
        mt_utility = cl_u_c_store{it_z_i} + fl_beta*mt_ev_condi_z_max_interp_z; 
 383 

 384 
        % Index update
 385 
        % using the method below is much faster than index replace
 386 
        % see <https://fanwangecon.github.io/M4Econ/support/speed/index/fs_subscript.html fs_subscript>
  0.001 
   2025 
 387
        mt_it_c_valid_idx = cl_c_valid_idx{it_z_i}; 
 388 
        % Default or Not Utility Handling
< 0.001 
   2025 
 389
        if (bl_default) 
 390 
            % if default: only today u(cmin), transition out next period, debt wiped out
  0.041 
   2025 
 391
            fl_v_default = fl_u_cmin + fl_beta*f_interpolante_w_level_pos_ev_z(fl_default_wprime); 
  0.045 
   2025 
 392
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_v_default*(mt_it_c_valid_idx); 
 393 
        else
 394 
            % if default is not allowed: v = u(cmin)
 395 
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_nan_replace*(mt_it_c_valid_idx);
< 0.001 
   2025 
 396
        end 
 397 

 398 
        % percentage algorithm does not have invalid (check to make sure
 399 
        % min percent is not 0 in ffs_ipwkbz_fibs_get_funcgrid.m)
 400 
        % mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_u_neg_c*(mt_it_c_valid_idx);
 401 

 402 
        %% E. Optimize Over Choices: max_{w_perc} U(coh_level, w_perc, z)
 403 
        % Optimization: remember matlab is column major, rows must be
 404 
        % choices, columns must be states
 405 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
  0.113 
   2025 
 406
        [ar_opti_val_z, ar_opti_idx_z] = max(mt_utility); 
 407 

 408 
        % Generate Linear Opti Index
  0.006 
   2025 
 409
        [it_choies_n, it_states_n] = size(mt_utility); 
  0.026 
   2025 
 410
        ar_add_grid = linspace(0, it_choies_n*(it_states_n-1), it_states_n); 
  0.002 
   2025 
 411
        ar_opti_linear_idx_z = ar_opti_idx_z + ar_add_grid; 
 412 

  0.016 
   2025 
 413
        ar_opti_aprime_z = mt_w_astar_interp_z(ar_opti_linear_idx_z); 
  0.015 
   2025 
 414
        ar_opti_kprime_z = mt_w_kstar_interp_z(ar_opti_linear_idx_z); 
  0.017 
   2025 
 415
        ar_opti_c_z = f_cons(ar_interp_coh_grid, ar_opti_aprime_z, ar_opti_kprime_z); 
 416 

 417 
        % Handle Default is optimal or not
< 0.001 
   2025 
 418
        if (bl_default) 
 419 
            % if defaulting is optimal choice, at these states, not required
 420 
            % to default, non-default possible, but default could be optimal
  0.050 
   2025 
 421
            fl_default_opti_kprime = f_interpolante_w_level_pos_kstar_z(fl_default_wprime); 
  0.009 
   2025 
 422
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = fl_default_wprime - fl_default_opti_kprime; 
  0.005 
   2025 
 423
            ar_opti_kprime_z(ar_opti_c_z <= fl_c_min) = fl_default_opti_kprime; 
 424 
        else
 425 
            % if default is not allowed, then next period same state as now
 426 
            % this is absorbing state, this is the limiting case, single
 427 
            % state space point, lowest a and lowest shock has this.
 428 
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = min(ar_a_meshk);
 429 
            ar_opti_kprime_z(ar_opti_c_z <= fl_c_min) = min(ar_k_mesha);
< 0.001 
   2025 
 430
        end 
 431 

 432 
        %% F. Store Results
  0.010 
   2025 
 433
        mt_val(:,it_z_i) = ar_opti_val_z; 
  0.005 
   2025 
 434
        mt_pol_a(:,it_z_i) = ar_opti_aprime_z; 
  0.005 
   2025 
 435
        mt_pol_k(:,it_z_i) = ar_opti_kprime_z; 
  0.001 
   2025 
 436
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     15 
 437
            mt_pol_idx(:,it_z_i) = ar_opti_linear_idx_z; 
< 0.001 
     15 
 438
        end 
 439 

  0.002 
   2025 
 440
    end 
 441 

 442 
    %% Check Tolerance and Continuation
 443 

 444 
    % Difference across iterations
  0.049 
    135 
 445
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.078 
    135 
 446
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur) + norm(mt_pol_k - mt_pol_k_cur); 
  0.010 
    135 
 447
    ar_pol_a_perc_change = sum((mt_pol_a ~= mt_pol_a_cur))/(length(ar_interp_coh_grid)); 
  0.007 
    135 
 448
    ar_pol_k_perc_change = sum((mt_pol_k ~= mt_pol_k_cur))/(length(ar_interp_coh_grid)); 
  0.017 
    135 
 449
    mt_pol_perc_change(it_iter, :) = mean([ar_pol_a_perc_change;ar_pol_k_perc_change]); 
 450 

 451 
    % Update
  0.004 
    135 
 452
    mt_val_cur = mt_val; 
  0.003 
    135 
 453
    mt_pol_a_cur = mt_pol_a; 
  0.002 
    135 
 454
    mt_pol_k_cur = mt_pol_k; 
 455 

 456 
    % Print Iteration Results
< 0.001 
    135 
 457
    if (bl_display && (rem(it_iter, it_display_every)==0)) 
 458 
        fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 459 
            it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 460 
        tb_valpol_iter = array2table([mean(mt_val_cur,1);...
 461 
                                      mean(mt_pol_a_cur,1); ...
 462 
                                      mean(mt_pol_k_cur,1); ...
 463 
                                      mt_val_cur(length(ar_interp_coh_grid),:); ...
 464 
                                      mt_pol_a_cur(length(ar_interp_coh_grid),:); ...
 465 
                                      mt_pol_k_cur(length(ar_interp_coh_grid),:)]);
 466 
        tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 467 
        tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'mak', 'Hval', 'Hap', 'Hak'};
 468 
        disp('mval = mean(mt_val_cur,1), average value over a')
 469 
        disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 470 
        disp('mkp  = mean(mt_pol_k_cur,1), average choice over k')
 471 
        disp('Hval = mt_val_cur(it_ameshk_n,:), highest a state val')
 472 
        disp('Hap = mt_pol_a_cur(it_ameshk_n,:), highest a state choice')
 473 
        disp('mak = mt_pol_k_cur(it_ameshk_n,:), highest k state choice')
 474 
        disp(tb_valpol_iter);
 475 
    end
 476 

 477 
    % Continuation Conditions:
 478 
    % 1. if value function convergence criteria reached
 479 
    % 2. if policy function variation over iterations is less than
 480 
    % threshold
< 0.001 
    135 
 481
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 482
        bl_vfi_continue = false; 
  0.002 
    134 
 483
    elseif ((it_iter == it_maxiter_val) || ... 
    134 
 484
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    134 
 485
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 486 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 487
        it_iter_last = it_iter; 
< 0.001 
      1 
 488
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 489
    end 
 490 

  0.001 
    135 
 491
end 
 492 

 493 
%% Process Optimal Choices 1: Formal and Informal Choices
 494 

< 0.001 
      1 
 495
result_map = containers.Map('KeyType','char', 'ValueType','any'); 
< 0.001 
      1 
 496
result_map('mt_val') = mt_val; 
< 0.001 
      1 
 497
result_map('mt_pol_idx') = mt_pol_idx; 
 498 

 499 
% Find optimal Formal Informal Choices. Could have saved earlier, but was
 500 
% wasteful of resources
< 0.001 
      1 
 501
for it_z_i = 1:length(ar_z) 
< 0.001 
     15 
 502
    for it_coh_interp_j = 1:length(ar_interp_coh_grid) 
 503 

< 0.001 
  11580 
 504
        fl_coh = mt_interp_coh_grid_mesh_z(it_coh_interp_j, it_z_i); 
< 0.001 
  11580 
 505
        fl_a_opti = mt_pol_a(it_coh_interp_j, it_z_i); 
 506 

 507 
        % call formal and informal function.
  1.262 
  11580 
 508
        [fl_max_c, fl_opti_b_bridge, fl_opti_inf_borr_nobridge, fl_opti_for_borr, fl_opti_for_save] = ... 
  11580 
 509
            ffs_fibs_min_c_cost_bridge(fl_a_opti, fl_coh, param_map, support_map, armt_map, func_map); 
 510 

 511 
        % store savings and borrowing formal and inf optimal choices
< 0.001 
  11580 
 512
        mt_pol_b_with_r(it_coh_interp_j,it_z_i) = fl_max_c; 
< 0.001 
  11580 
 513
        mt_pol_b_bridge(it_coh_interp_j,it_z_i) = fl_opti_b_bridge; 
< 0.001 
  11580 
 514
        mt_pol_inf_borr_nobridge(it_coh_interp_j,it_z_i) = fl_opti_inf_borr_nobridge; 
< 0.001 
  11580 
 515
        mt_pol_for_borr(it_coh_interp_j,it_z_i) = fl_opti_for_borr; 
< 0.001 
  11580 
 516
        mt_pol_for_save(it_coh_interp_j,it_z_i) = fl_opti_for_save; 
 517 

  0.001 
  11580 
 518
    end 
< 0.001 
     15 
 519
end 
 520 

 521 
%% Process Optimal Choices 2: Store a, k, c, coh Results
 522 
%
 523 
% # *mt_interp_coh_grid_mesh_z*: Cash-on-hand period _t_.
 524 
% # *mt_pol_a*: Safe asset choice, principles only for ipwkbz_fibs
 525 
% # *cl_mt_pol_a_principleonly*: mt_pol_a is stored in
 526 
% cl_mt_pol_a_principle only. This is a shortcut because we need to keep
 527 
% cl_mt_pol_a for mt_pol_b_with_r for the _ds_ code.
 528 
% # *cl_mt_pol_a*: stores _mt_pol_b_with_r_ which has principles and
 529 
% interest rates, to be used with _ds_ code.
 530 
% # *mt_pol_a*: Safe asset choice, principles only for ipwkbz_fibs
 531 
% # *cl_mt_pol_k*: Risky asset choice, principles only for ipwkbz_fibs
 532 
% # *cl_mt_pol_c*: Consumption in _t_ given choices.
 533 
% # *cl_pol_b_with_r*: Consumption cost of _mt_pol_a_ in _t+1_, given the
 534 
% formal and informal choices that are optimal to minimize this consumption
 535 
% cost.
 536 
%
 537 

< 0.001 
      1 
 538
result_map('cl_mt_coh') = {mt_interp_coh_grid_mesh_z, zeros(1)}; 
< 0.001 
      1 
 539
result_map('cl_mt_pol_k') = {mt_pol_k, zeros(1)}; 
  0.001 
      1 
 540
result_map('cl_mt_pol_c') = {f_cons(mt_interp_coh_grid_mesh_z, mt_pol_a, mt_pol_k), zeros(1)}; 
 541 

< 0.001 
      1 
 542
result_map('cl_mt_pol_a') = {mt_pol_b_with_r, zeros(1)}; 
< 0.001 
      1 
 543
result_map('cl_mt_pol_a_principleonly') = {mt_pol_a, zeros(1)}; 
 544 

 545 
%% Process Optimal Choices 3: Store Formal and Informal Choices
< 0.001 
      1 
 546
result_map('cl_mt_pol_b_bridge') = {mt_pol_b_bridge, zeros(1)}; 
< 0.001 
      1 
 547
result_map('cl_mt_pol_inf_borr_nobridge') = {mt_pol_inf_borr_nobridge, zeros(1)}; 
< 0.001 
      1 
 548
result_map('cl_mt_pol_for_borr') = {mt_pol_for_borr, zeros(1)}; 
< 0.001 
      1 
 549
result_map('cl_mt_pol_for_save') = {mt_pol_for_save, zeros(1)}; 
 550 

 551 
%% Process Optimal Choices 4: List of Variable Names to be processed by distributional codes
 552 
% this list is needed for the ds codes to generate distribution,
 553 
% distributional statistcs will be computed for elements in the list here.
 554 

< 0.001 
      1 
 555
result_map('ar_st_pol_names') = ... 
 556 
    ["cl_mt_coh", "cl_mt_pol_a", "cl_mt_pol_k", "cl_mt_pol_c", "cl_mt_pol_a_principleonly", ...
 557 
    "cl_mt_pol_b_bridge", "cl_mt_pol_inf_borr_nobridge", "cl_mt_pol_for_borr", "cl_mt_pol_for_save"];
 558 

 559 
% Get Discrete Choice Outcomes
  0.004 
      1 
 560
result_map = ffs_fibs_identify_discrete(result_map, bl_input_override); 
 561 

 562 
%% End Timer and Profile
 563 

 564 
% End Timer
< 0.001 
      1 
 565
if (bl_time) 
< 0.001 
      1 
 566
    toc; 
< 0.001 
      1 
 567
end 
 568 

 569 
% End Profile
< 0.001 
      1 
 570
if (bl_profile) 
  0.004 
      1 
 571
    profile off 
 572 
    profile viewer
 573 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 574 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 575 
end
 576 

 577 
%% Post Solution Graph and Table Generation
 578 

 579 
if (bl_post)
 580 
    bl_input_override = true;
 581 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 582 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 583 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 584 

 585 
    armt_map('mt_coh_wkb_ori') = mt_coh_wkb;
 586 
    armt_map('ar_a_meshk_ori') = ar_a_meshk;
 587 
    armt_map('ar_k_mesha_ori') = ar_k_mesha;
 588 
    
 589 
    armt_map('mt_coh_wkb') = mt_interp_coh_grid_mesh_z;
 590 
    armt_map('it_ameshk_n') = length(ar_interp_coh_grid);
 591 
    armt_map('ar_a_meshk') = mt_interp_coh_grid_mesh_z(:,1);
 592 
    armt_map('ar_k_mesha') = zeros(size(mt_interp_coh_grid_mesh_z(:,1)) + 0);
 593 

 594 
    % Standard AZ graphs
 595 
    result_map = ff_akz_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 596 

 597 
    % Graphs for results_map with FIBS contents
 598 
    armt_map('ar_a') = ar_interp_coh_grid;
 599 
    result_map = ff_az_fibs_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 600 

 601 
end
 602 

 603 
%% Display Various Containers
 604 

 605 
if (bl_display_defparam)
 606 
    
 607 
    %% Display 1 support_map    
 608 
    fft_container_map_display(support_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 609 
        
 610 
    %% Display 2 armt_map
 611 
    fft_container_map_display(armt_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 612 

 613 
    %% Display 3 param_map
 614 
    fft_container_map_display(param_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 615 
    
 616 
    %% Display 4 func_map
 617 
    fft_container_map_display(func_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 618 
    
 619 
    %% Display 5 result_map
 620 
    fft_container_map_display(result_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 621 
    
 622 
end
 623 

 624 
end

Other subfunctions in this file are not included in this listing.