| time  | Calls  |  line | 
|---|
|  |  |    7  | function result_map = ff_iwkz_vf_vecsv(varargin)
 | 
|  |  |    8  | %% FF_IWKZ_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 efficient vectorized version
 | 
|  |  |   11  | % of
 | 
|  |  |   12  | % <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_iwkz_vf.html
 | 
|  |  |   13  | % ff_iwkz_vf>. 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://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/ff_wkz_evf.m ff_wkz_evf>
 | 
|  |  |   46  | % * <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/ffs_akz_set_default_param.m ffs_akz_set_default_param>
 | 
|  |  |   47  | % * <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/ffs_akz_get_funcgrid.m ffs_akz_get_funcgrid>
 | 
|  |  |   48  | % * <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solvepost/ff_akz_vf_post.m ff_akz_vf_post>
 | 
|  |  |   49  | %
 | 
|  |  |   50  | % @seealso
 | 
|  |  |   51  | %
 | 
|  |  |   52  | % * concurrent (safe + risky) loop: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_akz_vf.html ff_akz_vf>
 | 
|  |  |   53  | % * concurrent (safe + risky) vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_akz_vf_vec.html ff_akz_vf_vec>
 | 
|  |  |   54  | % * concurrent (safe + risky) optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_akz_vf_vecsv.html ff_akz_vf_vecsv>
 | 
|  |  |   55  | % * two-stage (safe + risky) loop: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_wkz_vf.html ff_wkz_vf>
 | 
|  |  |   56  | % * two-stage (safe + risky) vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_wkz_vf_vec.html ff_wkz_vf_vec>
 | 
|  |  |   57  | % * two-stage (safe + risky) optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_wkz_vf_vecsv.html ff_wkz_vf_vecsv>
 | 
|  |  |   58  | % * two-stage + interpolate (safe + risky) loop: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_iwkz_vf.html ff_iwkz_vf>
 | 
|  |  |   59  | % * two-stage + interpolate (safe + risky) vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_iwkz_vf_vec.html ff_iwkz_vf_vec>
 | 
|  |  |   60  | % * two-stage + interpolate (safe + risky) optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_akz/solve/html/ff_iwkz_vf_vecsv.html ff_iwkz_vf_vecsv>
 | 
|  |  |   61  | %
 | 
|  |  |   62  | 
 | 
|  |  |   63  | 
 | 
|  |  |   64  | %% Default
 | 
|  |  |   65  | % * it_param_set = 1: quick test
 | 
|  |  |   66  | % * it_param_set = 2: benchmark run
 | 
|  |  |   67  | % * it_param_set = 3: benchmark profile
 | 
|  |  |   68  | % * it_param_set = 4: press publish button
 | 
|  |  |   69  | 
 | 
|  |  |   70  | it_param_set = 4;
 | 
|  |  |   71  | bl_input_override = true;
 | 
|  |  |   72  | [param_map, support_map] = ffs_akz_set_default_param(it_param_set);
 | 
|  |  |   73  | 
 | 
|  |  |   74  | % Note: param_map and support_map can be adjusted here or outside to override defaults
 | 
|  |  |   75  | % param_map('it_w_n') = 50;
 | 
|  |  |   76  | % param_map('it_ak_n') = param_map('it_w_n');
 | 
|  |  |   77  | % param_map('it_z_n') = 15;
 | 
|  |  |   78  | % param_map('fl_coh_interp_grid_gap') = 0.1;
 | 
|  |  |   79  | % param_map('it_c_interp_grid_gap') = 10^-4;
 | 
|  |  |   80  | 
 | 
|  |  |   81  | % get armt and func map
 | 
|  |  |   82  | [armt_map, func_map] = ffs_akz_get_funcgrid(param_map, support_map, bl_input_override); % 1 for override
 | 
|  |  |   83  | default_params = {param_map support_map armt_map func_map};
 | 
|  |  |   84  | 
 | 
|  |  |   85  | %% Parse Parameters 1
 | 
|  |  |   86  | 
 | 
|  |  |   87  | % if varargin only has param_map and support_map,
 | 
|  |  |   88  | params_len = length(varargin);
 | 
|  |  |   89  | [default_params{1:params_len}] = varargin{:};
 | 
|  |  |   90  | param_map = [param_map; default_params{1}];
 | 
|  |  |   91  | support_map = [support_map; default_params{2}];
 | 
|  |  |   92  | if params_len >= 1 && params_len <= 2
 | 
|  |  |   93  |     % If override param_map, re-generate armt and func if they are not
 | 
|  |  |   94  |     % provided
 | 
|  |  |   95  |     bl_input_override = true;
 | 
|  |  |   96  |     [armt_map, func_map] = ffs_akz_get_funcgrid(param_map, support_map, bl_input_override);
 | 
|  |  |   97  | else
 | 
|  |  |   98  |     % Override all
 | 
|  |  |   99  |     armt_map = [armt_map; default_params{3}];
 | 
|  |  |  100  |     func_map = [func_map; default_params{4}];
 | 
|  |  |  101  | end
 | 
|  |  |  102  | 
 | 
|  |  |  103  | % append function name
 | 
|  |  |  104  | st_func_name = 'ff_iwkz_vf_vecsv';
 | 
|  |  |  105  | support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 | 
|  |  |  106  | support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 | 
|  |  |  107  | support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 | 
|  |  |  108  | 
 | 
|  |  |  109  | %% Parse Parameters 2
 | 
|  |  |  110  | 
 | 
|  |  |  111  | % armt_map
 | 
|  |  |  112  | params_group = values(armt_map, {'ar_w', 'ar_z'});
 | 
|  |  |  113  | [ar_w, ar_z] = params_group{:};
 | 
|  |  |  114  | params_group = values(armt_map, {'ar_interp_c_grid', 'ar_interp_coh_grid', ...
 | 
|  |  |  115  |     'mt_interp_coh_grid_mesh_z', 'mt_z_mesh_coh_interp_grid'});
 | 
|  |  |  116  | [ar_interp_c_grid, ar_interp_coh_grid, ...
 | 
|  |  |  117  |     mt_interp_coh_grid_mesh_z, mt_z_mesh_coh_interp_grid] = params_group{:};
 | 
|  |  |  118  | params_group = values(armt_map, {'mt_coh_wkb', 'mt_z_mesh_coh_wkb'});
 | 
|  |  |  119  | [mt_coh_wkb, mt_z_mesh_coh_wkb] = params_group{:};
 | 
|  |  |  120  | 
 | 
|  |  |  121  | % func_map
 | 
|  |  |  122  | params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_cons', 'f_coh'});
 | 
|  |  |  123  | [f_util_log, f_util_crra, f_cons, f_coh] = params_group{:};
 | 
|  |  |  124  | 
 | 
|  |  |  125  | % param_map
 | 
|  |  |  126  | params_group = values(param_map, {'fl_r_save', 'fl_r_borr', 'fl_w',...
 | 
|  |  |  127  |     'it_z_n', 'fl_crra', 'fl_beta', 'fl_c_min'});
 | 
|  |  |  128  | [fl_r_save, fl_r_borr, fl_wage, it_z_n, fl_crra, fl_beta, fl_c_min] = params_group{:};
 | 
|  |  |  129  | params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 | 
|  |  |  130  | [it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 | 
|  |  |  131  | 
 | 
|  |  |  132  | % support_map
 | 
|  |  |  133  | params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 | 
|  |  |  134  |     'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 | 
|  |  |  135  |     'bl_time', 'bl_graph_evf', 'bl_display', 'it_display_every', 'bl_post'});
 | 
|  |  |  136  | [bl_profile, st_profile_path, ...
 | 
|  |  |  137  |     st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 | 
|  |  |  138  |     bl_time, bl_graph_evf, bl_display, it_display_every, bl_post] = params_group{:};
 | 
|  |  |  139  | 
 | 
|  |  |  140  | %% Initialize Output Matrixes
 | 
|  |  |  141  | 
 | 
|  |  |  142  | mt_val_cur = zeros(length(ar_interp_coh_grid),length(ar_z));
 | 
|  |  |  143  | mt_val = mt_val_cur - 1;
 | 
|  |  |  144  | mt_pol_a = zeros(length(ar_interp_coh_grid),length(ar_z));
 | 
|  |  |  145  | mt_pol_a_cur = mt_pol_a - 1;
 | 
|  |  |  146  | mt_pol_k = zeros(length(ar_interp_coh_grid),length(ar_z));
 | 
|  |  |  147  | mt_pol_k_cur = mt_pol_k - 1;
 | 
|  |  |  148  | mt_pol_idx = zeros(length(ar_interp_coh_grid),length(ar_z));
 | 
|  |  |  149  | 
 | 
|  |  |  150  | mt_ev_condi_z_max_kp = zeros(length(ar_w),length(ar_z));
 | 
|  |  |  151  | mt_ev_condi_z_max_kp_cur = mt_ev_condi_z_max_kp - 1;
 | 
|  |  |  152  | 
 | 
|  |  |  153  | % We did not need these in ff_oz_vf or ff_oz_vf_vec
 | 
|  |  |  154  | % see
 | 
|  |  |  155  | % <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 | 
|  |  |  156  | % fs_u_c_partrepeat_main> for why store using cells.
 | 
|  |  |  157  | cl_u_c_store = cell([it_z_n, 1]);
 | 
|  |  |  158  | cl_c_valid_idx = cell([it_z_n, 1]);
 | 
|  |  |  159  | 
 | 
|  |  |  160  | %% Initialize Convergence Conditions
 | 
|  |  |  161  | 
 | 
|  |  |  162  | bl_vfi_continue = true;
 | 
|  |  |  163  | it_iter = 0;
 | 
|  |  |  164  | ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 | 
|  |  |  165  | ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 | 
|  |  |  166  | mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 | 
|  |  |  167  | 
 | 
|  |  |  168  | %% Pre-calculate u(c)
 | 
|  |  |  169  | % Interpolation, see
 | 
|  |  |  170  | % <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 | 
|  |  |  171  | % fs_u_c_partrepeat_main> for why interpolate over u(c)
 | 
|  |  |  172  | 
 | 
|  |  |  173  | % Evaluate
 | 
|  |  |  174  | if (fl_crra == 1)
 | 
|  |  |  175  |     ar_interp_u_of_c_grid = f_util_log(ar_interp_c_grid);
 | 
|  |  |  176  |     fl_u_neg_c = f_util_log(fl_c_min);
 | 
|  |  |  177  | else
 | 
|  |  |  178  |     ar_interp_u_of_c_grid = f_util_crra(ar_interp_c_grid);
 | 
|  |  |  179  |     fl_u_neg_c = f_util_crra(fl_c_min);
 | 
|  |  |  180  | end
 | 
|  |  |  181  | ar_interp_u_of_c_grid(ar_interp_c_grid <= fl_c_min) = fl_u_neg_c;
 | 
|  |  |  182  | 
 | 
|  |  |  183  | % Get Interpolant
 | 
|  |  |  184  | f_grid_interpolant_spln = griddedInterpolant(ar_interp_c_grid, ar_interp_u_of_c_grid, 'spline');
 | 
|  |  |  185  | 
 | 
|  |  |  186  | %% Iterate Value Function
 | 
|  |  |  187  | % Loop solution with 4 nested loops
 | 
|  |  |  188  | %
 | 
|  |  |  189  | % # loop 1: over exogenous states
 | 
|  |  |  190  | % # loop 2: over endogenous states
 | 
|  |  |  191  | % # loop 3: over choices
 | 
|  |  |  192  | % # loop 4: add future utility, integration--loop over future shocks
 | 
|  |  |  193  | %
 | 
|  |  |  194  | 
 | 
|  |  |  195  | % Start Profile
 | 
|  |  |  196  | if (bl_profile)
 | 
|  |  |  197  |     close all;
 | 
|  |  |  198  |     profile off;
 | 
|  |  |  199  |     profile on;
 | 
| < 0.001  |       1  |  200 | end 
 | 
|  |  |  201  | 
 | 
|  |  |  202  | % Start Timer
 | 
| < 0.001  |       1  |  203 | if (bl_time) 
 | 
| < 0.001  |       1  |  204 |     tic; 
 | 
|  |       1  |  205 | end 
 | 
|  |  |  206  | 
 | 
|  |  |  207  | % Value Function Iteration
 | 
| < 0.001  |       1  |  208 | while bl_vfi_continue 
 | 
| < 0.001  |     111  |  209 |     it_iter = it_iter + 1; 
 | 
|  |  |  210  |     
 | 
|  |  |  211  |     %% Interpolate (1) reacahble v(coh(k(w,z),b(w,z),z),z) given v(coh, z)
 | 
|  |  |  212  |     % v(coh,z) solved on ar_interp_coh_grid, ar_z grids, see
 | 
|  |  |  213  |     % ffs_iwkz_get_funcgrid.m. Generate interpolant based on that, Then
 | 
|  |  |  214  |     % interpolate for the coh reachable levels given the k(w,z) percentage
 | 
|  |  |  215  |     % choice grids in the second stage of the problem
 | 
|  |  |  216  | 
 | 
|  |  |  217  |     % Generate Interpolant for v(coh,z)
 | 
|   0.023  |     111  |  218 |     f_grid_interpolant_value = griddedInterpolant(... 
 | 
|  |     111  |  219 |         mt_z_mesh_coh_interp_grid', mt_interp_coh_grid_mesh_z', mt_val_cur', 'linear'); 
 | 
|  |  |  220  |     
 | 
|  |  |  221  |     % Interpoalte for v(coh(k(w,z),b(w,z),z),z)
 | 
|   0.041  |     111  |  222 |     mt_val_wkb_interpolated = f_grid_interpolant_value(mt_z_mesh_coh_wkb, mt_coh_wkb); 
 | 
|  |  |  223  |         
 | 
|  |  |  224  |     %% Solve Second Stage Problem k*(w,z)
 | 
|  |  |  225  |     % This is the key difference between this function and
 | 
|  |  |  226  |     % <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/html/ffs_akz_set_functions.html
 | 
|  |  |  227  |     % ffs_akz_set_functions> which solves the two stages jointly    
 | 
|  |  |  228  |     % Interpolation first, because solution coh grid is not the same as all
 | 
|  |  |  229  |     % points reachable by k and b choices given w. 
 | 
|   0.007  |     111  |  230 |     support_map('bl_graph_evf') = false; 
 | 
| < 0.001  |     111  |  231 |     if (it_iter == (it_maxiter_val + 1)) 
 | 
| < 0.001  |       1  |  232 |         support_map('bl_graph_evf') = bl_graph_evf; 
 | 
|  |       1  |  233 |     end 
 | 
| < 0.001  |     111  |  234 |     bl_input_override = true; 
 | 
|   0.063  |     111  |  235 |     [mt_ev_condi_z_max, ~, mt_ev_condi_z_max_kp, mt_ev_condi_z_max_bp] = ... 
 | 
|  |     111  |  236 |         ff_wkz_evf(mt_val_wkb_interpolated, param_map, support_map, armt_map, bl_input_override); 
 | 
|  |  |  237  |     
 | 
|  |  |  238  |     %% Find which k choice differ across iterations?
 | 
| < 0.001  |     111  |  239 |     mt_w_kstar_diff_idx = (mt_ev_condi_z_max_kp_cur ~= mt_ev_condi_z_max_kp); 
 | 
|  |  |  240  |     
 | 
|  |  |  241  |     %% Solve First Stage Problem w*(z) given k*(w,z)
 | 
|  |  |  242  |         
 | 
|  |  |  243  |     % loop 1: over exogenous states
 | 
| < 0.001  |     111  |  244 |     for it_z_i = 1:length(ar_z) 
 | 
|  |  |  245  | 
 | 
|  |  |  246  |         % State Array fixed
 | 
|   0.002  |    1665  |  247 |         ar_coh_z = mt_interp_coh_grid_mesh_z(:,it_z_i); 
 | 
|  |  |  248  |         
 | 
|  |  |  249  |         % Get 2nd Stage Choice Arrays
 | 
|  |  |  250  |         % Update rows where opti k given w=k'+b' is changing        
 | 
| < 0.001  |    1665  |  251 |         ar_w_kstar_diff_idx = mt_w_kstar_diff_idx(:, it_z_i); 
 | 
|   0.005  |    1665  |  252 |         ar_w_kstar_z = mt_ev_condi_z_max_kp(ar_w_kstar_diff_idx, it_z_i); 
 | 
|   0.004  |    1665  |  253 |         ar_w_astar_z = mt_ev_condi_z_max_bp(ar_w_kstar_diff_idx, it_z_i);         
 | 
|  |  |  254  |         
 | 
|  |  |  255  |         % Consumption Update
 | 
|  |  |  256  |         % Note that compared to
 | 
|  |  |  257  |         % <https://fanwangecon.github.io/CodeDynaAsset/m_akz/paramfunc/html/ffs_akz_set_functions.html
 | 
|  |  |  258  |         % ffs_akz_set_functions> the mt_c here is much smaller the same
 | 
|  |  |  259  |         % number of columns (states) as in the ffs_akz_set_functions file,
 | 
|  |  |  260  |         % but the number of rows equal to ar_w length.            
 | 
|   0.034  |    1665  |  261 |         mt_c = f_cons(ar_coh_z', ar_w_astar_z, ar_w_kstar_z); 
 | 
|  |  |  262  |                 
 | 
|  |  |  263  |         % Interpolate (2) EVAL current utility: N by N, f_util defined earlier
 | 
|   0.098  |    1665  |  264 |         mt_utility_update = f_grid_interpolant_spln(mt_c); 
 | 
|  |  |  265  |         
 | 
|  |  |  266  |         % Eliminate Complex Numbers
 | 
|   0.005  |    1665  |  267 |         mt_it_c_valid_idx = (mt_c <= fl_c_min); 
 | 
|  |  |  268  |         
 | 
|  |  |  269  |         % Update Storage
 | 
| < 0.001  |    1665  |  270 |         if (it_iter == 1) 
 | 
| < 0.001  |      15  |  271 |             cl_u_c_store{it_z_i} = mt_utility_update; 
 | 
| < 0.001  |      15  |  272 |             cl_c_valid_idx{it_z_i} = mt_it_c_valid_idx; 
 | 
| < 0.001  |    1650  |  273 |         else 
 | 
|   0.011  |    1650  |  274 |             cl_u_c_store{it_z_i}(ar_w_kstar_diff_idx,:) = mt_utility_update;                 
 | 
|   0.006  |    1650  |  275 |             cl_c_valid_idx{it_z_i}(ar_w_kstar_diff_idx,:) = mt_it_c_valid_idx;  
 | 
| < 0.001  |    1665  |  276 |         end 
 | 
|  |  |  277  |                 
 | 
|  |  |  278  |         % EVAL add on future utility, N by N + N by 1
 | 
| < 0.001  |    1665  |  279 |         ar_evzp_ak_condi_z = mt_ev_condi_z_max(:, it_z_i); 
 | 
|   0.046  |    1665  |  280 |         mt_utility = cl_u_c_store{it_z_i} + fl_beta*ar_evzp_ak_condi_z; 
 | 
|  |  |  281  |         
 | 
|  |  |  282  |         % Index update
 | 
|  |  |  283  |         % using the method below is much faster than index replace
 | 
|  |  |  284  |         % see <https://fanwangecon.github.io/M4Econ/support/speed/index/fs_subscript.html fs_subscript>
 | 
|   0.003  |    1665  |  285 |         mt_it_c_valid_idx = cl_c_valid_idx{it_z_i};         
 | 
|   0.035  |    1665  |  286 |         mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_u_neg_c*(mt_it_c_valid_idx); 
 | 
|  |  |  287  |         
 | 
|  |  |  288  |         % Optimization: remember matlab is column major, rows must be
 | 
|  |  |  289  |         % choices, columns must be states
 | 
|  |  |  290  |         % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
 | 
|   0.080  |    1665  |  291 |         [ar_opti_val1_z, ar_opti_idx_z] = max(mt_utility); 
 | 
|   0.008  |    1665  |  292 |         mt_val(:,it_z_i) = ar_opti_val1_z; 
 | 
|   0.013  |    1665  |  293 |         mt_pol_a(:,it_z_i) = mt_ev_condi_z_max_bp(ar_opti_idx_z, it_z_i); 
 | 
|   0.012  |    1665  |  294 |         mt_pol_k(:,it_z_i) = mt_ev_condi_z_max_kp(ar_opti_idx_z, it_z_i);         
 | 
| < 0.001  |    1665  |  295 |         if (it_iter == (it_maxiter_val + 1)) 
 | 
| < 0.001  |      15  |  296 |             mt_pol_idx(:,it_z_i) = ar_opti_idx_z; 
 | 
| < 0.001  |      15  |  297 |         end 
 | 
|  |  |  298  | 
 | 
|   0.002  |    1665  |  299 |     end 
 | 
|  |  |  300  |     
 | 
|  |  |  301  |     %% Check Tolerance and Continuation
 | 
|  |  |  302  |     
 | 
|  |  |  303  |     % Difference across iterations
 | 
|   0.026  |     111  |  304 |     ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
 | 
|   0.042  |     111  |  305 |     ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur) + norm(mt_pol_k - mt_pol_k_cur); 
 | 
|   0.005  |     111  |  306 |     ar_pol_a_perc_change = sum((mt_pol_a ~= mt_pol_a_cur))/(length(ar_interp_coh_grid)); 
 | 
|   0.004  |     111  |  307 |     ar_pol_k_perc_change = sum((mt_pol_k ~= mt_pol_k_cur))/(length(ar_interp_coh_grid));     
 | 
|   0.010  |     111  |  308 |     mt_pol_perc_change(it_iter, :) = mean([ar_pol_a_perc_change;ar_pol_k_perc_change]); 
 | 
|  |  |  309  |     
 | 
|  |  |  310  |     % Update
 | 
|   0.002  |     111  |  311 |     mt_val_cur = mt_val; 
 | 
| < 0.001  |     111  |  312 |     mt_pol_a_cur = mt_pol_a; 
 | 
| < 0.001  |     111  |  313 |     mt_pol_k_cur = mt_pol_k; 
 | 
| < 0.001  |     111  |  314 |     mt_ev_condi_z_max_kp_cur = mt_ev_condi_z_max_kp; 
 | 
|  |  |  315  |     
 | 
|  |  |  316  |     % Print Iteration Results
 | 
| < 0.001  |     111  |  317 |     if (bl_display && (rem(it_iter, it_display_every)==0)) 
 | 
|  |  |  318  |         fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 | 
|  |  |  319  |             it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 | 
|  |  |  320  |         tb_valpol_iter = array2table([mean(mt_val_cur,1);...
 | 
|  |  |  321  |                                       mean(mt_pol_a_cur,1); ...
 | 
|  |  |  322  |                                       mean(mt_pol_k_cur,1); ...
 | 
|  |  |  323  |                                       mt_val_cur(length(ar_interp_coh_grid),:); ...
 | 
|  |  |  324  |                                       mt_pol_a_cur(length(ar_interp_coh_grid),:); ...
 | 
|  |  |  325  |                                       mt_pol_k_cur(length(ar_interp_coh_grid),:)]);
 | 
|  |  |  326  |         tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 | 
|  |  |  327  |         tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'mak', 'Hval', 'Hap', 'Hak'};
 | 
|  |  |  328  |         disp('mval = mean(mt_val_cur,1), average value over a')
 | 
|  |  |  329  |         disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 | 
|  |  |  330  |         disp('mkp  = mean(mt_pol_k_cur,1), average choice over k')
 | 
|  |  |  331  |         disp('Hval = mt_val_cur(it_ameshk_n,:), highest a state val')
 | 
|  |  |  332  |         disp('Hap = mt_pol_a_cur(it_ameshk_n,:), highest a state choice')
 | 
|  |  |  333  |         disp('mak = mt_pol_k_cur(it_ameshk_n,:), highest k state choice')                
 | 
|  |  |  334  |         disp(tb_valpol_iter);
 | 
|  |  |  335  |     end
 | 
|  |  |  336  |     
 | 
|  |  |  337  |     % Continuation Conditions:
 | 
|  |  |  338  |     % 1. if value function convergence criteria reached
 | 
|  |  |  339  |     % 2. if policy function variation over iterations is less than
 | 
|  |  |  340  |     % threshold
 | 
| < 0.001  |     111  |  341 |     if (it_iter == (it_maxiter_val + 1)) 
 | 
| < 0.001  |       1  |  342 |         bl_vfi_continue = false; 
 | 
|   0.001  |     110  |  343 |     elseif ((it_iter == it_maxiter_val) || ... 
 | 
|  |     110  |  344 |             (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
 | 
|  |     110  |  345 |             (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 | 
|  |  |  346  |         % Fix to max, run again to save results if needed
 | 
| < 0.001  |       1  |  347 |         it_iter_last = it_iter; 
 | 
|  |       1  |  348 |         it_iter = it_maxiter_val;         
 | 
|  |       1  |  349 |     end 
 | 
|  |  |  350  |     
 | 
| < 0.001  |     111  |  351 | end 
 | 
|  |  |  352  | 
 | 
|  |  |  353  | % End Timer
 | 
| < 0.001  |       1  |  354 | if (bl_time) 
 | 
| < 0.001  |       1  |  355 |     toc; 
 | 
| < 0.001  |       1  |  356 | end 
 | 
|  |  |  357  | 
 | 
|  |  |  358  | % End Profile
 | 
| < 0.001  |       1  |  359 | if (bl_profile) 
 | 
|   0.004  |       1  |  360 |     profile off 
 | 
|  |  |  361  |     profile viewer
 | 
|  |  |  362  |     st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 | 
|  |  |  363  |     profsave(profile('info'), strcat(st_profile_path, st_file_name));
 | 
|  |  |  364  | end
 | 
|  |  |  365  | 
 | 
|  |  |  366  | %% Process Optimal Choices
 | 
|  |  |  367  | 
 | 
|  |  |  368  | result_map = containers.Map('KeyType','char', 'ValueType','any');
 | 
|  |  |  369  | result_map('mt_val') = mt_val;
 | 
|  |  |  370  | result_map('mt_pol_idx') = mt_pol_idx;
 | 
|  |  |  371  | 
 | 
|  |  |  372  | result_map('cl_mt_pol_coh') = {mt_interp_coh_grid_mesh_z, zeros(1)};
 | 
|  |  |  373  | result_map('cl_mt_pol_a') = {mt_pol_a, zeros(1)};
 | 
|  |  |  374  | result_map('cl_mt_pol_k') = {mt_pol_k, zeros(1)};
 | 
|  |  |  375  | result_map('cl_mt_pol_c') = {f_cons(mt_interp_coh_grid_mesh_z, mt_pol_a, mt_pol_k), zeros(1)};
 | 
|  |  |  376  | result_map('ar_st_pol_names') = ["cl_mt_pol_coh", "cl_mt_pol_a", "cl_mt_pol_k", "cl_mt_pol_c"];
 | 
|  |  |  377  | 
 | 
|  |  |  378  | if (bl_post)
 | 
|  |  |  379  |     bl_input_override = true;
 | 
|  |  |  380  |     result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 | 
|  |  |  381  |     result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 | 
|  |  |  382  |     result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 | 
|  |  |  383  |     
 | 
|  |  |  384  |     % graphing based on coh_wkb, but that does not match optimal choice
 | 
|  |  |  385  |     % matrixes for graphs. 
 | 
|  |  |  386  |     armt_map('mt_coh_wkb') = mt_interp_coh_grid_mesh_z;
 | 
|  |  |  387  |     armt_map('it_ameshk_n') = length(ar_interp_coh_grid);
 | 
|  |  |  388  |     armt_map('ar_a_meshk') = mt_interp_coh_grid_mesh_z(:,1);
 | 
|  |  |  389  |     armt_map('ar_k_mesha') = zeros(size(mt_interp_coh_grid_mesh_z(:,1)) + 0);
 | 
|  |  |  390  |     
 | 
|  |  |  391  |     result_map = ff_akz_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 | 
|  |  |  392  | end
 | 
|  |  |  393  | 
 | 
|  |  |  394  | end
 | 
Other subfunctions in this file are not included in this listing.