This is a static copy of a profile report

Home

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

Home

ff_ipwkbzr_vf_vecsv (Calls: 1, Time: 37.952 s)
Generated 28-Jul-2019 18:14:01 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_ipwkbzr\solve\ff_ipwkbzr_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
325
cl_mt_coh_wkb_mesh_z_r_borr{it...
76016.731 s44.1%
408
ff_ipwkbzr_evf(clmt_val_wkb_in...
1524.489 s11.8%
459
mt_ev_condi_z_max_interp_z = f...
83603.116 s8.2%
425
mt_w_kstar_interp_z = f_interp...
83602.648 s7.0%
453
cl_w_kstar_interp_z{it_z_i} = ...
83601.190 s3.1%
All other lines  9.779 s25.8%
Totals  37.952 s100% 
Children (called functions)

Function NameFunction TypeCallsTotal Time% TimeTime Plot
ff_ipwkbzr_evffunction1524.432 s11.7%
...coh,bprime,kprime)(coh-kprime-bprime)anonymous function167200.319 s0.8%
linspacefunction83600.143 s0.4%
meanfunction1520.016 s0.0%
Self time (built-ins, overhead, etc.)  33.042 s87.1%
Totals  37.952 s100% 
Code Analyzer results
Line numberMessage
77Use of brackets [] is unnecessary. Use parentheses to group, if needed.
81Use of brackets [] is unnecessary. Use parentheses to group, if needed.
89Use of brackets [] is unnecessary. Use parentheses to group, if needed.
116The value assigned to variable 'bl_input_override' might be unused.
Coverage results
Show coverage for parent directory
Total lines in function635
Non-code lines (comments, blank lines)353
Code lines (lines that can run)282
Code lines that did run95
Code lines that did not run187
Coverage (did run/can run)33.69 %
Function listing
time 
Calls 
 line
   7 
function result_map = ff_ipwkbzr_vf_vecsv(varargin)
   8 
%% FF_IPWKBZR_VF_VECSV solve infinite horizon exo shock + endo asset problem
   9 
% This program solves the infinite horizon dynamic savings and risky
  10 
% capital asset problem with some ar1 shock. This is the two step solution
  11 
% with interpolation and with percentage asset grids version of
  12 
% <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_iwkz_vf_vecsv.html
  13 
% ff_iwkz_vf_vecsv>. See that file for more descriptions.
  14 
%
  15 
% @param param_map container parameter container
  16 
%
  17 
% @param support_map container support container
  18 
%
  19 
% @param armt_map container container with states, choices and shocks
  20 
% grids that are inputs for grid based solution algorithm
  21 
%
  22 
% @param func_map container container with function handles for
  23 
% consumption cash-on-hand etc.
  24 
%
  25 
% @return result_map container contains policy function matrix, value
  26 
% function matrix, iteration results, and policy function, value function
  27 
% and iteration results tables.
  28 
%
  29 
% keys included in result_map:
  30 
%
  31 
% * mt_val matrix states_n by shock_n matrix of converged value function grid
  32 
% * mt_pol_a matrix states_n by shock_n matrix of converged policy function grid
  33 
% * ar_val_diff_norm array if bl_post = true it_iter_last by 1 val function
  34 
% difference between iteration
  35 
% * ar_pol_diff_norm array if bl_post = true it_iter_last by 1 policy
  36 
% function difference between iterations
  37 
% * mt_pol_perc_change matrix if bl_post = true it_iter_last by shock_n the
  38 
% proportion of grid points at which policy function changed between
  39 
% current and last iteration for each element of shock
  40 
%
  41 
% @example
  42 
%
  43 
% @include
  44 
%
  45 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbzr/paramfunc/ff_ipwkbzr_evf.m ff_ipwkbzr_evf>
  46 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbzr/paramfunc/ffs_ipwkbzr_set_default_param.m ffs_ipwkbzr_set_default_param>
  47 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_ipwkbzr/paramfunc/ffs_ipwkbzr_get_funcgrid.m ffs_ipwkbzr_get_funcgrid>
  48 
% * <https://github.com/FanWangEcon/CodeDynaAsset/blob/master/m_akz/solvepost/ff_akz_vf_post.m ff_akz_vf_post>
  49 
%
  50 

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

  57 
it_param_set = 3;
  58 
[param_map, support_map] = ffs_ipwkbzr_set_default_param(it_param_set);
  59 

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

  75 
st_param_which = 'default';
  76 

  77 
if (ismember(st_param_which, ['default']))
  78 

  79 
    % default
  80 

  81 
elseif (ismember(st_param_which, ['small']))
  82 

  83 
    param_map('it_w_perc_n') = 20;
  84 
    param_map('it_ak_perc_n') = param_map('it_w_perc_n');
  85 
    param_map('it_z_wage_n') = 4;
  86 
    param_map('fl_z_r_borr_n') = 4;
  87 
    param_map('it_z_n') = param_map('it_z_wage_n') * param_map('fl_z_r_borr_n');
  88 

  89 
elseif ismember(st_param_which, ['ff_ipwkbz_vf_vecsv'])
  90 

  91 
    % ff_ipwkbzr_evf default
  92 
    param_map('fl_z_r_borr_min') = 0.095;
  93 
    param_map('fl_z_r_borr_max') = 0.095;
  94 
    param_map('fl_z_r_borr_n') = 1;
  95 

  96 
    param_map('fl_r_save') = 0.025;
  97 

  98 
    param_map('it_z_n') = param_map('it_z_wage_n') * param_map('fl_z_r_borr_n');
  99 

 100 
end
 101 

 102 
% get armt and func map
 103 
[armt_map, func_map] = ffs_ipwkbzr_get_funcgrid(param_map, support_map); % 1 for override
 104 
default_params = {param_map support_map armt_map func_map};
 105 

 106 
%% Parse Parameters 1
 107 

 108 
% if varargin only has param_map and support_map,
 109 
params_len = length(varargin);
 110 
[default_params{1:params_len}] = varargin{:};
 111 
param_map = [param_map; default_params{1}];
 112 
support_map = [support_map; default_params{2}];
 113 
if params_len >= 1 && params_len <= 2
 114 
    % If override param_map, re-generate armt and func if they are not
 115 
    % provided
 116 
    bl_input_override = true;
 117 
    [armt_map, func_map] = ffs_ipwkbzr_get_funcgrid(param_map, support_map);
 118 
else
 119 
    % Override all
 120 
    armt_map = [armt_map; default_params{3}];
 121 
    func_map = [func_map; default_params{4}];
 122 
end
 123 

 124 
% append function name
 125 
st_func_name = 'ff_ipwkbzr_vf_vecsv';
 126 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 127 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 128 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 129 

 130 
%% Parse Parameters 2, Asset Arrays
 131 
% Dimensions of Various Grids: I for level grid, M for shock grid, P for
 132 
% percent grid
 133 
%
 134 
% # ar_interp_c_grid: 1 by I^c, 1st stage consumption interpolation
 135 
% # ar_interp_coh_grid: 1 by I^{coh}, 1st stage value function V(coh,z)
 136 
% # ar_w_perc: 1 by P^{W=k+b}, 1st stage w \in {w_perc(coh)} choice set
 137 
% # ar_w_level: 1 by I^{W=k+b}, 2nd stage k*(w,z) w grid
 138 
% # ar_ak_perc: 1 by P^{k and b}, 2nd stage k \in {ask_perc(w,z)} set
 139 
%
 140 

 141 
params_group = values(armt_map, {...
 142 
    'ar_interp_c_grid', 'ar_interp_coh_grid', ...
 143 
    'ar_w_perc', 'ar_w_level', 'ar_ak_perc'});
 144 
[ar_interp_c_grid, ar_interp_coh_grid, ...
 145 
    ar_w_perc, ar_w_level, ar_ak_perc] = params_group{:};
 146 

 147 
%% Parse Parameters 2, interp_coh related matrixes
 148 
% Dimensions of Various Grids: I for level grid, M for shock grid, P for
 149 
% percent grid. These are grids for 1st stage solution
 150 
%
 151 
% # mt_interp_coh_grid_mesh_z_wage: I^{coh} by M^w
 152 
% # mt_z_wage_mesh_interp_coh_grid: I^{coh} by M^w
 153 
% # mt_interp_coh_grid_mesh_w_perc: I^{coh} by P^{LAM=k+b}
 154 
% # mt_w_perc_mesh_interp_coh_grid: I^{coh} by P^{LAM=k+b}
 155 
%
 156 

 157 
params_group = values(armt_map, {...
 158 
    'mt_interp_coh_grid_mesh_z_wage', ...
 159 
    'mt_interp_coh_grid_mesh_w_perc', ...
 160 
    'mt_z_wage_mesh_interp_coh_grid', ...
 161 
    'mt_w_perc_mesh_interp_coh_grid', ...
 162 
    'mt_interp_coh_grid_mesh_z', 'mt_z_mesh_interp_coh_grid', ...
 163 
    'cl_mt_coh_wkb_mesh_z_r_borr', 'mt_z_mesh_coh_wkb_seg'});
 164 
[mt_interp_coh_grid_mesh_z_wage, ...
 165 
    mt_interp_coh_grid_mesh_w_perc, ...
 166 
    mt_z_wage_mesh_interp_coh_grid, ...
 167 
    mt_w_perc_mesh_interp_coh_grid, ...
 168 
    mt_interp_coh_grid_mesh_z, mt_z_mesh_interp_coh_grid, ...
 169 
    cl_mt_coh_wkb_mesh_z_r_borr, mt_z_mesh_coh_wkb_seg] = params_group{:};
 170 

 171 
%% Parse Parameters 3, reachable cash-on-hand
 172 
% Dimensions of Various Grids: I for level grid, M for shock grid, P for
 173 
% percent grid. These are grids for 1st stage solution
 174 
%
 175 
% # mt_coh_wkb: (I^k x I^w x M^r) by (M^z)
 176 
% # mt_z_wage_mesh_coh_wkb: (I^k x I^w x M^r) by (M^z)
 177 
%
 178 

 179 
params_group = values(armt_map, {...
 180 
    'mt_coh_wkb', 'mt_coh_wkb_mesh_z_r_borr', 'mt_z_mesh_coh_wkb', 'mt_z_wage_mesh_coh_wkb'});
 181 
[mt_coh_wkb, mt_coh_wkb_mesh_z_r_borr, mt_z_mesh_coh_wkb, mt_z_wage_mesh_coh_wkb] = params_group{:};
 182 

 183 
%% Parse Parameters 4, other asset arrays
 184 

 185 
params_group = values(armt_map, {'ar_a_meshk', 'ar_k_mesha'});
 186 
[ar_a_meshk, ar_k_mesha] = params_group{:};
 187 

 188 
%% Parse Parameters 5, Others
 189 

 190 
% func_map
 191 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_cons'});
 192 
[f_util_log, f_util_crra, f_cons] = params_group{:};
 193 

 194 
% param_map
 195 
params_group = values(param_map, {'fl_crra', 'fl_beta', ...
 196 
    'fl_nan_replace', 'fl_c_min', 'bl_default', 'fl_default_wprime'});
 197 
[fl_crra, fl_beta, fl_nan_replace, fl_c_min, bl_default, fl_default_wprime] = params_group{:};
 198 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 199 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 200 
params_group = values(param_map, {'it_z_n', 'fl_z_r_borr_n', 'it_z_wage_n'});
 201 
[it_z_n, fl_z_r_borr_n, it_z_wage_n] = params_group{:};
 202 
params_group = values(param_map, {'st_v_coh_z_interp_method'});
 203 
[st_v_coh_z_interp_method] = params_group{:};
 204 

 205 
% support_map
 206 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 207 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 208 
    'bl_time', 'bl_display_defparam', 'bl_graph_evf', 'bl_display', 'it_display_every', 'bl_post'});
 209 
[bl_profile, st_profile_path, ...
 210 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 211 
    bl_time, bl_display_defparam, bl_graph_evf, bl_display, it_display_every, bl_post] = params_group{:};
 212 
params_group = values(support_map, {'it_display_summmat_rowmax', 'it_display_summmat_colmax'});
 213 
[it_display_summmat_rowmax, it_display_summmat_colmax] = params_group{:};
 214 

 215 
%% Initialize Output Matrixes
 216 

 217 
mt_val_cur = zeros(length(ar_interp_coh_grid),it_z_n);
 218 
mt_val = mt_val_cur - 1;
 219 
mt_pol_a = zeros(length(ar_interp_coh_grid),it_z_n);
 220 
mt_pol_a_cur = mt_pol_a - 1;
 221 
mt_pol_k = zeros(length(ar_interp_coh_grid),it_z_n);
 222 
mt_pol_k_cur = mt_pol_k - 1;
 223 
mt_pol_idx = zeros(length(ar_interp_coh_grid),it_z_n);
 224 

 225 
% We did not need these in ff_oz_vf or ff_oz_vf_vec
 226 
% see
 227 
% <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 228 
% fs_u_c_partrepeat_main> for why store using cells.
 229 
cl_u_c_store = cell([it_z_n, 1]);
 230 
cl_c_valid_idx = cell([it_z_n, 1]);
 231 
cl_w_kstar_interp_z = cell([it_z_n, 1]);
 232 
for it_z_i = 1:it_z_n
 233 
    cl_w_kstar_interp_z{it_z_i} = zeros([length(ar_w_perc), length(ar_interp_coh_grid)]) - 1;
 234 
end
 235 

 236 
clmt_val_wkb_interpolated = cell([fl_z_r_borr_n, 1]);
 237 

 238 
%% Initialize Convergence Conditions
 239 

 240 
bl_vfi_continue = true;
 241 
it_iter = 0;
 242 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 243 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 244 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 245 

 246 
%% Pre-calculate u(c)
 247 
% Interpolation, see
 248 
% <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 249 
% fs_u_c_partrepeat_main> for why interpolate over u(c)
 250 

 251 
% Evaluate
 252 
if (fl_crra == 1)
 253 
    ar_interp_u_of_c_grid = f_util_log(ar_interp_c_grid);
 254 
    fl_u_cmin = f_util_log(fl_c_min);
 255 
else
 256 
    ar_interp_u_of_c_grid = f_util_crra(ar_interp_c_grid);
 257 
    fl_u_cmin = f_util_crra(fl_c_min);
 258 
end
 259 
ar_interp_u_of_c_grid(ar_interp_c_grid <= fl_c_min) = fl_u_cmin;
 260 

 261 
% Get Interpolant
 262 
f_grid_interpolant_spln = griddedInterpolant(ar_interp_c_grid, ar_interp_u_of_c_grid, 'spline', 'nearest');
 263 

 264 
%% Iterate Value Function
 265 
% Loop solution with 4 nested loops
 266 
%
 267 
% # loop 1: over exogenous states
 268 
% # loop 2: over endogenous states
 269 
% # loop 3: over choices
 270 
% # loop 4: add future utility, integration--loop over future shocks
 271 
%
 272 

 273 
% Start Profile
 274 
if (bl_profile)
 275 
    close all;
 276 
    profile off;
 277 
    profile on;
< 0.001 
      1 
 278
end 
 279 

 280 
% Start Timer
< 0.001 
      1 
 281
if (bl_time) 
< 0.001 
      1 
 282
    tic; 
< 0.001 
      1 
 283
end 
 284 

 285 
% Value Function Iteration
< 0.001 
      1 
 286
while bl_vfi_continue 
< 0.001 
    152 
 287
    it_iter = it_iter + 1; 
 288 

 289 
    %% Interpolate V(coh, Z) 1: Splinterp2
 290 
    % Interpolate reacahble V(coh(k'(w),b'(w),zr,zw'),zw',zr')) given v(coh, z)
 291 

  0.001 
    152 
 292
    if (strcmp(st_v_coh_z_interp_method, 'method_idx_a')) 
 293 
        for it_z_r_borr_ctr = 1:1:fl_z_r_borr_n
 294 
            clmt_val_wkb_interpolated{it_z_r_borr_ctr} = ...
 295 
                splinterp2(mt_val_cur,mt_z_mesh_coh_wkb_seg,cl_mt_coh_wkb_mesh_z_r_borr{it_z_r_borr_ctr});
 296 
        end
 297 
    end
 298 

 299 
    %% Interpolate V(coh, Z) 2: griddedInterpolant(V)
 300 
    % Interpolate reacahble V(coh(k'(w),b'(w),zr,zw'),zw',zr')) given v(coh, z)
 301 

< 0.001 
    152 
 302
    if (strcmp(st_v_coh_z_interp_method, 'method_idx_b')) 
 303 
        % Generate Interpolant for v(coh,z)
 304 
        % mt_z_wage_mesh_interp_coh_grid is: (I^{coh_interp}) by (M^z)
 305 
        f_grid_interpolant_value = griddedInterpolant(mt_val_cur', 'linear', 'nearest');
 306 
        for it_z_r_borr_ctr = 1:1:fl_z_r_borr_n
 307 
            clmt_val_wkb_interpolated{it_z_r_borr_ctr} = ...
 308 
                f_grid_interpolant_value(mt_z_mesh_coh_wkb_seg,...
 309 
                                         cl_mt_coh_wkb_mesh_z_r_borr{it_z_r_borr_ctr});
 310 
        end
 311 
    end
 312 

 313 
    %% Interpolate V(coh, Z) 3: Store in Cell
 314 
    % Interpolate reacahble V(coh(k'(w),b'(w),zr,zw'),zw',zr')) given v(coh, z)
 315 

  0.001 
    152 
 316
    if (strcmp(st_v_coh_z_interp_method, 'method_cell')) 
  0.199 
    152 
 317
        f_grid_interpolant_value = griddedInterpolant(... 
    152 
 318
            mt_z_mesh_interp_coh_grid', mt_interp_coh_grid_mesh_z', ... 
    152 
 319
            mt_val_cur', 'linear', 'nearest'); 
 320 

< 0.001 
    152 
 321
        for it_z_r_borr_ctr = 1:1:fl_z_r_borr_n 
 322 

 16.732 
    760 
 323
            clmt_val_wkb_interpolated{it_z_r_borr_ctr} = ... 
    760 
 324
                f_grid_interpolant_value(mt_z_mesh_coh_wkb_seg,... 
    760 
 325
                                         cl_mt_coh_wkb_mesh_z_r_borr{it_z_r_borr_ctr}); 
  0.003 
    760 
 326
        end 
< 0.001 
    152 
 327
    end 
 328 

 329 

 330 
    %% Interpolate V(coh, Z) 4: Single Call Full Matrix
 331 
    % Interpolate reacahble V(coh(k'(w),b'(w),zr,zw'),zw',zr')) given v(coh, z)
 332 

  0.002 
    152 
 333
    if (strcmp(st_v_coh_z_interp_method, 'method_matrix')) 
 334 
        % Generate Interpolant for v(coh,z)
 335 
        % mt_z_wage_mesh_interp_coh_grid is: (I^{coh_interp}) by (M^z)
 336 
        f_grid_interpolant_value = griddedInterpolant(...
 337 
            mt_z_mesh_interp_coh_grid', mt_interp_coh_grid_mesh_z', ...
 338 
            mt_val_cur', 'linear', 'nearest');
 339 

 340 
        % Interpolate V(coh(k',b',z',r),z',r') for a specific r'
 341 
        % mt_z_wage_mesh_coh_wkb and mt_coh_wkb are: (I^k x I^w x M^r) by (M^z)
 342 
        clmt_val_wkb_interpolated = f_grid_interpolant_value(mt_z_mesh_coh_wkb, mt_coh_wkb_mesh_z_r_borr);
 343 
    end
 344 

 345 
    %% Interpolate V(coh, Z) 5: Matrix Store
 346 
    % Interpolate reacahble V(coh(k'(w),b'(w),zr,zw'),zw',zr')) given v(coh, z)
 347 

< 0.001 
    152 
 348
    if (strcmp(st_v_coh_z_interp_method, 'method_mat_seg')) 
 349 

 350 
        % 1. Number of W/B/K Choice Combinations
 351 
        it_ak_perc_n = length(ar_ak_perc);
 352 
        it_w_interp_n = length(ar_w_level);
 353 
        it_wak_n = it_w_interp_n*it_ak_perc_n;
 354 

 355 
        % 2. Initialize V(coh(k'(w),b'(w),zr,zw'),zw',zr'))
 356 
        % mt_val_wkb_interpolated is: (I^k x I^w x M^r) by (M^z x M^r)
 357 
        % reachable cash-on-hand (as rows) and shocks next period given choices
 358 
        % and shocks next period.
 359 
        clmt_val_wkb_interpolated = zeros([it_wak_n*fl_z_r_borr_n, it_z_n]);
 360 

 361 
        % 3. Loop over possible shocks over interest rate
 362 
        for it_z_r_borr_ctr = 1:1:fl_z_r_borr_n
 363 

 364 
            % 4. Interpolate V(coh(k',b',z',r),z',r') for a specific r'
 365 
            % v(coh,z) solved on ar_interp_coh_grid, ar_z grids, see
 366 
            % ffs_ipwkbzr_get_funcgrid.m. Generate interpolant based on that, Then
 367 
            % interpolate for the coh reachable levels given the k(w,z) percentage
 368 
            % choice grids in the second stage of the problem.
 369 
            %
 370 
            % Note mt_val_cur/mt_val dimension is based on interpolant
 371 
            % cash-on-hand for rows, and meshed shocks for columns. The meshed
 372 
            % shock structure, see
 373 
            % <https://fanwangecon.github.io/CodeDynaAsset/m_ipwkbzr/paramfunc/html/ffs_ipwkbzr_get_funcgrid.html
 374 
            % ffs_ipwkbzr_get_funcgrid> for details on how the shock grids are
 375 
            % formed.
 376 

 377 
            % Get current z_r_borr from mt_val
 378 
            it_mt_val_col_start = it_z_wage_n*(it_z_r_borr_ctr-1) + 1;
 379 
            it_mt_val_col_end   = it_mt_val_col_start + it_z_wage_n - 1;
 380 
            mt_val_cur_rcolseg =  mt_val_cur(:, it_mt_val_col_start:it_mt_val_col_end);
 381 

 382 
            % Generate Interpolant for v(coh,z)
 383 
            % mt_z_wage_mesh_interp_coh_grid is: (I^{coh_interp}) by (M^z)
 384 
            f_grid_interpolant_value = griddedInterpolant(...
 385 
                mt_z_wage_mesh_interp_coh_grid', mt_interp_coh_grid_mesh_z_wage', ...
 386 
                mt_val_cur_rcolseg', 'linear', 'nearest');
 387 

 388 
            % Interpolate V(coh(k',b',z',r),z',r') for a specific r'
 389 
            % mt_z_wage_mesh_coh_wkb and mt_coh_wkb are: (I^k x I^w x M^r) by (M^z)
 390 
            mt_val_wkb_interpolated_seg = f_grid_interpolant_value(mt_z_wage_mesh_coh_wkb, mt_coh_wkb);
 391 
            clmt_val_wkb_interpolated(:, it_mt_val_col_start:it_mt_val_col_end) = mt_val_wkb_interpolated_seg;
 392 

 393 
        end
 394 
    end
 395 

 396 
    %% Solve Second Stage Problem k*(w,z)
 397 
    % This is the key difference between this function and
 398 
    % <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/html/ffs_akz_set_functions.html
 399 
    % ffs_akz_set_functions> which solves the two stages jointly
 400 
    % Interpolation first, because solution coh grid is not the same as all
 401 
    % points reachable by k and b choices given w.
  0.026 
    152 
 402
    support_map('bl_graph_evf') = false; 
< 0.001 
    152 
 403
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 404
        support_map('bl_graph_evf') = bl_graph_evf; 
< 0.001 
      1 
 405
    end 
< 0.001 
    152 
 406
    bl_input_override = true; 
  4.489 
    152 
 407
    [mt_ev_condi_z_max, ~, mt_ev_condi_z_max_kp, ~] = ... 
    152 
 408
        ff_ipwkbzr_evf(clmt_val_wkb_interpolated, param_map, support_map, armt_map, bl_input_override); 
 409 

 410 
    %% Solve First Stage Problem w*(z) given k*(w,z)
 411 

 412 
    % loop 1: over exogenous states
< 0.001 
    152 
 413
    for it_z_i = 1:it_z_n 
 414 

 415 
        %% A. Interpolate FULL to get k*(w_perc, z), b*(k,w) based on k*(w_level, z)
 416 
        % Generate interpolant for (2) k*(ar_w_perc) from k*(ar_w_level,z)
 417 
        % There are two w=k'+b' arrays. ar_w_level is the level even grid based
 418 
        % on which we solve the 2nd stage problem in ff_ipwkbzr_evf.m. Here for
 419 
        % each coh level, we have a different vector of w levels, but the same
 420 
        % vector of percentage ws. So we need to interpolate to get the optimal
 421 
        % k* and b* choices at each percentage level of w.
  0.516 
   8360 
 422
        f_interpolante_w_level_kstar_z = griddedInterpolant(ar_w_level, mt_ev_condi_z_max_kp(:, it_z_i)', 'linear', 'nearest'); 
 423 

 424 
        % Interpolate (2), shift from w_level to w_perc
  2.648 
   8360 
 425
        mt_w_kstar_interp_z = f_interpolante_w_level_kstar_z(mt_w_perc_mesh_interp_coh_grid); 
  0.283 
   8360 
 426
        mt_w_astar_interp_z = mt_w_perc_mesh_interp_coh_grid - mt_w_kstar_interp_z; 
 427 

 428 
        % changes in w_perc kstar choices
  0.310 
   8360 
 429
        mt_w_kstar_diff_idx = (cl_w_kstar_interp_z{it_z_i} ~= mt_w_kstar_interp_z); 
 430 

 431 
        %% B. Calculate UPDATE u(c): u(c(coh_level, w_perc)) given k*_interp, b*_interp
 432 
        % Note that compared to
 433 
        % <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/html/ffs_akz_set_functions.html
 434 
        % ffs_akz_set_functions> the mt_c here is much smaller the same
 435 
        % number of columns (states) as in the ffs_akz_set_functions file,
 436 
        % but the number of rows equal to ar_w length.
  1.933 
   8360 
 437
        ar_c = f_cons(mt_interp_coh_grid_mesh_w_perc(mt_w_kstar_diff_idx), ... 
   8360 
 438
            mt_w_astar_interp_z(mt_w_kstar_diff_idx), ... 
   8360 
 439
            mt_w_kstar_interp_z(mt_w_kstar_diff_idx)); 
 440 

  0.059 
   8360 
 441
        ar_it_c_valid_idx = (ar_c <= fl_c_min); 
 442 
        % EVAL current utility: N by N, f_util defined earlier
  0.826 
   8360 
 443
        ar_utility_update = f_grid_interpolant_spln(ar_c); 
 444 

 445 
        % Update Storage
  0.003 
   8360 
 446
        if (it_iter == 1) 
  0.002 
     55 
 447
            cl_u_c_store{it_z_i} = reshape(ar_utility_update, [length(ar_w_perc), length(ar_interp_coh_grid)]); 
< 0.001 
     55 
 448
            cl_c_valid_idx{it_z_i} = reshape(ar_it_c_valid_idx, [length(ar_w_perc), length(ar_interp_coh_grid)]); 
  0.001 
   8305 
 449
        else 
  0.506 
   8305 
 450
            cl_u_c_store{it_z_i}(mt_w_kstar_diff_idx) = ar_utility_update; 
  0.441 
   8305 
 451
            cl_c_valid_idx{it_z_i}(mt_w_kstar_diff_idx) = ar_it_c_valid_idx; 
< 0.001 
   8360 
 452
        end 
  1.190 
   8360 
 453
        cl_w_kstar_interp_z{it_z_i} = mt_w_kstar_interp_z; 
 454 

 455 
        %% C. Interpolate FULL EV(k*(coh_level, w_perc, z), w - b*|z) based on EV(k*(w_level, z))
 456 
        % Generate Interpolant for (3) EV(k*(ar_w_perc),Z)
  0.573 
   8360 
 457
        f_interpolante_ev_condi_z_max_z = griddedInterpolant(ar_w_level, mt_ev_condi_z_max(:, it_z_i)', 'linear', 'nearest'); 
 458 
        % Interpolate (3), EVAL add on future utility, N by N + N by N
  3.116 
   8360 
 459
        mt_ev_condi_z_max_interp_z = f_interpolante_ev_condi_z_max_z(mt_w_perc_mesh_interp_coh_grid); 
 460 

 461 
        %% D. Compute FULL U(coh_level, w_perc, z) over all w_perc
  0.398 
   8360 
 462
        mt_utility = cl_u_c_store{it_z_i} + fl_beta*mt_ev_condi_z_max_interp_z; 
 463 

 464 
        % Index update
 465 
        % using the method below is much faster than index replace
 466 
        % see <https://fanwangecon.github.io/M4Econ/support/speed/index/fs_subscript.html fs_subscript>
  0.010 
   8360 
 467
        mt_it_c_valid_idx = cl_c_valid_idx{it_z_i}; 
 468 
        % Default or Not Utility Handling
  0.002 
   8360 
 469
        if (bl_default) 
 470 
            % if default: only today u(cmin), transition out next period, debt wiped out
  0.366 
   8360 
 471
            fl_v_default = fl_u_cmin + fl_beta*f_interpolante_ev_condi_z_max_z(fl_default_wprime); 
  0.457 
   8360 
 472
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_v_default*(mt_it_c_valid_idx); 
 473 
        else
 474 
            % if default is not allowed: v = u(cmin)
 475 
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_nan_replace*(mt_it_c_valid_idx);
  0.001 
   8360 
 476
        end 
 477 

 478 
        % percentage algorithm does not have invalid (check to make sure
 479 
        % min percent is not 0 in ffs_ipwkbzr_get_funcgrid.m)
 480 
        % mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_u_neg_c*(mt_it_c_valid_idx);
 481 

 482 
        %% E. Optimize Over Choices: max_{w_perc} U(coh_level, w_perc, z)
 483 
        % Optimization: remember matlab is column major, rows must be
 484 
        % choices, columns must be states
 485 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
  0.857 
   8360 
 486
        [ar_opti_val_z, ar_opti_idx_z] = max(mt_utility); 
 487 

 488 
        % Generate Linear Opti Index
  0.063 
   8360 
 489
        [it_choies_n, it_states_n] = size(mt_utility); 
  0.205 
   8360 
 490
        ar_add_grid = linspace(0, it_choies_n*(it_states_n-1), it_states_n); 
  0.015 
   8360 
 491
        ar_opti_linear_idx_z = ar_opti_idx_z + ar_add_grid; 
 492 

  0.122 
   8360 
 493
        ar_opti_aprime_z = mt_w_astar_interp_z(ar_opti_linear_idx_z); 
  0.109 
   8360 
 494
        ar_opti_kprime_z = mt_w_kstar_interp_z(ar_opti_linear_idx_z); 
  0.116 
   8360 
 495
        ar_opti_c_z = f_cons(ar_interp_coh_grid, ar_opti_aprime_z, ar_opti_kprime_z); 
 496 

 497 
        % Handle Default is optimal or not
  0.002 
   8360 
 498
        if (bl_default) 
 499 
            % if defaulting is optimal choice, at these states, not required
 500 
            % to default, non-default possible, but default could be optimal
  0.370 
   8360 
 501
            fl_default_opti_kprime = f_interpolante_w_level_kstar_z(fl_default_wprime); 
  0.065 
   8360 
 502
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = fl_default_wprime - fl_default_opti_kprime; 
  0.036 
   8360 
 503
            ar_opti_kprime_z(ar_opti_c_z <= fl_c_min) = fl_default_opti_kprime; 
 504 
        else
 505 
            % if default is not allowed, then next period same state as now
 506 
            % this is absorbing state, this is the limiting case, single
 507 
            % state space point, lowest a and lowest shock has this.
 508 
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = min(ar_a_meshk);
 509 
            ar_opti_kprime_z(ar_opti_c_z <= fl_c_min) = min(ar_k_mesha);
< 0.001 
   8360 
 510
        end 
 511 

 512 
        %% F. Store Results
  0.064 
   8360 
 513
        mt_val(:,it_z_i) = ar_opti_val_z; 
  0.047 
   8360 
 514
        mt_pol_a(:,it_z_i) = ar_opti_aprime_z; 
  0.044 
   8360 
 515
        mt_pol_k(:,it_z_i) = ar_opti_kprime_z; 
  0.003 
   8360 
 516
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     55 
 517
            mt_pol_idx(:,it_z_i) = ar_opti_linear_idx_z; 
< 0.001 
     55 
 518
        end 
 519 

  0.004 
   8360 
 520
    end 
 521 

 522 
    %% Check Tolerance and Continuation
 523 

 524 
    % Difference across iterations
  0.220 
    152 
 525
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.391 
    152 
 526
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur) + norm(mt_pol_k - mt_pol_k_cur); 
  0.027 
    152 
 527
    ar_pol_a_perc_change = sum((mt_pol_a ~= mt_pol_a_cur))/(length(ar_interp_coh_grid)); 
  0.022 
    152 
 528
    ar_pol_k_perc_change = sum((mt_pol_k ~= mt_pol_k_cur))/(length(ar_interp_coh_grid)); 
  0.023 
    152 
 529
    mt_pol_perc_change(it_iter, :) = mean([ar_pol_a_perc_change;ar_pol_k_perc_change]); 
 530 

 531 
    % Update
  0.017 
    152 
 532
    mt_val_cur = mt_val; 
  0.011 
    152 
 533
    mt_pol_a_cur = mt_pol_a; 
  0.010 
    152 
 534
    mt_pol_k_cur = mt_pol_k; 
 535 

 536 
    % Print Iteration Results
< 0.001 
    152 
 537
    if (bl_display && (rem(it_iter, it_display_every)==0)) 
 538 
        fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 539 
            it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 540 
        tb_valpol_iter = array2table([mean(mt_val_cur,1);...
 541 
            mean(mt_pol_a_cur,1); ...
 542 
            mean(mt_pol_k_cur,1); ...
 543 
            mt_val_cur(length(ar_interp_coh_grid),:); ...
 544 
            mt_pol_a_cur(length(ar_interp_coh_grid),:); ...
 545 
            mt_pol_k_cur(length(ar_interp_coh_grid),:)]);
 546 
        tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 547 
        tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'mak', 'Hval', 'Hap', 'Hak'};
 548 
        disp('mval = mean(mt_val_cur,1), average value over a')
 549 
        disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 550 
        disp('mkp  = mean(mt_pol_k_cur,1), average choice over k')
 551 
        disp('Hval = mt_val_cur(it_ameshk_n,:), highest a state val')
 552 
        disp('Hap = mt_pol_a_cur(it_ameshk_n,:), highest a state choice')
 553 
        disp('mak = mt_pol_k_cur(it_ameshk_n,:), highest k state choice')
 554 
        disp(tb_valpol_iter);
 555 
    end
 556 

 557 
    % Continuation Conditions:
 558 
    % 1. if value function convergence criteria reached
 559 
    % 2. if policy function variation over iterations is less than
 560 
    % threshold
< 0.001 
    152 
 561
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 562
        bl_vfi_continue = false; 
  0.002 
    151 
 563
    elseif ((it_iter == it_maxiter_val) || ... 
    151 
 564
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    151 
 565
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 566 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 567
        it_iter_last = it_iter; 
< 0.001 
      1 
 568
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 569
    end 
 570 

< 0.001 
    152 
 571
end 
 572 

 573 
% End Timer
< 0.001 
      1 
 574
if (bl_time) 
< 0.001 
      1 
 575
    toc; 
< 0.001 
      1 
 576
end 
 577 

 578 
% End Profile
< 0.001 
      1 
 579
if (bl_profile) 
  0.002 
      1 
 580
    profile off 
 581 
    profile viewer
 582 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 583 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 584 
end
 585 

 586 
%% Process Optimal Choices
 587 

 588 
result_map = containers.Map('KeyType','char', 'ValueType','any');
 589 
result_map('mt_val') = mt_val;
 590 
result_map('mt_pol_idx') = mt_pol_idx;
 591 

 592 
result_map('cl_mt_coh') = {mt_interp_coh_grid_mesh_z, zeros(1)};
 593 
result_map('cl_mt_pol_a') = {mt_pol_a, zeros(1)};
 594 
result_map('cl_mt_pol_k') = {mt_pol_k, zeros(1)};
 595 
mt_pol_c = f_cons(mt_interp_coh_grid_mesh_z, mt_pol_a, mt_pol_k);
 596 
mt_pol_c(mt_pol_c <= fl_c_min) = fl_c_min;
 597 
result_map('cl_mt_pol_c') = {mt_pol_c, zeros(1)};
 598 
result_map('ar_st_pol_names') = ["cl_mt_coh", "cl_mt_pol_a", "cl_mt_pol_k", "cl_mt_pol_c"];
 599 

 600 
if (bl_post)
 601 
    bl_input_override = true;
 602 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 603 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 604 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 605 

 606 
    armt_map('mt_coh_wkb_ori') = mt_coh_wkb;
 607 
    armt_map('ar_a_meshk_ori') = ar_a_meshk;
 608 
    armt_map('ar_k_mesha_ori') = ar_k_mesha;
 609 

 610 
    % graphing based on coh_wkb, but that does not match optimal choice
 611 
    % matrixes for graphs.
 612 
    armt_map('mt_coh_wkb') = mt_interp_coh_grid_mesh_z;
 613 
    armt_map('it_ameshk_n') = length(ar_interp_coh_grid);
 614 
    armt_map('ar_a_meshk') = mt_interp_coh_grid_mesh_z(:,1);
 615 
    armt_map('ar_k_mesha') = zeros(size(mt_interp_coh_grid_mesh_z(:,1)) + 0);
 616 

 617 
    result_map = ff_akz_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 618 
end
 619 

 620 
%% Display Various Containers
 621 

 622 
if (bl_display_defparam)
 623 

 624 
    %% Display 1 support_map
 625 
    fft_container_map_display(support_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 626 

 627 
    %% Display 2 armt_map
 628 
    fft_container_map_display(armt_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 629 

 630 
    %% Display 3 param_map
 631 
    fft_container_map_display(param_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 632 

 633 
    %% Display 4 func_map
 634 
    fft_container_map_display(func_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 635 

 636 
    %% Display 5 result_map
 637 
    fft_container_map_display(result_map, it_display_summmat_rowmax, it_display_summmat_colmax);
 638 

 639 
end
 640 

 641 
end

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