This is a static copy of a profile report

Home

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

Home

ff_abz_fibs_vf_vec (Calls: 1, Time: 50.241 s)
Generated 14-Jul-2019 10:59:24 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_fibs\m_abz_solve\ff_abz_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
354
mt_utility = f_util_crra(mt_c)...
178520.888 s41.6%
371
mt_utility(mt_c <= fl_c_min...
17858.656 s17.2%
307
bl_display_minccost, bl_input_...
17855.828 s11.6%
378
mt_c(mt_c < fl_c_min) = fl_...
17853.438 s6.8%
255
mt_c = f_cons_coh_save(ar_coh,...
17852.685 s5.3%
All other lines  8.747 s17.4%
Totals  50.241 s100% 
Children (called functions)

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

  87 
%% Default
  88 
% * it_param_set = 1: quick test
  89 
% * it_param_set = 2: benchmark run
  90 
% * it_param_set = 3: benchmark profile
  91 
% * it_param_set = 4: press publish button
  92 

  93 
it_param_set = 3;
  94 
bl_input_override = true;
  95 
[param_map, support_map] = ffs_abz_fibs_set_default_param(it_param_set);
  96 

  97 
% Note: param_map and support_map can be adjusted here or outside to override defaults
  98 
% To generate results as if formal informal do not matter
  99 
% param_map('fl_r_fsv') = 0.025;
 100 
% param_map('fl_r_inf') = 0.035;
 101 
% param_map('fl_r_inf_bridge') = 0.035;
 102 
% param_map('fl_r_fbr') = 0.035;
 103 
% param_map('bl_b_is_principle') = false;
 104 
% param_map('st_forbrblk_type') = 'seg3';
 105 
% param_map('fl_forbrblk_brmost') = -19;
 106 
% param_map('fl_forbrblk_brleast') = -1;
 107 
% param_map('fl_forbrblk_gap') = -1.5;
 108 
% param_map('bl_b_is_principle') = false;
 109 
% param_map('it_a_n') = 750;
 110 
% param_map('it_z_n') = 15;
 111 

 112 
[armt_map, func_map] = ffs_abz_fibs_get_funcgrid(param_map, support_map, bl_input_override); % 1 for override
 113 
default_params = {param_map support_map armt_map func_map};
 114 

 115 
%% Parse Parameters 1
 116 

 117 
% if varargin only has param_map and support_map,
 118 
params_len = length(varargin);
 119 
[default_params{1:params_len}] = varargin{:};
 120 
param_map = [param_map; default_params{1}];
 121 
support_map = [support_map; default_params{2}];
 122 
if params_len >= 1 && params_len <= 2
 123 
    % If override param_map, re-generate armt and func if they are not
 124 
    % provided
 125 
    bl_input_override = true;
 126 
    [armt_map, func_map] = ffs_abz_fibs_get_funcgrid(param_map, support_map, bl_input_override);
 127 
else
 128 
    % Override all
 129 
    armt_map = [armt_map; default_params{3}];
 130 
    func_map = [func_map; default_params{4}];
 131 
end
 132 

 133 
% append function name
 134 
st_func_name = 'ff_abz_fibs_vf_vec';
 135 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 136 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 137 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 138 

 139 
%% Parse Parameters 2
 140 

 141 
% armt_map
 142 
params_group = values(armt_map, {'ar_a', 'mt_z_trans', 'ar_z'});
 143 
[ar_a, mt_z_trans, ar_z] = params_group{:};
 144 

 145 
% Formal choice Menu/Grid and Interest Rate Menu/Grid
 146 
params_group = values(armt_map, {'ar_forbrblk_r', 'ar_forbrblk'});
 147 
[ar_forbrblk_r, ar_forbrblk] = params_group{:};
 148 

 149 
% func_map
 150 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_coh', 'f_cons_coh_fbis', 'f_cons_coh_save'});
 151 
[f_util_log, f_util_crra, f_coh, f_cons_coh_fbis, f_cons_coh_save] = params_group{:};
 152 

 153 
% param_map
 154 
params_group = values(param_map, {'it_a_n', 'it_z_n', 'fl_crra', 'fl_beta', 'fl_c_min',...
 155 
    'fl_nan_replace', 'bl_default', 'bl_bridge', 'bl_rollover', 'fl_default_aprime'});
 156 
[it_a_n, it_z_n, fl_crra, fl_beta, fl_c_min, ...
 157 
    fl_nan_replace, bl_default, bl_bridge, bl_rollover, fl_default_aprime] = params_group{:};
 158 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 159 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 160 

 161 
% param_map, Formal informal
 162 
params_group = values(param_map, {'fl_r_inf', 'fl_r_fsv', 'bl_b_is_principle'});
 163 
[fl_r_inf, fl_r_fsv, bl_b_is_principle] = params_group{:};
 164 

 165 
% support_map
 166 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 167 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 168 
    'bl_display_minccost', 'bl_display_infbridge', ...
 169 
    'bl_time', 'bl_display', 'it_display_every', 'bl_post'});
 170 
[bl_profile, st_profile_path, ...
 171 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 172 
    bl_display_minccost, bl_display_infbridge, ...
 173 
    bl_time, bl_display, it_display_every, bl_post] = params_group{:};
 174 

 175 
%% Initialize Output Matrixes
 176 
% include mt_pol_idx which we did not have in looped code
 177 

 178 
mt_val_cur = zeros(length(ar_a),length(ar_z));
 179 
mt_val = mt_val_cur - 1;
 180 
mt_pol_a = zeros(length(ar_a),length(ar_z));
 181 
mt_pol_a_cur = mt_pol_a - 1;
 182 
mt_pol_idx = zeros(length(ar_a),length(ar_z));
 183 
mt_pol_cons = zeros(length(ar_a),length(ar_z));
 184 

 185 
% collect optimal borrowing formal and informal choices
 186 
mt_pol_b_bridge = zeros(length(ar_a),length(ar_z));
 187 
mt_pol_inf_borr_nobridge = zeros(length(ar_a),length(ar_z));
 188 
mt_pol_for_borr = zeros(length(ar_a),length(ar_z));
 189 
mt_pol_for_save = zeros(length(ar_a),length(ar_z));
 190 

 191 
%% Initialize Convergence Conditions
 192 

 193 
bl_vfi_continue = true;
 194 
it_iter = 0;
 195 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 196 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 197 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 198 

 199 
%% Iterate Value Function
 200 
% Loop solution with 4 nested loops
 201 
%
 202 
% # loop 1: over exogenous states
 203 
% # loop 2: over endogenous states
 204 
% # loop 3: over choices
 205 
% # loop 4: add future utility, integration--loop over future shocks
 206 
%
 207 

 208 
% Start Profile
 209 
if (bl_profile)
 210 
    close all;
 211 
    profile off;
 212 
    profile on;
< 0.001 
      1 
 213
end 
 214 

 215 
% Start Timer
< 0.001 
      1 
 216
if (bl_time) 
< 0.001 
      1 
 217
    tic; 
< 0.001 
      1 
 218
end 
 219 

 220 
% Value Function Iteration
< 0.001 
      1 
 221
while bl_vfi_continue 
< 0.001 
    119 
 222
    it_iter = it_iter + 1; 
 223 

 224 
    %% Solve Optimization Problem Current Iteration
 225 

 226 
    % loop 1: over exogenous states
< 0.001 
    119 
 227
    for it_z_i = 1:length(ar_z) 
 228 

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

 248 
        % 1. Current Shock
< 0.001 
   1785 
 249
        fl_z = ar_z(it_z_i); 
 250 

 251 
        % 2. cash-on-hand
  0.026 
   1785 
 252
        ar_coh = f_coh(fl_z, ar_a); 
 253 

 254 
        % 3. *CASE A* initiate consumption matrix as if all save
  2.685 
   1785 
 255
        mt_c = f_cons_coh_save(ar_coh, ar_a'); 
 256 

 257 
        % 3. if Bridge Loan is Needed
 258 

 259 
        % 4. *CASE B+C* get negative coh index and get borrowing choices index
  0.005 
   1785 
 260
        ar_coh_neg_idx = (ar_coh <= 0); 
 261 

  0.003 
   1785 
 262
        ar_a_neg_idx = (ar_a < 0); 
  0.014 
   1785 
 263
        ar_coh_neg = ar_coh(ar_coh_neg_idx); 
  0.007 
   1785 
 264
        ar_a_neg = ar_a(ar_a_neg_idx); 
 265 

 266 
        % 5. if coh > 0 and ap < 0, can allow same for+inf result to all coh.
 267 
        % The procedure below works regardless of how ar_coh is sorted. get
 268 
        % the index of all negative coh elements as well as first
 269 
        % non-negative element. We solve the formal and informal problem at
 270 
        % these points, note that we only need to solve the formal and
 271 
        % informal problem for positive coh level once.
  0.019 
   1785 
 272
        ar_coh_first_pos_idx = (cumsum(ar_coh_neg_idx == 0) == 1); 
  0.003 
   1785 
 273
        ar_coh_forinfsolve_idx = (ar_coh_first_pos_idx | ar_coh_neg_idx); 
  0.009 
   1785 
 274
        ar_coh_forinfsolve_a_neg_idx = (ar_coh(ar_coh_forinfsolve_idx) <= 0); 
 275 

 276 
        % 6. *CASE B + C* Negative asset choices (borrowing), 1 col Case C
 277 
        % negp1: negative coh + 1, 1 meaning 1 positive coh, first positive
 278 
        % coh column index element grabbed.
  0.216 
   1785 
 279
        mt_coh_negp1_mesh_neg_aprime = zeros(size(ar_a_neg')) + ar_coh(ar_coh_forinfsolve_idx); 
  0.173 
   1785 
 280
        mt_neg_aprime_mesh_coh_negp1 = zeros(size(mt_coh_negp1_mesh_neg_aprime)) + ar_a_neg'; 
 281 

< 0.001 
   1785 
 282
        if (bl_bridge) 
 283 
            %         mt_neg_aprime_mesh_coh_1col4poscoh = zeros([length(ar_a_neg), (length(ar_coh_neg)+1)]) + ar_a_neg';
 284 
            %         ar_coh_neg_idx_1col4poscoh = ar_coh_neg_idx(1:(length(ar_coh_neg)+1));
 285 

 286 
            % 6. *CASE B* Solve for: if (fl_ap < 0) and if (fl_coh < 0)
  1.609 
   1785 
 287
            [mt_aprime_nobridge_negcoh, ~, mt_c_bridge_negcoh] = ffs_fibs_inf_bridge(... 
   1785 
 288
                bl_b_is_principle, fl_r_inf, ... 
   1785 
 289
                mt_neg_aprime_mesh_coh_negp1(:,ar_coh_forinfsolve_a_neg_idx), ... 
   1785 
 290
                mt_coh_negp1_mesh_neg_aprime(:,ar_coh_forinfsolve_a_neg_idx), ... 
   1785 
 291
                bl_display_infbridge, bl_input_override); 
 292 

 293 
            % generate mt_aprime_nobridge
  0.063 
   1785 
 294
            mt_neg_aprime_mesh_coh_negp1(:, ar_coh_forinfsolve_a_neg_idx) = mt_aprime_nobridge_negcoh; 
 295 
        else
 296 
            % no bridge loan needed means roll over is allowed.
 297 
            mt_neg_aprime_mesh_coh_negp1 = ar_a_neg';
< 0.001 
   1785 
 298
        end 
 299 

 300 
        % 7. *CASE B + C* formal and informal joint choices, 1 col Case C
< 0.001 
   1785 
 301
        bl_input_override = true; 
  5.832 
   1785 
 302
        [ar_max_c_nobridge, ~, ~, ~] = ... 
 303 
            ffs_fibs_min_c_cost(...
   1785 
 304
            bl_b_is_principle, fl_r_inf, fl_r_fsv, ... 
   1785 
 305
            ar_forbrblk_r, ar_forbrblk, ... 
   1785 
 306
            mt_neg_aprime_mesh_coh_negp1(:), ... 
   1785 
 307
            bl_display_minccost, bl_input_override); 
 308 

 309 
        %% Update Consumption Matrix *CASE A + B + C* Consumptions
 310 
        % Current mt_c is assuming all to be case A
 311 
        %
 312 
        % * Update Columns for case B (negative coh)
 313 
        % * Update Columns for case C (1 column): ar_coh_first_pos_idx,
 314 
        % included in ar_coh_forinfsolve_idx
 315 
        % * Update Columns for all case C: ~ar_coh_neg_idx using 1 column
 316 
        % result
 317 
        %
 318 

 319 
        % 1. Initalize all Neg Aprime consumption cost of aprime inputs
 320 
        % Initialize
  0.846 
   1785 
 321
        mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + 0; 
  0.814 
   1785 
 322
        mt_c_bridge_coh_a_neg = zeros(size(mt_max_c_nobridge_a_neg)) + 0; 
 323 

 324 
        % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
  0.089 
   1785 
 325
        mt_max_c_nobridge_negcohp1 = reshape(ar_max_c_nobridge, [size(mt_neg_aprime_mesh_coh_negp1)]); 
 326 

  0.001 
   1785 
 327
        if (bl_bridge) 
 328 
            % 2. Fill in *Case B* Bridge C-cost
  0.098 
   1785 
 329
            mt_c_bridge_coh_a_neg(:, ar_coh_neg_idx) = mt_c_bridge_negcoh; 
 330 

 331 
            % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
  0.081 
   1785 
 332
            mt_max_c_nobridge_a_neg(:, ar_coh_forinfsolve_idx) = mt_max_c_nobridge_negcohp1; 
  1.351 
   1785 
 333
            mt_max_c_nobridge_a_neg(:, ~ar_coh_forinfsolve_idx) = ... 
   1785 
 334
                zeros(size(mt_c(ar_a_neg_idx, ~ar_coh_forinfsolve_idx))) ... 
   1785 
 335
                + mt_max_c_nobridge_negcohp1(:, ~ar_coh_forinfsolve_a_neg_idx); 
 336 
        else
 337 
            mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + mt_max_c_nobridge_negcohp1;
< 0.001 
   1785 
 338
        end 
 339 

 340 
        % 3. Consumption for B + C Cases
 341 
        % note, the c cost of aprime is the same for all coh > 0, but mt_c
 342 
        % is different still for each coh and aprime.
  1.669 
   1785 
 343
        mt_c_forinfsolve = f_cons_coh_fbis(ar_coh, mt_c_bridge_coh_a_neg + mt_max_c_nobridge_a_neg); 
 344 

 345 
        % 4. Update with Case B and C
  0.362 
   1785 
 346
        mt_c(ar_a_neg_idx, :) = mt_c_forinfsolve; 
 347 

 348 
        %% Solve Optimization Problem: max_{a'} (u(c_forinf(a')) + EV(a',z'))
 349 
        % 1. EVAL current utility: N by N, f_util defined earlier
< 0.001 
   1785 
 350
        if (fl_crra == 1) 
 351 
            mt_utility = f_util_log(mt_c);
 352 
            fl_u_cmin = f_util_log(fl_c_min);
< 0.001 
   1785 
 353
        else 
 20.888 
   1785 
 354
            mt_utility = f_util_crra(mt_c); 
  0.037 
   1785 
 355
            fl_u_cmin = f_util_crra(fl_c_min); 
< 0.001 
   1785 
 356
        end 
 357 

 358 
        % 2. f(z'|z)
  0.004 
   1785 
 359
        ar_z_trans_condi = mt_z_trans(it_z_i,:); 
 360 

 361 
        % 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
 362 
        % Note: transpose ar_z_trans_condi from 1 by Z to Z by 1
 363 
        % Note: matrix multiply not dot multiply
  0.033 
   1785 
 364
        mt_evzp_condi_z = mt_val_cur * ar_z_trans_condi'; 
 365 

 366 
        % 4. EVAL add on future utility, N by N + N by 1, broadcast again
  0.318 
   1785 
 367
        mt_utility = mt_utility + fl_beta*mt_evzp_condi_z; 
 368 

  0.001 
   1785 
 369
        if (bl_default) 
 370 
            % if default: only today u(cmin), transition out next period, debt wiped out
  8.656 
   1785 
 371
            mt_utility(mt_c <= fl_c_min) = fl_u_cmin + fl_beta*mt_evzp_condi_z(ar_a == fl_default_aprime); 
 372 
        else
 373 
            % if default is not allowed: v = fl_nan_replace
 374 
            mt_utility(mt_c <= fl_c_min) = fl_nan_replace;
< 0.001 
   1785 
 375
        end 
 376 

 377 
        % Set below threshold c to c_min
  3.438 
   1785 
 378
        mt_c(mt_c < fl_c_min) = fl_c_min; 
 379 

 380 
        % 5. no bridge and no rollover allowed
  0.001 
   1785 
 381
        if( ~bl_rollover && ~bl_bridge) 
 382 
            if (bl_default)
 383 
                % if default: only today u(cmin), transition out next period, debt wiped out
 384 
                mt_utility(:, ar_coh_neg_idx) = fl_u_cmin + fl_beta*mt_evzp_condi_z(ar_a == fl_default_aprime);
 385 
            else
 386 
                % if default is not allowed: v = fl_nan_replace
 387 
                mt_utility(:, ar_coh_neg_idx) = fl_nan_replace;
 388 
            end
 389 
        end
 390 

 391 
        % 5. Optimization: remember matlab is column major, rows must be
 392 
        % choices, columns must be states
 393 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
 394 
        % mt_utility is N by N, rows are choices, cols are states.
  0.615 
   1785 
 395
        [ar_opti_val_z, ar_opti_idx_z] = max(mt_utility); 
  0.015 
   1785 
 396
        [it_choies_n, it_states_n] = size(mt_utility); 
  0.056 
   1785 
 397
        ar_add_grid = linspace(0, it_choies_n*(it_states_n-1), it_states_n); 
  0.004 
   1785 
 398
        ar_opti_linear_idx_z = ar_opti_idx_z + ar_add_grid; 
  0.017 
   1785 
 399
        ar_opti_aprime_z = ar_a(ar_opti_idx_z); 
  0.025 
   1785 
 400
        ar_opti_c_z = mt_c(ar_opti_linear_idx_z); 
 401 

 402 
        % 6. Handle Default is optimal or not
  0.001 
   1785 
 403
        if (bl_default) 
 404 
            % if defaulting is optimal choice, at these states, not required
 405 
            % to default, non-default possible, but default could be optimal
  0.011 
   1785 
 406
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = fl_default_aprime; 
  0.015 
   1785 
 407
            ar_opti_idx_z(ar_opti_c_z <= fl_c_min) = find(ar_a == fl_default_aprime); 
 408 
        else
 409 
            % if default is not allowed, then next period same state as now
 410 
            % this is absorbing state, this is the limiting case, single
 411 
            % state space point, lowest a and lowest shock has this.
 412 
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = min(ar_a);
< 0.001 
   1785 
 413
        end 
 414 

 415 
        % 6. no bridge and no rollover allowed
< 0.001 
   1785 
 416
        if( ~bl_rollover && ~bl_bridge) 
 417 
            if (bl_default)
 418 
                % if default: only today u(cmin), transition out next period, debt wiped out
 419 
                ar_opti_aprime_z(ar_coh_neg_idx) = fl_default_aprime;
 420 
            else
 421 
                % if default is not allowed: v = fl_nan_replace
 422 
                ar_opti_aprime_z(ar_coh_neg_idx) = ar_a(fl_nan_replace);
 423 
            end
 424 
        end
 425 

 426 
        %% Store Optimal Choices Current Iteration
  0.012 
   1785 
 427
        mt_val(:,it_z_i) = ar_opti_val_z; 
  0.006 
   1785 
 428
        mt_pol_a(:,it_z_i) = ar_opti_aprime_z; 
  0.004 
   1785 
 429
        mt_pol_cons(:,it_z_i) = ar_opti_c_z; 
 430 

  0.001 
   1785 
 431
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     15 
 432
            mt_pol_idx(:,it_z_i) = ar_opti_idx_z; 
< 0.001 
     15 
 433
        end 
  0.002 
   1785 
 434
    end 
 435 

 436 
    %% Check Tolerance and Continuation
 437 

 438 
    % Difference across iterations
  0.044 
    119 
 439
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.033 
    119 
 440
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur); 
  0.009 
    119 
 441
    mt_pol_perc_change(it_iter, :) = sum((mt_pol_a ~= mt_pol_a_cur))/(it_a_n); 
 442 

 443 
    % Update
  0.002 
    119 
 444
    mt_val_cur = mt_val; 
  0.002 
    119 
 445
    mt_pol_a_cur = mt_pol_a; 
 446 

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

 462 
    % Continuation Conditions:
 463 
    % 1. if value function convergence criteria reached
 464 
    % 2. if policy function variation over iterations is less than
 465 
    % threshold
< 0.001 
    119 
 466
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 467
        bl_vfi_continue = false; 
  0.002 
    118 
 468
    elseif ((it_iter == it_maxiter_val) || ... 
    118 
 469
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    118 
 470
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 471 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 472
        it_iter_last = it_iter; 
< 0.001 
      1 
 473
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 474
    end 
 475 

< 0.001 
    119 
 476
end 
 477 

 478 
% End Timer
< 0.001 
      1 
 479
if (bl_time) 
< 0.001 
      1 
 480
    toc; 
< 0.001 
      1 
 481
end 
 482 

 483 
% End Profile
< 0.001 
      1 
 484
if (bl_profile) 
  0.004 
      1 
 485
    profile off 
 486 
    profile viewer
 487 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 488 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 489 
end
 490 

 491 
%% Process Optimal Choices
 492 

 493 
result_map = containers.Map('KeyType','char', 'ValueType','any');
 494 
result_map('mt_val') = mt_val;
 495 
result_map('mt_pol_idx') = mt_pol_idx;
 496 

 497 
% Find optimal Formal Informal Choices. Could have saved earlier, but was
 498 
% wasteful of resources
 499 
for it_z_i = 1:length(ar_z)
 500 
    for it_a_j = 1:length(ar_a)
 501 
        fl_z = ar_z(it_z_i);
 502 
        fl_a = ar_a(it_a_j);
 503 
        fl_coh = f_coh(fl_z, fl_a);
 504 
        fl_a_opti = mt_pol_a(it_a_j, it_z_i);
 505 

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

 511 
        % store savings and borrowing formal and inf optimal choices
 512 
        mt_pol_b_bridge(it_a_j,it_z_i) = fl_opti_b_bridge;
 513 
        mt_pol_inf_borr_nobridge(it_a_j,it_z_i) = fl_opti_inf_borr_nobridge;
 514 
        mt_pol_for_borr(it_a_j,it_z_i) = fl_opti_for_borr;
 515 
        mt_pol_for_save(it_a_j,it_z_i) = fl_opti_for_save;
 516 

 517 
    end
 518 
end
 519 

 520 
result_map('cl_mt_pol_a') = {mt_pol_a, zeros(1)};
 521 
result_map('cl_mt_coh') = {f_coh(ar_z, ar_a'), zeros(1)};
 522 

 523 
result_map('cl_mt_pol_c') = {mt_pol_cons, zeros(1)};
 524 
result_map('cl_mt_pol_b_bridge') = {mt_pol_b_bridge, zeros(1)};
 525 
result_map('cl_mt_pol_inf_borr_nobridge') = {mt_pol_inf_borr_nobridge, zeros(1)};
 526 
result_map('cl_mt_pol_for_borr') = {mt_pol_for_borr, zeros(1)};
 527 
result_map('cl_mt_pol_for_save') = {mt_pol_for_save, zeros(1)};
 528 

 529 
result_map('ar_st_pol_names') = ["cl_mt_pol_a", "cl_mt_coh", "cl_mt_pol_c", ...
 530 
    "cl_mt_pol_b_bridge", "cl_mt_pol_inf_borr_nobridge", "cl_mt_pol_for_borr", "cl_mt_pol_for_save"];
 531 

 532 
% Get Discrete Choice Outcomes
 533 
result_map = ffs_fibs_identify_discrete(result_map, bl_input_override);
 534 

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

 564 
if (bl_post)
 565 
    bl_input_override = true;
 566 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 567 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 568 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 569 

 570 
    % Standard AZ graphs
 571 
    result_map = ff_az_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 572 

 573 
    % Graphs for results_map with FIBS contents
 574 
    result_map = ff_az_fibs_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 575 
end
 576 

 577 
%% Display Various Containers
 578 
bl_display_defparam = true;
 579 
if (bl_display_defparam)
 580 
    
 581 
    %% Display 1 support_map    
 582 
    fft_container_map_display(support_map);
 583 
        
 584 
    %% Display 2 armt_map
 585 
    fft_container_map_display(armt_map);
 586 

 587 
    %% Display 3 param_map
 588 
    fft_container_map_display(param_map);
 589 
    
 590 
    %% Display 4 func_map
 591 
    fft_container_map_display(func_map);
 592 
    
 593 
    %% Display 5 result_map
 594 
    fft_container_map_display(result_map);
 595 
    
 596 
end
 597 

 598 
end

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