This is a static copy of a profile report

Home

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

Home

ff_abzr_fibs_vf_vec (Calls: 1, Time: 272.458 s)
Generated 14-Jul-2019 10:48:15 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_fibs\m_abzr_solve\ff_abzr_fibs_vf_vec.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
360
mt_utility = f_util_crra(mt_c)...
9150111.327 s40.9%
377
mt_utility(mt_c <= fl_c_min...
915047.286 s17.4%
313
bl_display_minccost, bl_input_...
915031.317 s11.5%
384
mt_c(mt_c < fl_c_min) = fl_...
915018.899 s6.9%
261
mt_c = f_cons_coh_save(ar_coh,...
915014.436 s5.3%
All other lines  49.193 s18.1%
Totals  272.458 s100% 
Children (called functions)

Function NameFunction TypeCallsTotal Time% TimeTime Plot
...c)(((c).^(1-fl_crra)-1)./(1-fl_crra))anonymous function18300101.811 s37.4%
ffs_fibs_min_c_costfunction915030.609 s11.2%
..._save)(coh-ar_for_save./(1+fl_r_fsv))anonymous function91509.337 s3.4%
ffs_fibs_inf_bridgefunction91506.195 s2.3%
...h,ar_bprime_in_c)(coh+ar_bprime_in_c)anonymous function91503.035 s1.1%
linspacefunction91500.181 s0.1%
...tions>@(ar_z,ar_b)(ar_z*fl_w+ar_b)anonymous function91500.053 s0.0%
Self time (built-ins, overhead, etc.)  121.239 s44.5%
Totals  272.458 s100% 
Code Analyzer results
Line numberMessage
269The value assigned to variable 'ar_coh_neg' might be unused.
331Use of brackets [] is unnecessary. Use parentheses to group, if needed.
Coverage results
Show coverage for parent directory
Total lines in function600
Non-code lines (comments, blank lines)365
Code lines (lines that can run)235
Code lines that did run97
Code lines that did not run138
Coverage (did run/can run)41.28 %
Function listing
time 
Calls 
 line
   7 
function result_map = ff_abzr_fibs_vf_vec(varargin)
   8 
%% FF_ABZR_FIBS_VF_VEC solve infinite horizon exo shock + endo asset problem
   9 
% With R shock.
  10 
%
  11 
% The model could be invoked mainly in sveral ways:
  12 
%
  13 
% # param_map('bl_default') = true;  param_map('bl_bridge') = false;
  14 
% param_map('bl_rollover') = true; Given these, default is possible, bridge
  15 
% loans are not needed because rollover is allowed for formal loans (or
  16 
% informal loans)
  17 
% # we change param_map('bl_bridge') = true, that means
  18 
% rollover is still allowed, but only allowed using informal sources,
  19 
% formal loans no longer allow for roll-over. Furthermore, if both
  20 
% bl_bridge and bl_rollover are false, that means we are not allowing for
  21 
% rollover at all, so households can not borrow such that they end up with
  22 
% negative cash-on-hand.
  23 
%
  24 
% Default simulation bl_bridge = false.
  25 
%
  26 
% @param param_map container parameter container
  27 
%
  28 
% @param support_map container support container
  29 
%
  30 
% @param armt_map container container with states, choices and shocks
  31 
% grids that are inputs for grid based solution algorithm
  32 
%
  33 
% @param func_map container container with function handles for
  34 
% consumption cash-on-hand etc.
  35 
%
  36 
% @return result_map container contains policy function matrix, value
  37 
% function matrix, iteration results, and policy function, value function
  38 
% and iteration results tables.
  39 
%
  40 
% keys included in result_map:
  41 
%
  42 
% * mt_val matrix states_n by shock_n matrix of converged value function grid
  43 
% * mt_pol_a matrix states_n by shock_n matrix of converged policy function grid
  44 
% * ar_val_diff_norm array if bl_post = true it_iter_last by 1 val function
  45 
% difference between iteration
  46 
% * ar_pol_diff_norm array if bl_post = true it_iter_last by 1 policy
  47 
% function difference between iterations
  48 
% * mt_pol_perc_change matrix if bl_post = true it_iter_last by shock_n the
  49 
% proportion of grid points at which policy function changed between
  50 
% current and last iteration for each element of shock
  51 
%
  52 
% @example
  53 
%
  54 
%    % Get Default Parameters
  55 
%    it_param_set = 4;
  56 
%    [param_map, support_map] = ffs_abzr_fibs_set_default_param(it_param_set);
  57 
%    % Chnage param_map keys for borrowing
  58 
%    param_map('fl_b_bd') = -20; % borrow bound
  59 
%    param_map('bl_default') = false; % true if allow for default
  60 
%    param_map('fl_c_min') = 0.0001; % u(c_min) when default
  61 
%    % Change Keys in param_map
  62 
%    param_map('it_a_n') = 75;
  63 
%    param_map('fl_z_r_borr_n') = 3;
  64 
%    param_map('it_z_wage_n') = 5;
  65 
%    param_map('it_z_n') = param_map('it_z_wage_n') * param_map('fl_z_r_borr_n');
  66 
%    param_map('fl_a_max') = 100;
  67 
%    param_map('fl_w') = 1.3;
  68 
%    % Change Keys support_map
  69 
%    support_map('bl_display') = false;
  70 
%    support_map('bl_post') = true;
  71 
%    support_map('bl_display_final') = false;
  72 
%    % Call Program with external parameters that override defaults.
  73 
%    ff_abzr_fibs_vf_vec(param_map, support_map);
  74 
%
  75 
% @include
  76 
%
  77 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/m_abzr_paramfunc/html/ffs_abzr_fibs_set_default_param.html ffs_abzr_fibs_set_default_param>
  78 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/m_abzr_paramfunc/html/ffs_abzr_fibs_get_funcgrid.html ffs_abzr_fibs_get_funcgrid>
  79 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_min_c_cost_bridge.html ffs_fibs_min_c_cost_bridge>
  80 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_inf_bridge.html ffs_fibs_inf_bridge>
  81 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_min_c_cost.html ffs_fibs_min_c_cost>
  82 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_az/solvepost/html/ff_az_vf_post.html ff_az_vf_post>
  83 
%
  84 
% @seealso
  85 
%
  86 
% * for/inf + save + borr loop: <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/m_abzr_solve/html/ff_abzr_fibs_vf.html ff_abzr_fibs_vf>
  87 
% * for/inf + borr vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/m_abzr_solve/html/ff_abzr_fibs_vf_vec.html ff_abzr_fibs_vf_vec>
  88 
% * for/inf + borr optimized-vectorized: <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/m_abzr_solve/html/ff_abzr_fibs_vf_vecsv.html ff_abzr_fibs_vf_vecsv>
  89 
%
  90 

  91 

  92 
%% Default
  93 
% * it_param_set = 1: quick test
  94 
% * it_param_set = 2: benchmark run
  95 
% * it_param_set = 3: benchmark profile
  96 
% * it_param_set = 4: press publish button
  97 

  98 
it_param_set = 3;
  99 
bl_input_override = true;
 100 
[param_map, support_map] = ffs_abzr_fibs_set_default_param(it_param_set);
 101 

 102 
% Note: param_map and support_map can be adjusted here or outside to override defaults
 103 
% To generate results as if formal informal do not matter
 104 

 105 
% param_map('fl_r_fsv') = 0.025;
 106 
% param_map('fl_r_fbr') = 0.035;
 107 
% param_map('bl_b_is_principle') = false;
 108 
% param_map('st_forbrblk_type') = 'seg3';
 109 
% param_map('fl_forbrblk_brmost') = -19;
 110 
% param_map('fl_forbrblk_brleast') = -1;
 111 
% param_map('fl_forbrblk_gap') = -1.5;
 112 
% param_map('bl_b_is_principle') = false;
 113 
% param_map('it_a_n') = 750;
 114 
% param_map('fl_z_r_borr_n') = 5;
 115 
% param_map('it_z_wage_n') = 15;
 116 
% param_map('it_z_n') = param_map('it_z_wage_n') * param_map('fl_z_r_borr_n');
 117 

 118 
[armt_map, func_map] = ffs_abzr_fibs_get_funcgrid(param_map, support_map); % 1 for override
 119 
default_params = {param_map support_map armt_map func_map};
 120 

 121 
%% Parse Parameters 1
 122 

 123 
% if varargin only has param_map and support_map,
 124 
params_len = length(varargin);
 125 
[default_params{1:params_len}] = varargin{:};
 126 
param_map = [param_map; default_params{1}];
 127 
support_map = [support_map; default_params{2}];
 128 
if params_len >= 1 && params_len <= 2
 129 
    % If override param_map, re-generate armt and func if they are not
 130 
    % provided
 131 
    [armt_map, func_map] = ffs_abzr_fibs_get_funcgrid(param_map, support_map);
 132 
else
 133 
    % Override all
 134 
    armt_map = [armt_map; default_params{3}];
 135 
    func_map = [func_map; default_params{4}];
 136 
end
 137 

 138 
% append function name
 139 
st_func_name = 'ff_abzr_fibs_vf_vec';
 140 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 141 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 142 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 143 

 144 
%% Parse Parameters 2
 145 

 146 
% armt_map
 147 
params_group = values(armt_map, {'ar_a', 'mt_z_trans', 'ar_z_r_infbr_mesh_wage', 'ar_z_wage_mesh_r_infbr'});
 148 
[ar_a, mt_z_trans, ar_z_r_infbr_mesh_wage, ar_z_wage_mesh_r_infbr] = params_group{:};
 149 

 150 
% Formal choice Menu/Grid and Interest Rate Menu/Grid
 151 
params_group = values(armt_map, {'ar_forbrblk_r', 'ar_forbrblk'});
 152 
[ar_forbrblk_r, ar_forbrblk] = params_group{:};
 153 

 154 
% func_map
 155 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_coh', 'f_cons_coh_fbis', 'f_cons_coh_save'});
 156 
[f_util_log, f_util_crra, f_coh, f_cons_coh_fbis, f_cons_coh_save] = params_group{:};
 157 

 158 
% param_map
 159 
params_group = values(param_map, {'it_a_n', 'it_z_n', 'fl_crra', 'fl_beta', 'fl_c_min',...
 160 
    'fl_nan_replace', 'bl_default', 'bl_bridge', 'bl_rollover', 'fl_default_aprime'});
 161 
[it_a_n, it_z_n, fl_crra, fl_beta, fl_c_min, ...
 162 
    fl_nan_replace, bl_default, bl_bridge, bl_rollover, fl_default_aprime] = params_group{:};
 163 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 164 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 165 

 166 
% param_map, Formal informal
 167 
params_group = values(param_map, {'fl_r_fsv', 'bl_b_is_principle'});
 168 
[fl_r_fsv, bl_b_is_principle] = params_group{:};
 169 

 170 
% support_map
 171 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 172 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 173 
    'bl_display_minccost', 'bl_display_infbridge', ...
 174 
    'bl_time', 'bl_display_defparam', 'bl_display', 'it_display_every', 'bl_post'});
 175 
[bl_profile, st_profile_path, ...
 176 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 177 
    bl_display_minccost, bl_display_infbridge, ...
 178 
    bl_time, bl_display_defparam, bl_display, it_display_every, bl_post] = params_group{:};
 179 

 180 
%% Initialize Output Matrixes
 181 
% include mt_pol_idx which we did not have in looped code
 182 

 183 
mt_val_cur = zeros(it_a_n,it_z_n);
 184 
mt_val = mt_val_cur - 1;
 185 
mt_pol_a = zeros(it_a_n,it_z_n);
 186 
mt_pol_a_cur = mt_pol_a - 1;
 187 
mt_pol_idx = zeros(it_a_n,it_z_n);
 188 
mt_pol_cons = zeros(it_a_n,it_z_n);
 189 

 190 
% collect optimal borrowing formal and informal choices
 191 
mt_pol_b_bridge = zeros(it_a_n,it_z_n);
 192 
mt_pol_inf_borr_nobridge = zeros(it_a_n,it_z_n);
 193 
mt_pol_for_borr = zeros(it_a_n,it_z_n);
 194 
mt_pol_for_save = zeros(it_a_n,it_z_n);
 195 

 196 
%% Initialize Convergence Conditions
 197 

 198 
bl_vfi_continue = true;
 199 
it_iter = 0;
 200 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 201 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 202 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 203 

 204 
%% Iterate Value Function
 205 
% Loop solution with 4 nested loops
 206 
%
 207 
% # loop 1: over exogenous states
 208 
% # loop 2: over endogenous states
 209 
% # loop 3: over choices
 210 
% # loop 4: add future utility, integration--loop over future shocks
 211 
%
 212 

 213 
% Start Profile
 214 
if (bl_profile)
 215 
    close all;
 216 
    profile off;
 217 
    profile on;
< 0.001 
      1 
 218
end 
 219 

 220 
% Start Timer
< 0.001 
      1 
 221
if (bl_time) 
< 0.001 
      1 
 222
    tic; 
< 0.001 
      1 
 223
end 
 224 

 225 
% Value Function Iteration
< 0.001 
      1 
 226
while bl_vfi_continue 
< 0.001 
    122 
 227
    it_iter = it_iter + 1; 
 228 

 229 
    %% Solve Optimization Problem Current Iteration
 230 

 231 
    % loop 1: over exogenous states
< 0.001 
    122 
 232
    for it_z_i = 1:it_z_n 
 233 

 234 
        %% Solve the Formal Informal Problem for each a' and coh: c_forinf(a')
 235 
        % find the today's consumption maximizing formal and informal
 236 
        % choices given a' and coh. The formal and informal choices need to
 237 
        % generate exactly a', but depending on which formal and informal
 238 
        % joint choice is used, the consumption cost today a' is different.
 239 
        % Note here, a is principle + interests. Three areas:
 240 
        %
 241 
        % * *CASE A* a' > 0: savings, do not need to optimize over formal and
 242 
        % informal choices
 243 
        % * *CASE B* a' < 0 & coh < 0: need bridge loan to pay for unpaid debt, and
 244 
        % borrowing over-all, need to first pick bridge loan to pay for
 245 
        % debt, if bridge loan is insufficient, go into default. After
 246 
        % bridge loan, optimize over formal+informal, borrow+save joint
 247 
        % choices.
 248 
        % * *CASE C* a' < 0 & coh > 0: do not need to get informal bridge loans,
 249 
        % optimize over for+inf save, for+save+borr, inf+borr only, for
 250 
        % borrow only.
 251 
        %
 252 

 253 
        % 1. Current Shock
  0.003 
   9150 
 254
        fl_z_r_borr = ar_z_r_infbr_mesh_wage(it_z_i); 
  0.003 
   9150 
 255
        fl_z_wage = ar_z_wage_mesh_r_infbr(it_z_i); 
 256 

 257 
        % 2. cash-on-hand
  0.113 
   9150 
 258
        ar_coh = f_coh(fl_z_wage, ar_a); 
 259 

 260 
        % 3. *CASE A* initiate consumption matrix as if all save
 14.436 
   9150 
 261
        mt_c = f_cons_coh_save(ar_coh, ar_a'); 
 262 

 263 
        % 3. if Bridge Loan is Needed
 264 

 265 
        % 4. *CASE B+C* get negative coh index and get borrowing choices index
  0.022 
   9150 
 266
        ar_coh_neg_idx = (ar_coh <= 0); 
 267 

  0.013 
   9150 
 268
        ar_a_neg_idx = (ar_a < 0); 
  0.070 
   9150 
 269
        ar_coh_neg = ar_coh(ar_coh_neg_idx); 
  0.033 
   9150 
 270
        ar_a_neg = ar_a(ar_a_neg_idx); 
 271 

 272 
        % 5. if coh > 0 and ap < 0, can allow same for+inf result to all coh.
 273 
        % The procedure below works regardless of how ar_coh is sorted. get
 274 
        % the index of all negative coh elements as well as first
 275 
        % non-negative element. We solve the formal and informal problem at
 276 
        % these points, note that we only need to solve the formal and
 277 
        % informal problem for positive coh level once.
  0.087 
   9150 
 278
        ar_coh_first_pos_idx = (cumsum(ar_coh_neg_idx == 0) == 1); 
  0.010 
   9150 
 279
        ar_coh_forinfsolve_idx = (ar_coh_first_pos_idx | ar_coh_neg_idx); 
  0.036 
   9150 
 280
        ar_coh_forinfsolve_a_neg_idx = (ar_coh(ar_coh_forinfsolve_idx) <= 0); 
 281 

 282 
        % 6. *CASE B + C* Negative asset choices (borrowing), 1 col Case C
 283 
        % negp1: negative coh + 1, 1 meaning 1 positive coh, first positive
 284 
        % coh column index element grabbed.
  1.319 
   9150 
 285
        mt_coh_negp1_mesh_neg_aprime = zeros(size(ar_a_neg')) + ar_coh(ar_coh_forinfsolve_idx); 
  0.976 
   9150 
 286
        mt_neg_aprime_mesh_coh_negp1 = zeros(size(mt_coh_negp1_mesh_neg_aprime)) + ar_a_neg'; 
 287 

  0.004 
   9150 
 288
        if (bl_bridge) 
 289 
            %         mt_neg_aprime_mesh_coh_1col4poscoh = zeros([length(ar_a_neg), (length(ar_coh_neg)+1)]) + ar_a_neg';
 290 
            %         ar_coh_neg_idx_1col4poscoh = ar_coh_neg_idx(1:(length(ar_coh_neg)+1));
 291 

 292 
            % 6. *CASE B* Solve for: if (fl_ap < 0) and if (fl_coh < 0)
  9.109 
   9150 
 293
            [mt_aprime_nobridge_negcoh, ~, mt_c_bridge_negcoh] = ffs_fibs_inf_bridge(... 
   9150 
 294
                bl_b_is_principle, fl_z_r_borr, ... 
   9150 
 295
                mt_neg_aprime_mesh_coh_negp1(:,ar_coh_forinfsolve_a_neg_idx), ... 
   9150 
 296
                mt_coh_negp1_mesh_neg_aprime(:,ar_coh_forinfsolve_a_neg_idx), ... 
   9150 
 297
                bl_display_infbridge, bl_input_override); 
 298 

 299 
            % generate mt_aprime_nobridge
  0.342 
   9150 
 300
            mt_neg_aprime_mesh_coh_negp1(:, ar_coh_forinfsolve_a_neg_idx) = mt_aprime_nobridge_negcoh; 
 301 
        else
 302 
            % no bridge loan needed means roll over is allowed.
 303 
            mt_neg_aprime_mesh_coh_negp1 = ar_a_neg';
  0.002 
   9150 
 304
        end 
 305 

 306 
        % 7. *CASE B + C* formal and informal joint choices, 1 col Case C
  0.001 
   9150 
 307
        bl_input_override = true; 
 31.332 
   9150 
 308
        [ar_max_c_nobridge, ~, ~, ~] = ... 
 309 
            ffs_fibs_min_c_cost(...
   9150 
 310
            bl_b_is_principle, fl_z_r_borr, fl_r_fsv, ... 
   9150 
 311
            ar_forbrblk_r, ar_forbrblk, ... 
   9150 
 312
            mt_neg_aprime_mesh_coh_negp1(:), ... 
   9150 
 313
            bl_display_minccost, bl_input_override); 
 314 

 315 
        %% Update Consumption Matrix *CASE A + B + C* Consumptions
 316 
        % Current mt_c is assuming all to be case A
 317 
        %
 318 
        % * Update Columns for case B (negative coh)
 319 
        % * Update Columns for case C (1 column): ar_coh_first_pos_idx,
 320 
        % included in ar_coh_forinfsolve_idx
 321 
        % * Update Columns for all case C: ~ar_coh_neg_idx using 1 column
 322 
        % result
 323 
        %
 324 

 325 
        % 1. Initalize all Neg Aprime consumption cost of aprime inputs
 326 
        % Initialize
  4.820 
   9150 
 327
        mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + 0; 
  4.526 
   9150 
 328
        mt_c_bridge_coh_a_neg = zeros(size(mt_max_c_nobridge_a_neg)) + 0; 
 329 

 330 
        % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
  0.511 
   9150 
 331
        mt_max_c_nobridge_negcohp1 = reshape(ar_max_c_nobridge, [size(mt_neg_aprime_mesh_coh_negp1)]); 
 332 

  0.003 
   9150 
 333
        if (bl_bridge) 
 334 
            % 2. Fill in *Case B* Bridge C-cost
  0.512 
   9150 
 335
            mt_c_bridge_coh_a_neg(:, ar_coh_neg_idx) = mt_c_bridge_negcoh; 
 336 

 337 
            % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
  0.433 
   9150 
 338
            mt_max_c_nobridge_a_neg(:, ar_coh_forinfsolve_idx) = mt_max_c_nobridge_negcohp1; 
  7.503 
   9150 
 339
            mt_max_c_nobridge_a_neg(:, ~ar_coh_forinfsolve_idx) = ... 
   9150 
 340
                zeros(size(mt_c(ar_a_neg_idx, ~ar_coh_forinfsolve_idx))) ... 
   9150 
 341
                + mt_max_c_nobridge_negcohp1(:, ~ar_coh_forinfsolve_a_neg_idx); 
 342 
        else
 343 
            mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + mt_max_c_nobridge_negcohp1;
  0.002 
   9150 
 344
        end 
 345 

 346 
        % 3. Consumption for B + C Cases
 347 
        % note, the c cost of aprime is the same for all coh > 0, but mt_c
 348 
        % is different still for each coh and aprime.
  9.290 
   9150 
 349
        mt_c_forinfsolve = f_cons_coh_fbis(ar_coh, mt_c_bridge_coh_a_neg + mt_max_c_nobridge_a_neg); 
 350 

 351 
        % 4. Update with Case B and C
  1.944 
   9150 
 352
        mt_c(ar_a_neg_idx, :) = mt_c_forinfsolve; 
 353 

 354 
        %% Solve Optimization Problem: max_{a'} (u(c_forinf(a')) + EV(a',z'))
 355 
        % 1. EVAL current utility: N by N, f_util defined earlier
  0.003 
   9150 
 356
        if (fl_crra == 1) 
 357 
            mt_utility = f_util_log(mt_c);
 358 
            fl_u_cmin = f_util_log(fl_c_min);
  0.001 
   9150 
 359
        else 
 111.327 
   9150 
 360
            mt_utility = f_util_crra(mt_c); 
  0.176 
   9150 
 361
            fl_u_cmin = f_util_crra(fl_c_min); 
  0.002 
   9150 
 362
        end 
 363 

 364 
        % 2. f(z'|z)
  0.039 
   9150 
 365
        ar_z_trans_condi = mt_z_trans(it_z_i,:); 
 366 

 367 
        % 3. EVAL EV((A',K'),Z'|Z) = V((A',K'),Z') x p(z'|z)', (N by Z) x (Z by 1) = N by 1
 368 
        % Note: transpose ar_z_trans_condi from 1 by Z to Z by 1
 369 
        % Note: matrix multiply not dot multiply
  1.001 
   9150 
 370
        mt_evzp_condi_z = mt_val_cur * ar_z_trans_condi'; 
 371 

 372 
        % 4. EVAL add on future utility, N by N + N by 1, broadcast again
  1.847 
   9150 
 373
        mt_utility = mt_utility + fl_beta*mt_evzp_condi_z; 
 374 

  0.004 
   9150 
 375
        if (bl_default) 
 376 
            % if default: only today u(cmin), transition out next period, debt wiped out
 47.286 
   9150 
 377
            mt_utility(mt_c <= fl_c_min) = fl_u_cmin + fl_beta*mt_evzp_condi_z(ar_a == fl_default_aprime); 
 378 
        else
 379 
            % if default is not allowed: v = fl_nan_replace
 380 
            mt_utility(mt_c <= fl_c_min) = fl_nan_replace;
  0.003 
   9150 
 381
        end 
 382 

 383 
        % Set below threshold c to c_min
 18.899 
   9150 
 384
        mt_c(mt_c < fl_c_min) = fl_c_min; 
 385 

 386 
        % 5. no bridge and no rollover allowed
  0.003 
   9150 
 387
        if( ~bl_rollover && ~bl_bridge) 
 388 
            if (bl_default)
 389 
                % if default: only today u(cmin), transition out next period, debt wiped out
 390 
                mt_utility(:, ar_coh_neg_idx) = fl_u_cmin + fl_beta*mt_evzp_condi_z(ar_a == fl_default_aprime);
 391 
            else
 392 
                % if default is not allowed: v = fl_nan_replace
 393 
                mt_utility(:, ar_coh_neg_idx) = fl_nan_replace;
 394 
            end
 395 
        end
 396 

 397 
        % 5. Optimization: remember matlab is column major, rows must be
 398 
        % choices, columns must be states
 399 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
 400 
        % mt_utility is N by N, rows are choices, cols are states.
  3.256 
   9150 
 401
        [ar_opti_val_z, ar_opti_idx_z] = max(mt_utility); 
  0.075 
   9150 
 402
        [it_choies_n, it_states_n] = size(mt_utility); 
  0.261 
   9150 
 403
        ar_add_grid = linspace(0, it_choies_n*(it_states_n-1), it_states_n); 
  0.018 
   9150 
 404
        ar_opti_linear_idx_z = ar_opti_idx_z + ar_add_grid; 
  0.089 
   9150 
 405
        ar_opti_aprime_z = ar_a(ar_opti_idx_z); 
  0.170 
   9150 
 406
        ar_opti_c_z = mt_c(ar_opti_linear_idx_z); 
 407 

 408 
        % 6. Handle Default is optimal or not
  0.003 
   9150 
 409
        if (bl_default) 
 410 
            % if defaulting is optimal choice, at these states, not required
 411 
            % to default, non-default possible, but default could be optimal
  0.054 
   9150 
 412
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = fl_default_aprime; 
  0.072 
   9150 
 413
            ar_opti_idx_z(ar_opti_c_z <= fl_c_min) = find(ar_a == fl_default_aprime); 
 414 
        else
 415 
            % if default is not allowed, then next period same state as now
 416 
            % this is absorbing state, this is the limiting case, single
 417 
            % state space point, lowest a and lowest shock has this.
 418 
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = min(ar_a);
  0.001 
   9150 
 419
        end 
 420 

 421 
        % 6. no bridge and no rollover allowed
  0.002 
   9150 
 422
        if( ~bl_rollover && ~bl_bridge) 
 423 
            if (bl_default)
 424 
                % if default: only today u(cmin), transition out next period, debt wiped out
 425 
                ar_opti_aprime_z(ar_coh_neg_idx) = fl_default_aprime;
 426 
            else
 427 
                % if default is not allowed: v = fl_nan_replace
 428 
                ar_opti_aprime_z(ar_coh_neg_idx) = ar_a(fl_nan_replace);
 429 
            end
 430 
        end
 431 

 432 
        %% Store Optimal Choices Current Iteration
  0.046 
   9150 
 433
        mt_val(:,it_z_i) = ar_opti_val_z; 
  0.028 
   9150 
 434
        mt_pol_a(:,it_z_i) = ar_opti_aprime_z; 
  0.018 
   9150 
 435
        mt_pol_cons(:,it_z_i) = ar_opti_c_z; 
 436 

  0.003 
   9150 
 437
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     75 
 438
            mt_pol_idx(:,it_z_i) = ar_opti_idx_z; 
< 0.001 
     75 
 439
        end 
  0.005 
   9150 
 440
    end 
 441 

 442 
    %% Check Tolerance and Continuation
 443 

 444 
    % Difference across iterations
  0.142 
    122 
 445
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.133 
    122 
 446
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur); 
  0.013 
    122 
 447
    mt_pol_perc_change(it_iter, :) = sum((mt_pol_a ~= mt_pol_a_cur))/(it_a_n); 
 448 

 449 
    % Update
  0.006 
    122 
 450
    mt_val_cur = mt_val; 
  0.004 
    122 
 451
    mt_pol_a_cur = mt_pol_a; 
 452 

 453 
    % Print Iteration Results
< 0.001 
    122 
 454
    if (bl_display && (rem(it_iter, it_display_every)==0)) 
 455 
        fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 456 
            it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 457 
        tb_valpol_iter = array2table([mean(mt_val_cur,1); mean(mt_pol_a_cur,1); ...
 458 
            mt_val_cur(it_a_n,:); mt_pol_a_cur(it_a_n,:)]);
 459 
        tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 460 
        tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'Hval', 'Hap'};
 461 
        disp('mval = mean(mt_val_cur,1), average value over a')
 462 
        disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 463 
        disp('Hval = mt_val_cur(it_a_n,:), highest a state val')
 464 
        disp('Hap = mt_pol_a_cur(it_a_n,:), highest a state choice')
 465 
        disp(tb_valpol_iter);
 466 
    end
 467 

 468 
    % Continuation Conditions:
 469 
    % 1. if value function convergence criteria reached
 470 
    % 2. if policy function variation over iterations is less than
 471 
    % threshold
< 0.001 
    122 
 472
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 473
        bl_vfi_continue = false; 
  0.002 
    121 
 474
    elseif ((it_iter == it_maxiter_val) || ... 
    121 
 475
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    121 
 476
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 477 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 478
        it_iter_last = it_iter; 
< 0.001 
      1 
 479
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 480
    end 
 481 

< 0.001 
    122 
 482
end 
 483 

 484 
% End Timer
< 0.001 
      1 
 485
if (bl_time) 
< 0.001 
      1 
 486
    toc; 
< 0.001 
      1 
 487
end 
 488 

 489 
% End Profile
< 0.001 
      1 
 490
if (bl_profile) 
  0.004 
      1 
 491
    profile off 
 492 
    profile viewer
 493 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 494 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 495 
end
 496 

 497 
%% Process Optimal Choices
 498 

 499 
result_map = containers.Map('KeyType','char', 'ValueType','any');
 500 
result_map('mt_val') = mt_val;
 501 
result_map('mt_pol_idx') = mt_pol_idx;
 502 

 503 
% Find optimal Formal Informal Choices. Could have saved earlier, but was
 504 
% wasteful of resources
 505 
for it_z_i = 1:it_z_n
 506 
    for it_a_j = 1:it_a_n
 507 
        fl_z_r_borr = ar_z_r_infbr_mesh_wage(it_z_i);
 508 
        fl_z_wage = ar_z_wage_mesh_r_infbr(it_z_i);        
 509 

 510 
        fl_a = ar_a(it_a_j);
 511 
        fl_coh = f_coh(fl_z_wage, fl_a);
 512 
        fl_a_opti = mt_pol_a(it_a_j, it_z_i);
 513 

 514 
        param_map('fl_r_inf') = fl_z_r_borr;
 515 

 516 
        % call formal and informal function.
 517 
        [~, fl_opti_b_bridge, fl_opti_inf_borr_nobridge, fl_opti_for_borr, fl_opti_for_save] = ...
 518 
            ffs_fibs_min_c_cost_bridge(fl_a_opti, fl_coh, ...
 519 
            param_map, support_map, armt_map, func_map, bl_input_override);
 520 

 521 
        % store savings and borrowing formal and inf optimal choices
 522 
        mt_pol_b_bridge(it_a_j,it_z_i) = fl_opti_b_bridge;
 523 
        mt_pol_inf_borr_nobridge(it_a_j,it_z_i) = fl_opti_inf_borr_nobridge;
 524 
        mt_pol_for_borr(it_a_j,it_z_i) = fl_opti_for_borr;
 525 
        mt_pol_for_save(it_a_j,it_z_i) = fl_opti_for_save;
 526 

 527 
    end
 528 
end
 529 

 530 
result_map('cl_mt_pol_a') = {mt_pol_a, zeros(1)};
 531 
result_map('cl_mt_coh') = {f_coh(ar_z_r_infbr_mesh_wage, ar_a'), zeros(1)};
 532 

 533 
result_map('cl_mt_pol_c') = {mt_pol_cons, zeros(1)};
 534 
result_map('cl_mt_pol_b_bridge') = {mt_pol_b_bridge, zeros(1)};
 535 
result_map('cl_mt_pol_inf_borr_nobridge') = {mt_pol_inf_borr_nobridge, zeros(1)};
 536 
result_map('cl_mt_pol_for_borr') = {mt_pol_for_borr, zeros(1)};
 537 
result_map('cl_mt_pol_for_save') = {mt_pol_for_save, zeros(1)};
 538 

 539 
result_map('ar_st_pol_names') = ["cl_mt_pol_a", "cl_mt_pol_coh", "cl_mt_pol_c", ...
 540 
    "cl_mt_pol_b_bridge", "cl_mt_pol_inf_borr_nobridge", "cl_mt_pol_for_borr", "cl_mt_pol_for_save"];
 541 

 542 
% Get Discrete Choice Outcomes
 543 
result_map = ffs_fibs_identify_discrete(result_map, bl_input_override);
 544 

 545 
%% Post Solution Graph and Table Generation
 546 
% Note in comparison with *abzr*, results here, even when using identical
 547 
% parameters would differ because in *abzr* solved where choices are
 548 
% principle. Here choices are principle + interests in order to facilitate
 549 
% using the informal choice functions.
 550 
%
 551 
% Note that this means two things are
 552 
% different, on the one hand, the value of asset for to coh is different
 553 
% based on the grid of assets. If the asset grid is negative, now per grid
 554 
% point, there is more coh because that grid point of asset no longer has
 555 
% interest rates. On the other hand, if one has positive asset grid point
 556 
% on arrival, that is worth less to coh. Additionally, when making choices
 557 
% for the next period, now choices aprime includes interests. What these
 558 
% mean is that the a grid no longer has the same meaning. We should expect
 559 
% at higher savings levels, for the same grid points, if optimal grid
 560 
% choices are the same as before, consumption should be lower when b
 561 
% includes interest rates and principle. This is however, not true when
 562 
% arriving in a period with negative a levels, for the same negative a
 563 
% level and same a prime negative choice, could have higher consumption
 564 
% here becasue have to pay less interests on debt. This tends to happen for
 565 
% smaller levels of borrowing choices.
 566 
%
 567 
% Graphically, when using interest + principle, big difference in
 568 
% consumption as a fraction of (coh - aprime) figure. In those figures,
 569 
% when counting in principles only, the gap in coh and aprime is
 570 
% consumption, but now, as more is borrowed only a small fraction of coh
 571 
% and aprime gap is consumption, becuase aprime/(1+r) is put into
 572 
% consumption.
 573 

 574 
if (bl_post)
 575 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 576 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 577 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 578 

 579 
    % Standard AZ graphs
 580 
    result_map = ff_az_vf_post(param_map, support_map, armt_map, func_map, result_map);
 581 

 582 
    % Graphs for results_map with FIBS contents
 583 
    result_map = ff_az_fibs_vf_post(param_map, support_map, armt_map, func_map, result_map);
 584 
end
 585 

 586 
%% Display Various Containers
 587 
if (bl_display_defparam)
 588 
    
 589 
    %% Display 1 support_map    
 590 
    fft_container_map_display(support_map);
 591 
        
 592 
    %% Display 2 armt_map
 593 
    fft_container_map_display(armt_map);
 594 

 595 
    %% Display 3 param_map
 596 
    fft_container_map_display(param_map);
 597 
    
 598 
    %% Display 4 func_map
 599 
    fft_container_map_display(func_map);
 600 
    
 601 
    %% Display 5 result_map
 602 
    fft_container_map_display(result_map);
 603 
    
 604 
end
 605 

 606 
end

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