Potential Issues in `ValueFnIter/FHorz/SemiExo`

Potential Issues in ValueFnIter/FHorz/SemiExo

I have been going through the MATLAB implementation of finite-horizon VFI with semi-exogenous shocks in:

ValueFnIter/FHorz/SemiExo

and wanted to report a few issues (maybe not really bugs).


1. Inconsistent use of n_semiz vs vfoptions.n_semiz (confirmed issue)

Where

ValueFnIter_FHorz_SemiExo.m

Problem

The wrapper function takes n_semiz as an input argument, and:

  • uses n_semiz in branches without e
  • uses vfoptions.n_semiz in branches with N_e > 0

Example:

ValueFnIter_FHorz_SemiExo_noz_e_raw(..., vfoptions.n_semiz, ...)
ValueFnIter_FHorz_SemiExo_e_raw(..., vfoptions.n_semiz, ...)

Later, reshaping logic also relies on vfoptions.n_semiz.

Why this is problematic

  • vfoptions.n_semiz is not implied by the function signature
  • if it is missing, this can produce a runtime error
  • if it differs from n_semiz, this can create silent dimension inconsistencies

Suggested fix

Use n_semiz consistently:

ValueFnIter_FHorz_SemiExo_noz_e_raw(..., n_semiz, ...)
ValueFnIter_FHorz_SemiExo_e_raw(..., n_semiz, ...)

and ensure all reshaping uses the same variable.


2. Terminal-period shape inconsistency in e_raw (likely issue)

Where

ValueFnIter_FHorz_SemiExo_e_raw.m
Branch: V_Jplus1 and vfoptions.lowmemory == 0

Problem

After selecting optimal indices, the code constructs:

d1aprime_ind = reshape(..., [N_a, N_semiz*N_z*N_e]);

and then assigns:

Policy3(1,:,:,:,N_j) = rem(d1aprime_ind-1,N_d1)+1;
Policy3(3,:,:,:,N_j) = ceil(d1aprime_ind/N_d1);

So in this block the object is treated as a 2D array:

[N_a, N_semiz*N_z*N_e]

Why this looks suspicious

Nearby analogous code paths handle the same object differently:

  • in the lowmemory == 1 terminal branch, the code uses shiftdim(...) to restore dimensional structure before assignment
  • in the backward-iteration part of the same file (jj < N_j, lowmemory == 0), the code explicitly reshapes to
[N_a, N_semiz*N_z, N_e]

That is the shape one would naturally expect for slices such as:

Policy3(1,:,:,:,N_j)
Policy3(3,:,:,:,N_j)

Why this matters

This branch flattens the (semiz,z,e) structure into one dimension, while nearby branches restore the multidimensional structure explicitly.

So the concern is not necessarily that MATLAB must always error here, but rather:

  1. this block is internally inconsistent with neighboring branches
  2. it may rely on MATLAB accepting an assignment whose shape is not made explicit
  3. if accepted, it may still be fragile and hard to maintain

Suggested fix

Make the shape explicit and consistent with the rest of the file:

d1aprime_ind = reshape(..., [N_a, N_semiz*N_z, N_e]);

Policy3(1,:,:,:,N_j) = rem(d1aprime_ind-1,N_d1)+1;
Policy3(3,:,:,:,N_j) = ceil(d1aprime_ind/N_d1);

Why I call this “likely” rather than “confirmed”

I have not run the code, and MATLAB sometimes accepts assignments as long as the total number of elements matches. So I cannot say for certain that this block always fails at runtime.

But it is definitely dimensionally inconsistent with the surrounding code, and for that reason it looks like a likely bug.


3. lowmemory == 2 is partially implemented but disabled (stale code)

Where

  • ValueFnIter_FHorz_SemiExo_e_raw.m
  • ValueFnIter_FHorz_SemiExo_noz_e_raw.m

Problem

At the top of the file there is an explicit error such as:

error('vfoptions.lowmemory=2 not supported with semi-exogenous states');

But later in the same file:

  • arrays are still preallocated for lowmemory == 2
  • several elseif vfoptions.lowmemory==2 branches still appear

Interpretation

  • this is not really a live runtime bug, because execution stops earlier
  • but it is dead or unreachable code
  • it suggests incomplete refactoring or partially removed support

Suggested fix

Either:

  • remove the lowmemory == 2 branches entirely, or
  • re-enable support and remove the early error(...)

Summary

  • Confirmed issue: inconsistent use of vfoptions.n_semiz vs n_semiz
  • Likely issue: terminal-period shape inconsistency in ValueFnIter_FHorz_SemiExo_e_raw.m
  • Maintenance issue: stale lowmemory == 2 code

Final note

The second issue may not always generate a MATLAB error, but it is inconsistent with the rest of the implementation and may create subtle bugs or dimension problems.

These are all non-issues. If you want to clean some up as a pull request feel free but otherwise I plan to ignore them all.

1 Like