I’d like to propose an improvement for infinite horizon models that is quite effective for large grid sizes. In a current project with n_a=1200 and n_z=245 (not uncommon if you have more than one z variable) I realized that doing the Howard acceleration with a sparse matrix improves speed significantly. This applies to the case with howardsgreedy=0: as already discussed in another post, howardsgreedy is beneficial only for very small grid sizes.
Therefore I am proposing the following change. I propose to add vfoptions.howardssparse, which applies to the case howardsgreedy=0.
Step 0
At the beginning of ValueFnIter_Case1, introduce option howardssparse with default value equal to 0 (this is a trivial change, please see attached file).
Step 1
After creating ReturnMatrix, ValueFnIter_Case1 calls ValueFnIter_nod_raw at lines 479-483. The current block of code
if vfoptions.howardsgreedy==1
[VKron,Policy]=ValueFnIter_nod_HowardGreedy_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter); % a_grid, z_grid,
elseif vfoptions.howardsgreedy==0
[VKron,Policy]=ValueFnIter_nod_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter); % a_grid, z_grid,
end
should be replaced by
if vfoptions.howardsgreedy==1
[VKron,Policy]=ValueFnIter_nod_HowardGreedy_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter); % a_grid, z_grid,
elseif vfoptions.howardsgreedy==0
if vfoptions.howardssparse==0
[VKron,Policy]=ValueFnIter_nod_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter);
elseif vfoptions.howardssparse==1
[VKron,Policy]=ValueFnIter_nod_raw_sparse(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter);
end
end
Step 2
In ValueFnIter_Refine please change this block of code
if vfoptions.howardsgreedy==1
[VKron,Policy_a]=ValueFnIter_nod_HowardGreedy_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.maxhowards, vfoptions.tolerance,vfoptions.maxiter);
elseif vfoptions.howardsgreedy==0
[VKron,Policy_a]=ValueFnIter_nod_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance,vfoptions.maxiter);
end
with this one:
if vfoptions.howardsgreedy==1
[VKron,Policy_a]=ValueFnIter_nod_HowardGreedy_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.maxhowards, vfoptions.tolerance,vfoptions.maxiter);
elseif vfoptions.howardsgreedy==0
%[VKron,Policy_a]=ValueFnIter_nod_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance,vfoptions.maxiter);
if vfoptions.howardssparse==0
[VKron,Policy_a]=ValueFnIter_nod_raw(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter);
elseif vfoptions.howardssparse==1
[VKron,Policy_a]=ValueFnIter_nod_raw_sparse(V0, N_a, N_z, pi_z, DiscountFactorParamsVec, ReturnMatrix, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter);
end
end
Step 3 (Low memory)
In ValueFnIter_Case1 around lines 510-516 please change this block of code:
[VKron,Policy]=ValueFnIter_LowMem_nod_raw(V0, n_a, n_z, a_grid, z_gridvals, pi_z, DiscountFactorParamsVec, ReturnFn, ReturnFnParamsVec, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance);
with this:
if vfoptions.howardssparse==0
[VKron,Policy]=ValueFnIter_LowMem_nod_raw(V0, n_a, n_z, a_grid, z_gridvals, pi_z, DiscountFactorParamsVec, ReturnFn, ReturnFnParamsVec, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance);
elseif vfoptions.howardssparse==1
[VKron,Policy]=ValueFnIter_LowMem_nod_raw_sparse(V0, n_a, n_z, a_grid, z_gridvals, pi_z, DiscountFactorParamsVec, ReturnFn, ReturnFnParamsVec, vfoptions.howards, vfoptions.maxhowards, vfoptions.tolerance, vfoptions.maxiter);
end
I uploaded in the github repo AiyagariSparse the files that I changed in the toolkit:
ValueFnIter_Case1with the new option howardssparseValueFnIter_Refinefor models with d variableValueFnIter_nod_raw_sparsewhich is the new file, called byValueFnIter_Case1around lines 480-490 and called byValueFnIter_Refinearound lines 40-45.ValueFnIter_LowMem_nod_raw_sparsewhich is the new file for the low memory case. It is called byValueFnIter_Case1around lines 510-516.
I’m quite satisfied about this change, so I hope it can be officially included in the toolkit as an option, without changing the default settings ![]()
On my laptop, I see the benefit of howardssparse when n_a=1000 and n_z=51, on the desktop (where I have a better GPU), I see the benefits for n_a=1200 and n_z=101.