This is a static copy of a profile report

Home

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

Home

ff_abz_fibs_vf_vecsv (Calls: 1, Time: 2.525 s)
Generated 14-Jul-2019 00:09:16 using performance time.
function in file C:\Users\fan\CodeDynaAsset\m_fibs\m_abz_solve\ff_abz_fibs_vf_vecsv.m
Copy to new window for comparing multiple runs

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

Line NumberCodeCallsTotal Time% TimeTime Plot
428
[ar_opti_val_z, ar_opti_idx_z]...
17850.657 s26.0%
418
mt_utility = mt_utility.*(~mt_...
17850.497 s19.7%
408
mt_utility = cl_u_c_store{it_z...
17850.401 s15.9%
373
mt_utility = f_util_crra(mt_c)...
150.208 s8.2%
473
ar_pol_diff_norm(it_iter) = no...
1190.115 s4.5%
All other lines  0.646 s25.6%
Totals  2.525 s100% 
Children (called functions)

Function NameFunction TypeCallsTotal Time% TimeTime Plot
...c)(((c).^(1-fl_crra)-1)./(1-fl_crra))anonymous function300.200 s7.9%
ffs_fibs_min_c_costfunction150.077 s3.1%
linspacefunction17850.022 s0.9%
..._save)(coh-ar_for_save./(1+fl_r_fsv))anonymous function150.018 s0.7%
ffs_fibs_inf_bridgefunction150.013 s0.5%
...tions>@(ar_z,ar_b)(ar_z*fl_w+ar_b)anonymous function17850.009 s0.3%
...h,ar_bprime_in_c)(coh+ar_bprime_in_c)anonymous function150.006 s0.3%
Self time (built-ins, overhead, etc.)  2.179 s86.3%
Totals  2.525 s100% 
Code Analyzer results
Line numberMessage
282The value assigned to variable 'ar_coh_neg' might be unused.
344Use of brackets [] is unnecessary. Use parentheses to group, if needed.
Coverage results
Show coverage for parent directory
Total lines in function604
Non-code lines (comments, blank lines)369
Code lines (lines that can run)235
Code lines that did run105
Code lines that did not run130
Coverage (did run/can run)44.68 %
Function listing
time 
Calls 
 line
   7 
function result_map = ff_abz_fibs_vf_vecsv(varargin)
   8 
%% FF_ABZ_FIBS_VF_VECSV solve infinite horizon exo shock + endo asset problem
   9 
% This program solves the infinite horizon dynamic single asset and single
  10 
% shock problem with vectorized codes.
  11 
% <https://fanwangecon.github.io/CodeDynaAsset/m_abz/solve/html/ff_abz_fibs_vf.html
  12 
% ff_abz_fibs_vf> shows looped codes. The solution is the same.
  13 
%
  14 
% The model could be invoked mainly in sveral ways:
  15 
%
  16 
% # param_map('bl_default') = true;  param_map('bl_bridge') = false;
  17 
% param_map('bl_rollover') = true; Given these, default is possible, bridge
  18 
% loans are not needed because rollover is allowed for formal loans (or
  19 
% informal loans)
  20 
% # we change param_map('bl_bridge') = true, that means
  21 
% rollover is still allowed, but only allowed using informal sources,
  22 
% formal loans no longer allow for roll-over. Furthermore, if both
  23 
% bl_bridge and bl_rollover are false, that means we are not allowing for
  24 
% rollover at all, so households can not borrow such that they end up with
  25 
% negative cash-on-hand.
  26 
%
  27 
% Default simulation bl_bridge = false.
  28 
%
  29 
% @param param_map container parameter container
  30 
%
  31 
% @param support_map container support container
  32 
%
  33 
% @param armt_map container container with states, choices and shocks
  34 
% grids that are inputs for grid based solution algorithm
  35 
%
  36 
% @param func_map container container with function handles for
  37 
% consumption cash-on-hand etc.
  38 
%
  39 
% @return result_map container contains policy function matrix, value
  40 
% function matrix, iteration results, and policy function, value function
  41 
% and iteration results tables.
  42 
%
  43 
% @example
  44 
%
  45 
%    % Get Default Parameters
  46 
%    it_param_set = 4;
  47 
%    [param_map, support_map] = ffs_abz_fibs_set_default_param(it_param_set);
  48 
%    % Chnage param_map keys for borrowing
  49 
%    param_map('fl_b_bd') = -20; % borrow bound
  50 
%    param_map('bl_default') = false; % true if allow for default
  51 
%    param_map('fl_c_min') = 0.0001; % u(c_min) when default
  52 
%    % Change Keys in param_map
  53 
%    param_map('it_a_n') = 500;
  54 
%    param_map('it_z_n') = 11;
  55 
%    param_map('fl_a_max') = 100;
  56 
%    param_map('fl_w') = 1.3;
  57 
%    param_map('fl_r_inf') = 0.06;
  58 
%    param_map('fl_r_fsv') = 0.01;
  59 
%    param_map('fl_r_fbr') = 0.035;
  60 
%    param_map('bl_b_is_principle') = false;
  61 
%    % see: ffs_for_br_block.m
  62 
%    param_map('st_forbrblk_type') = 'seg3';
  63 
%    param_map('fl_forbrblk_brmost') = -10;
  64 
%    param_map('fl_forbrblk_brleast') = -1;
  65 
%    param_map('fl_forbrblk_gap') = -1;
  66 
%    % Change Keys support_map
  67 
%    support_map('bl_display') = false;
  68 
%    support_map('bl_post') = true;
  69 
%    support_map('bl_display_final') = false;
  70 
%    % Call Program with external parameters that override defaults.
  71 
%    ff_abz_fibs_vf_vecsv(param_map, support_map);
  72 
%
  73 
%
  74 
% @include
  75 
%
  76 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc/html/ffs_abz_fibs_set_default_param.html ffs_abz_fibs_set_default_param>
  77 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc/html/ffs_abz_fibs_get_funcgrid.html ffs_abz_fibs_get_funcgrid>
  78 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_min_c_cost_bridge.html ffs_fibs_min_c_cost_bridge>
  79 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_inf_bridge.html ffs_fibs_inf_bridge>
  80 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc_fibs/html/ffs_fibs_min_c_cost.html ffs_fibs_min_c_cost>
  81 
% * <https://fanwangecon.github.io/CodeDynaAsset/m_az/solvepost/html/ff_az_vf_post.html ff_az_vf_post>
  82 
%
  83 
% @seealso
  84 
%
  85 
% * 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>
  86 
% * 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>
  87 
% * 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>
  88 
%
  89 

  90 
%% Default
  91 
%
  92 
% * it_param_set = 1: quick test
  93 
% * it_param_set = 2: benchmark run
  94 
% * it_param_set = 3: benchmark profile
  95 
% * it_param_set = 4: press publish button
  96 
%
  97 
% go to
  98 
% <https://fanwangecon.github.io/CodeDynaAsset/m_fibs/paramfunc/html/ffs_abz_fibs_fibs_set_default_param.html
  99 
% ffs_abz_fibs_fibs_set_default_param> to change parameters in param_map container.
 100 
% The parameters can also be updated here directly after obtaining them
 101 
% from ffs_abz_fibs_set_default_param as we possibly change it_a_n and it_z_n
 102 
% here.
 103 

 104 
it_param_set = 3;
 105 
bl_input_override = true;
 106 
[param_map, support_map] = ffs_abz_fibs_set_default_param(it_param_set);
 107 

 108 
% Note: param_map and support_map can be adjusted here or outside to override defaults
 109 
% To generate results as if formal informal do not matter
 110 
% param_map('fl_r_fsv') = 0.025;
 111 
% param_map('fl_r_inf') = 0.035;
 112 
% param_map('fl_r_inf_bridge') = 0.035;
 113 
% param_map('fl_r_fbr') = 0.035;
 114 
% param_map('bl_b_is_principle') = false;
 115 
% param_map('st_forbrblk_type') = 'seg3';
 116 
% param_map('fl_forbrblk_brmost') = -19;
 117 
% param_map('fl_forbrblk_brleast') = -1;
 118 
% param_map('fl_forbrblk_gap') = -1.5;
 119 
% param_map('bl_b_is_principle') = false;
 120 
% param_map('it_a_n') = 750;
 121 
% param_map('it_z_n') = 15;
 122 

 123 
[armt_map, func_map] = ffs_abz_fibs_get_funcgrid(param_map, support_map, bl_input_override); % 1 for override
 124 
default_params = {param_map support_map armt_map func_map};
 125 

 126 
%% Parse Parameters 1
 127 

 128 
% if varargin only has param_map and support_map,
 129 
params_len = length(varargin);
 130 
[default_params{1:params_len}] = varargin{:};
 131 
param_map = [param_map; default_params{1}];
 132 
support_map = [support_map; default_params{2}];
 133 
if params_len >= 1 && params_len <= 2
 134 
    % If override param_map, re-generate armt and func if they are not
 135 
    % provided
 136 
    bl_input_override = true;
 137 
    [armt_map, func_map] = ffs_abz_fibs_get_funcgrid(param_map, support_map, bl_input_override);
 138 
else
 139 
    % Override all
 140 
    armt_map = [armt_map; default_params{3}];
 141 
    func_map = [func_map; default_params{4}];
 142 
end
 143 

 144 
% append function name
 145 
st_func_name = 'ff_abz_fibs_vf_vecsv';
 146 
support_map('st_profile_name_main') = [st_func_name support_map('st_profile_name_main')];
 147 
support_map('st_mat_name_main') = [st_func_name support_map('st_mat_name_main')];
 148 
support_map('st_img_name_main') = [st_func_name support_map('st_img_name_main')];
 149 

 150 
%% Parse Parameters 2
 151 

 152 
% armt_map
 153 
params_group = values(armt_map, {'ar_a', 'mt_z_trans', 'ar_z'});
 154 
[ar_a, mt_z_trans, ar_z] = params_group{:};
 155 

 156 
% Formal choice Menu/Grid and Interest Rate Menu/Grid
 157 
params_group = values(armt_map, {'ar_forbrblk_r', 'ar_forbrblk'});
 158 
[ar_forbrblk_r, ar_forbrblk] = params_group{:};
 159 

 160 
% func_map
 161 
params_group = values(func_map, {'f_util_log', 'f_util_crra', 'f_coh', 'f_cons_coh_fbis', 'f_cons_coh_save'});
 162 
[f_util_log, f_util_crra, f_coh, f_cons_coh_fbis, f_cons_coh_save] = params_group{:};
 163 

 164 
% param_map
 165 
params_group = values(param_map, {'it_a_n', 'it_z_n', 'fl_crra', 'fl_beta', 'fl_c_min',...
 166 
    'fl_nan_replace', 'bl_default', 'bl_bridge', 'bl_rollover', 'fl_default_aprime'});
 167 
[it_a_n, it_z_n, fl_crra, fl_beta, fl_c_min, ...
 168 
    fl_nan_replace, bl_default, bl_bridge, bl_rollover, fl_default_aprime] = params_group{:};
 169 
params_group = values(param_map, {'it_maxiter_val', 'fl_tol_val', 'fl_tol_pol', 'it_tol_pol_nochange'});
 170 
[it_maxiter_val, fl_tol_val, fl_tol_pol, it_tol_pol_nochange] = params_group{:};
 171 

 172 
% param_map, Formal informal
 173 
params_group = values(param_map, {'fl_r_inf', 'fl_r_fsv', 'bl_b_is_principle'});
 174 
[fl_r_inf, fl_r_fsv, bl_b_is_principle] = params_group{:};
 175 

 176 
% support_map
 177 
params_group = values(support_map, {'bl_profile', 'st_profile_path', ...
 178 
    'st_profile_prefix', 'st_profile_name_main', 'st_profile_suffix',...
 179 
    'bl_display_minccost', 'bl_display_infbridge', ...
 180 
    'bl_time', 'bl_display', 'it_display_every', 'bl_post'});
 181 
[bl_profile, st_profile_path, ...
 182 
    st_profile_prefix, st_profile_name_main, st_profile_suffix, ...
 183 
    bl_display_minccost, bl_display_infbridge, ...
 184 
    bl_time, bl_display, it_display_every, bl_post] = params_group{:};
 185 

 186 
%% Initialize Output Matrixes
 187 
% include mt_pol_idx which we did not have in looped code
 188 

 189 
mt_val_cur = zeros(length(ar_a),length(ar_z));
 190 
mt_val = mt_val_cur - 1;
 191 
mt_pol_a = zeros(length(ar_a),length(ar_z));
 192 
mt_pol_a_cur = mt_pol_a - 1;
 193 
mt_pol_idx = zeros(length(ar_a),length(ar_z));
 194 
mt_pol_cons = zeros(length(ar_a),length(ar_z));
 195 

 196 
% collect optimal borrowing formal and informal choices
 197 
mt_pol_b_bridge = zeros(length(ar_a),length(ar_z));
 198 
mt_pol_inf_borr_nobridge = zeros(length(ar_a),length(ar_z));
 199 
mt_pol_for_borr = zeros(length(ar_a),length(ar_z));
 200 
mt_pol_for_save = zeros(length(ar_a),length(ar_z));
 201 

 202 
% We did not need these in ff_abz_vf or ff_abz_vf_vec
 203 
% see
 204 
% <https://fanwangecon.github.io/M4Econ/support/speed/partupdate/fs_u_c_partrepeat_main.html
 205 
% fs_u_c_partrepeat_main> for why store using cells.
 206 
cl_u_c_store = cell([it_z_n, 1]);
 207 
cl_c_store = cell([it_z_n, 1]);
 208 
cl_c_valid_idx = cell([it_z_n, 1]);
 209 

 210 
%% Initialize Convergence Conditions
 211 

 212 
bl_vfi_continue = true;
 213 
it_iter = 0;
 214 
ar_val_diff_norm = zeros([it_maxiter_val, 1]);
 215 
ar_pol_diff_norm = zeros([it_maxiter_val, 1]);
 216 
mt_pol_perc_change = zeros([it_maxiter_val, it_z_n]);
 217 

 218 
%% Iterate Value Function
 219 
% Loop solution with 4 nested loops
 220 
%
 221 
% # loop 1: over exogenous states
 222 
% # loop 2: over endogenous states
 223 
% # loop 3: over choices
 224 
% # loop 4: add future utility, integration--loop over future shocks
 225 
%
 226 

 227 
% Start Profile
 228 
if (bl_profile)
 229 
    close all;
 230 
    profile off;
 231 
    profile on;
< 0.001 
      1 
 232
end 
 233 

 234 
% Start Timer
< 0.001 
      1 
 235
if (bl_time) 
< 0.001 
      1 
 236
    tic; 
< 0.001 
      1 
 237
end 
 238 

 239 
% Value Function Iteration
< 0.001 
      1 
 240
while bl_vfi_continue 
< 0.001 
    119 
 241
    it_iter = it_iter + 1; 
 242 

 243 
    %% Solve Optimization Problem Current Iteration
 244 

 245 
    % loop 1: over exogenous states
< 0.001 
    119 
 246
    for it_z_i = 1:length(ar_z) 
 247 

 248 
        %% Solve the Formal Informal Problem for each a' and coh: c_forinf(a')
 249 
        % find the today's consumption maximizing formal and informal
 250 
        % choices given a' and coh. The formal and informal choices need to
 251 
        % generate exactly a', but depending on which formal and informal
 252 
        % joint choice is used, the consumption cost today a' is different.
 253 
        % Note here, a is principle + interests. Three areas:
 254 
        %
 255 
        % * *CASE A* a' > 0: savings, do not need to optimize over formal and
 256 
        % informal choices
 257 
        % * *CASE B* a' < 0 & coh < 0: need bridge loan to pay for unpaid debt, and
 258 
        % borrowing over-all, need to first pick bridge loan to pay for
 259 
        % debt, if bridge loan is insufficient, go into default. After
 260 
        % bridge loan, optimize over formal+informal, borrow+save joint
 261 
        % choices.
 262 
        % * *CASE C* a' < 0 & coh > 0: do not need to get informal bridge loans,
 263 
        % optimize over for+inf save, for+save+borr, inf+borr only, for
 264 
        % borrow only.
 265 
        %
 266 

 267 
        % 1. Current Shock
< 0.001 
   1785 
 268
        fl_z = ar_z(it_z_i); 
 269 

 270 
        % 2. cash-on-hand
  0.017 
   1785 
 271
        ar_coh = f_coh(fl_z, ar_a); 
 272 

 273 
        % Consumption and u(c) only need to be evaluated once
  0.001 
   1785 
 274
        if (it_iter == 1) 
 275 

 276 
            % 3. *CASE A* initiate consumption matrix as if all save
  0.019 
     15 
 277
            mt_c = f_cons_coh_save(ar_coh, ar_a'); 
 278 

 279 
            % 4. *CASE B+C* get negative coh index and get borrowing choices index
< 0.001 
     15 
 280
            ar_coh_neg_idx = (ar_coh <= 0); 
< 0.001 
     15 
 281
            ar_a_neg_idx = (ar_a < 0); 
< 0.001 
     15 
 282
            ar_coh_neg = ar_coh(ar_coh_neg_idx); 
< 0.001 
     15 
 283
            ar_a_neg = ar_a(ar_a_neg_idx); 
 284 

 285 
            % 5. if coh > 0 and ap < 0, can allow same for+inf result to all coh.
 286 
            % The procedure below works regardless of how ar_coh is sorted. get
 287 
            % the index of all negative coh elements as well as first
 288 
            % non-negative element. We solve the formal and informal problem at
 289 
            % these points, note that we only need to solve the formal and
 290 
            % informal problem for positive coh level once.
< 0.001 
     15 
 291
            ar_coh_first_pos_idx = (cumsum(ar_coh_neg_idx == 0) == 1); 
< 0.001 
     15 
 292
            ar_coh_forinfsolve_idx = (ar_coh_first_pos_idx | ar_coh_neg_idx); 
< 0.001 
     15 
 293
            ar_coh_forinfsolve_a_neg_idx = (ar_coh(ar_coh_forinfsolve_idx) <= 0); 
 294 

 295 
            % 6. *CASE B + C* Negative asset choices (borrowing), 1 col Case C
 296 
            % negp1: negative coh + 1, 1 meaning 1 positive coh, first positive
 297 
            % coh column index element grabbed.
  0.004 
     15 
 298
            mt_coh_negp1_mesh_neg_aprime = zeros(size(ar_a_neg')) + ar_coh(ar_coh_forinfsolve_idx); 
  0.003 
     15 
 299
            mt_neg_aprime_mesh_coh_negp1 = zeros(size(mt_coh_negp1_mesh_neg_aprime)) + ar_a_neg'; 
 300 

< 0.001 
     15 
 301
            if (bl_bridge) 
 302 
                %         mt_neg_aprime_mesh_coh_1col4poscoh = zeros([length(ar_a_neg), (length(ar_coh_neg)+1)]) + ar_a_neg';
 303 
                %         ar_coh_neg_idx_1col4poscoh = ar_coh_neg_idx(1:(length(ar_coh_neg)+1));
 304 

 305 
                % 6. *CASE B* Solve for: if (fl_ap < 0) and if (fl_coh < 0)
  0.021 
     15 
 306
                [mt_aprime_nobridge_negcoh, ~, mt_c_bridge_negcoh] = ffs_fibs_inf_bridge(... 
     15 
 307
                    bl_b_is_principle, fl_r_inf, ... 
     15 
 308
                    mt_neg_aprime_mesh_coh_negp1(:,ar_coh_forinfsolve_a_neg_idx), ... 
     15 
 309
                    mt_coh_negp1_mesh_neg_aprime(:,ar_coh_forinfsolve_a_neg_idx), ... 
     15 
 310
                    bl_display_infbridge, bl_input_override); 
 311 

 312 
                % generate mt_aprime_nobridge
< 0.001 
     15 
 313
                mt_neg_aprime_mesh_coh_negp1(:, ar_coh_forinfsolve_a_neg_idx) = mt_aprime_nobridge_negcoh; 
 314 
            else
 315 
                % no bridge loan needed means roll over is allowed.
 316 
                mt_neg_aprime_mesh_coh_negp1 = ar_a_neg';
< 0.001 
     15 
 317
            end 
 318 

 319 
            % 7. *CASE B + C* formal and informal joint choices, 1 col Case C
< 0.001 
     15 
 320
            bl_input_override = true; 
  0.081 
     15 
 321
            [ar_max_c_nobridge, ~, ~, ~] = ... 
 322 
                ffs_fibs_min_c_cost(...
     15 
 323
                bl_b_is_principle, fl_r_inf, fl_r_fsv, ... 
     15 
 324
                ar_forbrblk_r, ar_forbrblk, ... 
     15 
 325
                mt_neg_aprime_mesh_coh_negp1(:), ... 
     15 
 326
                bl_display_minccost, bl_input_override); 
 327 

 328 
            %% Update Consumption Matrix *CASE A + B + C* Consumptions
 329 
            % Current mt_c is assuming all to be case A
 330 
            %
 331 
            % * Update Columns for case B (negative coh)
 332 
            % * Update Columns for case C (1 column): ar_coh_first_pos_idx,
 333 
            % included in ar_coh_forinfsolve_idx
 334 
            % * Update Columns for all case C: ~ar_coh_neg_idx using 1 column
 335 
            % result
 336 
            %
 337 

 338 
            % 1. Initalize all Neg Aprime consumption cost of aprime inputs
 339 
            % Initialize
  0.011 
     15 
 340
            mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + 0; 
  0.010 
     15 
 341
            mt_c_bridge_coh_a_neg = zeros(size(mt_max_c_nobridge_a_neg)) + 0; 
 342 

 343 
            % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
< 0.001 
     15 
 344
            mt_max_c_nobridge_negcohp1 = reshape(ar_max_c_nobridge, [size(mt_neg_aprime_mesh_coh_negp1)]); 
 345 

< 0.001 
     15 
 346
            if (bl_bridge) 
 347 
                % 2. Fill in *Case B* Bridge C-cost
< 0.001 
     15 
 348
                mt_c_bridge_coh_a_neg(:, ar_coh_neg_idx) = mt_c_bridge_negcoh; 
 349 

 350 
                % 2. Fill in *Case B* and *Case C* (one column) Other C-cost
< 0.001 
     15 
 351
                mt_max_c_nobridge_a_neg(:, ar_coh_forinfsolve_idx) = mt_max_c_nobridge_negcohp1; 
  0.013 
     15 
 352
                mt_max_c_nobridge_a_neg(:, ~ar_coh_forinfsolve_idx) = ... 
     15 
 353
                    zeros(size(mt_c(ar_a_neg_idx, ~ar_coh_forinfsolve_idx))) ... 
     15 
 354
                    + mt_max_c_nobridge_negcohp1(:, ~ar_coh_forinfsolve_a_neg_idx); 
 355 
            else
 356 
                mt_max_c_nobridge_a_neg = zeros([length(ar_a_neg), length(ar_coh)]) + mt_max_c_nobridge_negcohp1;
< 0.001 
     15 
 357
            end 
 358 

 359 
            % 3. Consumption for B + C Cases
 360 
            % note, the c cost of aprime is the same for all coh > 0, but mt_c
 361 
            % is different still for each coh and aprime.
  0.019 
     15 
 362
            mt_c_forinfsolve = f_cons_coh_fbis(ar_coh, mt_c_bridge_coh_a_neg + mt_max_c_nobridge_a_neg); 
 363 

 364 
            % 4. Update with Case B and C
  0.003 
     15 
 365
            mt_c(ar_a_neg_idx, :) = mt_c_forinfsolve; 
 366 

 367 
            %% Evaluate u(c) and store
 368 
            % 1. EVAL current utility: N by N, f_util defined earlier
< 0.001 
     15 
 369
            if (fl_crra == 1) 
 370 
                mt_utility = log(mt_c);
 371 
                fl_u_cmin = f_util_log(fl_c_min);
< 0.001 
     15 
 372
            else 
  0.208 
     15 
 373
                mt_utility = f_util_crra(mt_c); 
  0.001 
     15 
 374
                fl_u_cmin = f_util_crra(fl_c_min); 
< 0.001 
     15 
 375
            end 
 376 

 377 
            % 2. Invliad consumption points
  0.004 
     15 
 378
            mt_it_c_valid_idx = (mt_c <= fl_c_min); 
 379 
            % Set below threshold c to c_min
  0.040 
     15 
 380
            mt_c(mt_c < fl_c_min) = fl_c_min; 
 381 

 382 
            % 3. Invalid points if bridge not possible also no rollover
< 0.001 
     15 
 383
            if( ~bl_rollover && ~bl_bridge) 
 384 
                mt_it_c_valid_idx(:, ar_coh_neg_idx) = 1;
 385 
            end
 386 

 387 
            % 4. Eliminate Complex Numbers
  0.087 
     15 
 388
            mt_utility(mt_it_c_valid_idx) = fl_u_cmin; 
 389 

 390 
            % 5. Store in cells
< 0.001 
     15 
 391
            cl_c_store{it_z_i} = mt_c; 
< 0.001 
     15 
 392
            cl_u_c_store{it_z_i} = mt_utility; 
< 0.001 
     15 
 393
            cl_c_valid_idx{it_z_i} = mt_it_c_valid_idx; 
 394 

< 0.001 
     15 
 395
        end 
 396 

 397 
        %% Solve Optimization Problem: max_{a'} (u(c_forinf(a')) + EV(a',z'))
 398 

 399 
        % 1. f(z'|z)
  0.002 
   1785 
 400
        ar_z_trans_condi = mt_z_trans(it_z_i,:); 
 401 

 402 
        % 2. EVAL EV((A',K'),Z'|Z) = V((A',K'),Z') x p(z'|z)', (N by Z) x (Z by 1) = N by 1
 403 
        % Note: transpose ar_z_trans_condi from 1 by Z to Z by 1
 404 
        % Note: matrix multiply not dot multiply
  0.012 
   1785 
 405
        mt_evzp_condi_z = mt_val_cur * ar_z_trans_condi'; 
 406 

 407 
        % 3. EVAL add on future utility, N by N + N by 1, broadcast again
  0.401 
   1785 
 408
        mt_utility = cl_u_c_store{it_z_i} + fl_beta*mt_evzp_condi_z; 
 409 

 410 
        % 4. Index update
 411 
        % using the method below is much faster than index replace
 412 
        % see <https://fanwangecon.github.io/M4Econ/support/speed/index/fs_subscript.html fs_subscript>
  0.002 
   1785 
 413
        mt_it_c_valid_idx = cl_c_valid_idx{it_z_i}; 
 414 
        % Default or Not Utility Handling
< 0.001 
   1785 
 415
        if (bl_default) 
 416 
            % if default: only today u(cmin), transition out next period, debt wiped out
  0.014 
   1785 
 417
            fl_v_default = fl_u_cmin + fl_beta*mt_evzp_condi_z(ar_a == fl_default_aprime); 
  0.497 
   1785 
 418
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_v_default*(mt_it_c_valid_idx); 
 419 
        else
 420 
            % if default is not allowed: v = u(cmin)
 421 
            mt_utility = mt_utility.*(~mt_it_c_valid_idx) + fl_nan_replace*(mt_it_c_valid_idx);
< 0.001 
   1785 
 422
        end 
 423 

 424 
        % Optimization: remember matlab is column major, rows must be
 425 
        % choices, columns must be states
 426 
        % <https://en.wikipedia.org/wiki/Row-_and_column-major_order COLUMN-MAJOR>
 427 
        % mt_utility is N by N, rows are choices, cols are states.
  0.657 
   1785 
 428
        [ar_opti_val_z, ar_opti_idx_z] = max(mt_utility); 
  0.010 
   1785 
 429
        [it_choies_n, it_states_n] = size(mt_utility); 
  0.031 
   1785 
 430
        ar_add_grid = linspace(0, it_choies_n*(it_states_n-1), it_states_n); 
  0.003 
   1785 
 431
        ar_opti_linear_idx_z = ar_opti_idx_z + ar_add_grid; 
  0.015 
   1785 
 432
        ar_opti_aprime_z = ar_a(ar_opti_idx_z); 
  0.040 
   1785 
 433
        ar_opti_c_z = cl_c_store{it_z_i}(ar_opti_linear_idx_z); 
 434 

 435 
        % Handle Default is optimal or not
< 0.001 
   1785 
 436
        if (bl_default) 
 437 
            % if defaulting is optimal choice, at these states, not required
 438 
            % to default, non-default possible, but default could be optimal
  0.010 
   1785 
 439
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = fl_default_aprime; 
  0.015 
   1785 
 440
            ar_opti_idx_z(ar_opti_c_z <= fl_c_min) = find(ar_a == fl_default_aprime); 
 441 
        else
 442 
            % if default is not allowed, then next period same state as now
 443 
            % this is absorbing state, this is the limiting case, single
 444 
            % state space point, lowest a and lowest shock has this.
 445 
            ar_opti_aprime_z(ar_opti_c_z <= fl_c_min) = min(ar_a);
< 0.001 
   1785 
 446
        end 
 447 

 448 
        % 6. no bridge and no rollover allowed
< 0.001 
   1785 
 449
        if( ~bl_rollover && ~bl_bridge) 
 450 
            if (bl_default)
 451 
                % if default: only today u(cmin), transition out next period, debt wiped out
 452 
                ar_opti_aprime_z(ar_coh_neg_idx) = fl_default_aprime;
 453 
            else
 454 
                % if default is not allowed: v = fl_nan_replace
 455 
                ar_opti_aprime_z(ar_coh_neg_idx) = ar_a(fl_nan_replace);
 456 
            end
 457 
        end
 458 

 459 
        % store optimal values
  0.013 
   1785 
 460
        mt_val(:,it_z_i) = ar_opti_val_z; 
  0.006 
   1785 
 461
        mt_pol_a(:,it_z_i) = ar_opti_aprime_z; 
  0.003 
   1785 
 462
        mt_pol_cons(:,it_z_i) = ar_opti_c_z; 
 463 

  0.001 
   1785 
 464
        if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
     15 
 465
            mt_pol_idx(:,it_z_i) = ar_opti_idx_z; 
< 0.001 
     15 
 466
        end 
  0.002 
   1785 
 467
    end 
 468 

 469 
    %% Check Tolerance and Continuation
 470 

 471 
    % Difference across iterations
  0.100 
    119 
 472
    ar_val_diff_norm(it_iter) = norm(mt_val - mt_val_cur); 
  0.115 
    119 
 473
    ar_pol_diff_norm(it_iter) = norm(mt_pol_a - mt_pol_a_cur); 
  0.009 
    119 
 474
    mt_pol_perc_change(it_iter, :) = sum((mt_pol_a ~= mt_pol_a_cur))/(it_a_n); 
 475 

 476 
    % Update
  0.002 
    119 
 477
    mt_val_cur = mt_val; 
  0.001 
    119 
 478
    mt_pol_a_cur = mt_pol_a; 
 479 

 480 
    % Print Iteration Results
< 0.001 
    119 
 481
    if (bl_display && (rem(it_iter, it_display_every)==0)) 
 482 
        fprintf('VAL it_iter:%d, fl_diff:%d, fl_diff_pol:%d\n', ...
 483 
            it_iter, ar_val_diff_norm(it_iter), ar_pol_diff_norm(it_iter));
 484 
        tb_valpol_iter = array2table([mean(mt_val_cur,1); mean(mt_pol_a_cur,1); ...
 485 
            mt_val_cur(it_a_n,:); mt_pol_a_cur(it_a_n,:)]);
 486 
        tb_valpol_iter.Properties.VariableNames = strcat('z', string((1:size(mt_val_cur,2))));
 487 
        tb_valpol_iter.Properties.RowNames = {'mval', 'map', 'Hval', 'Hap'};
 488 
        disp('mval = mean(mt_val_cur,1), average value over a')
 489 
        disp('map  = mean(mt_pol_a_cur,1), average choice over a')
 490 
        disp('Hval = mt_val_cur(it_a_n,:), highest a state val')
 491 
        disp('Hap = mt_pol_a_cur(it_a_n,:), highest a state choice')
 492 
        disp(tb_valpol_iter);
 493 
    end
 494 

 495 
    % Continuation Conditions:
 496 
    % 1. if value function convergence criteria reached
 497 
    % 2. if policy function variation over iterations is less than
 498 
    % threshold
< 0.001 
    119 
 499
    if (it_iter == (it_maxiter_val + 1)) 
< 0.001 
      1 
 500
        bl_vfi_continue = false; 
  0.002 
    118 
 501
    elseif ((it_iter == it_maxiter_val) || ... 
    118 
 502
            (ar_val_diff_norm(it_iter) < fl_tol_val) || ... 
    118 
 503
            (sum(ar_pol_diff_norm(max(1, it_iter-it_tol_pol_nochange):it_iter)) < fl_tol_pol)) 
 504 
        % Fix to max, run again to save results if needed
< 0.001 
      1 
 505
        it_iter_last = it_iter; 
< 0.001 
      1 
 506
        it_iter = it_maxiter_val; 
< 0.001 
      1 
 507
    end 
 508 

< 0.001 
    119 
 509
end 
 510 

 511 
% End Timer
< 0.001 
      1 
 512
if (bl_time) 
< 0.001 
      1 
 513
    toc; 
< 0.001 
      1 
 514
end 
 515 

 516 
% End Profile
< 0.001 
      1 
 517
if (bl_profile) 
  0.001 
      1 
 518
    profile off 
 519 
    profile viewer
 520 
    st_file_name = [st_profile_prefix st_profile_name_main st_profile_suffix];
 521 
    profsave(profile('info'), strcat(st_profile_path, st_file_name));
 522 
end
 523 

 524 
%% Process Optimal Choices
 525 

 526 
result_map = containers.Map('KeyType','char', 'ValueType','any');
 527 
result_map('mt_val') = mt_val;
 528 
result_map('mt_pol_idx') = mt_pol_idx;
 529 

 530 
% Find optimal Formal Informal Choices. Could have saved earlier, but was
 531 
% wasteful of resources
 532 
for it_z_i = 1:length(ar_z)
 533 
    for it_a_j = 1:length(ar_a)
 534 
        fl_z = ar_z(it_z_i);
 535 
        fl_a = ar_a(it_a_j);
 536 
        fl_coh = f_coh(fl_z, fl_a);
 537 
        fl_a_opti = mt_pol_a(it_a_j, it_z_i);
 538 

 539 
        % call formal and informal function.
 540 
        [~, fl_opti_b_bridge, fl_opti_inf_borr_nobridge, fl_opti_for_borr, fl_opti_for_save] = ...
 541 
            ffs_fibs_min_c_cost_bridge(fl_a_opti, fl_coh, ...
 542 
            param_map, support_map, armt_map, func_map, bl_input_override);
 543 

 544 
        % store savings and borrowing formal and inf optimal choices
 545 
        mt_pol_b_bridge(it_a_j,it_z_i) = fl_opti_b_bridge;
 546 
        mt_pol_inf_borr_nobridge(it_a_j,it_z_i) = fl_opti_inf_borr_nobridge;
 547 
        mt_pol_for_borr(it_a_j,it_z_i) = fl_opti_for_borr;
 548 
        mt_pol_for_save(it_a_j,it_z_i) = fl_opti_for_save;
 549 

 550 
    end
 551 
end
 552 

 553 
result_map('cl_mt_pol_a') = {mt_pol_a, zeros(1)};
 554 
result_map('cl_mt_coh') = {f_coh(ar_z, ar_a'), zeros(1)};
 555 

 556 
result_map('cl_mt_pol_c') = {mt_pol_cons, zeros(1)};
 557 
result_map('cl_mt_pol_b_bridge') = {mt_pol_b_bridge, zeros(1)};
 558 
result_map('cl_mt_pol_inf_borr_nobridge') = {mt_pol_inf_borr_nobridge, zeros(1)};
 559 
result_map('cl_mt_pol_for_borr') = {mt_pol_for_borr, zeros(1)};
 560 
result_map('cl_mt_pol_for_save') = {mt_pol_for_save, zeros(1)};
 561 

 562 
result_map('ar_st_pol_names') = ["cl_mt_pol_a", "cl_mt_coh", "cl_mt_pol_c", ...
 563 
    "cl_mt_pol_b_bridge", "cl_mt_pol_inf_borr_nobridge", "cl_mt_pol_for_borr", "cl_mt_pol_for_save"];
 564 

 565 
% Get Discrete Choice Outcomes
 566 
result_map = ffs_fibs_identify_discrete(result_map, bl_input_override);
 567 

 568 
%% Post Solution Graph and Table Generation
 569 
% Note in comparison with *abz*, results here, even when using identical
 570 
% parameters would differ because in *abz* solved where choices are
 571 
% principle. Here choices are principle + interests in order to facilitate
 572 
% using the informal choice functions.
 573 
%
 574 
% Note that this means two things are
 575 
% different, on the one hand, the value of asset for to coh is different
 576 
% based on the grid of assets. If the asset grid is negative, now per grid
 577 
% point, there is more coh because that grid point of asset no longer has
 578 
% interest rates. On the other hand, if one has positive asset grid point
 579 
% on arrival, that is worth less to coh. Additionally, when making choices
 580 
% for the next period, now choices aprime includes interests. What these
 581 
% mean is that the a grid no longer has the same meaning. We should expect
 582 
% at higher savings levels, for the same grid points, if optimal grid
 583 
% choices are the same as before, consumption should be lower when b
 584 
% includes interest rates and principle. This is however, not true when
 585 
% arriving in a period with negative a levels, for the same negative a
 586 
% level and same a prime negative choice, could have higher consumption
 587 
% here becasue have to pay less interests on debt. This tends to happen for
 588 
% smaller levels of borrowing choices.
 589 
%
 590 
% Graphically, when using interest + principle, big difference in
 591 
% consumption as a fraction of (coh - aprime) figure. In those figures,
 592 
% when counting in principles only, the gap in coh and aprime is
 593 
% consumption, but now, as more is borrowed only a small fraction of coh
 594 
% and aprime gap is consumption, becuase aprime/(1+r) is put into
 595 
% consumption.
 596 

 597 
if (bl_post)
 598 
    bl_input_override = true;
 599 
    result_map('ar_val_diff_norm') = ar_val_diff_norm(1:it_iter_last);
 600 
    result_map('ar_pol_diff_norm') = ar_pol_diff_norm(1:it_iter_last);
 601 
    result_map('mt_pol_perc_change') = mt_pol_perc_change(1:it_iter_last, :);
 602 

 603 
    % Standard AZ graphs
 604 
    result_map = ff_az_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 605 

 606 
    % Graphs for results_map with FIBS contents
 607 
    result_map = ff_az_fibs_vf_post(param_map, support_map, armt_map, func_map, result_map, bl_input_override);
 608 
end
 609 

 610 
end

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