Bug in SimPanelValues_TransPath_InfHorz

While testing GuerrieriLorenzoni2017_Example.m, MATLAB fails at the first call to SimPanelValues_TransPath_InfHorz.

Error:

Unrecognized function or variable 'transpathoptions'.

Error in SimPanelValues_TransPath_InfHorz (line 165)
... = inputsFindtplus1tminus1(..., transpathoptions);

The function signature ends with simoptions:

function SimPanelValues = SimPanelValues_TransPath_InfHorz( ...
    PolicyPath, PricePath, ParamPath, T, AgentDist_initial, ...
    n_d, n_a, n_z, pi_z, d_grid, a_grid, z_grid, ...
    FnsToEvaluate, Parameters, simoptions)

However, transpathoptions is neither an input nor defined locally before it is used on line 165. Consequently, the function appears to fail for every ordinary call, even when none of the functions to evaluate uses _tminus1 or _tplus1 variables.

I encountered this using the standard Figure 6 call in GuerrieriLorenzoni2017_Example.m under MATLAB R2026a. A likely backwards-compatible fix would be to accept transpathoptions as an optional final argument and initialize it to an empty/default structure when omitted.

1 Like

This mistake happened also to me when I ran this example. It can be easily fixed by just commenting out the code for the figure.

After fixing that, the transition is very slow and does not converge. Is this an outdated example or is there a problem with the transition code in the toolkit? More in general, I’m using the toolkit to compute transitions in infinite horizon models and it’s a great help for me. But I noticed that somehow the transitions are always very very slow, even when they converge.

1 Like

I agree. This is partly because the updates in examples are very ‘dampened’. If you change the factor used in the updates they are much faster, but also potentially less stable.

I am working towards some much bigger improvements in transition paths, especially around using some improved alternatives to the shooting algorithm, but that won’t be seen until later this year as there is still a fair bit of work and testing left to be done.

Toolkit tends to be okay on OLG (FHorz) transitions, because transpathoptions.fastOLG=1 is powerful (as long as you don’t run out of memory), but for InfHorz transition it is definitely slow and has room for improvement.

1 Like

I was wondering if this issue is solved, thanks.

The command has been fixed, but I haven’t had a change to check GL2017 so I didn’t want to say yes just yet.

1 Like

I will test it then and report back :slight_smile:

The error in SimPanelValues_TransPath_InfHorz is fixed, but the transition does not converge, confirming what @javier_fernan had reported above.

This is strange: I had run this example years ago and the transition was ok

2 Likes

Thanks! Any idea why the transition does not converge? Is there another algorithm we can use? I have been stuck on computing transitions for these type of models for some time now and I would appreciate suggestions

1 Like

A related technical point is that we are not sure if the transitional path exists!

Existence of steady state has been proven in the context of Bewley models with production: see here:
https://www.sciencedirect.com/science/article/abs/pii/S0022053117301084). Regarding the Huggett economy (no production but endowment), Akira Toda has a nice paper where he proves existence of equilibrium for CARA utility: https://www.sciencedirect.com/science/article/pii/S0165188917301823. This is restrictive (typically one would use CRRA utility) but there are probably other more general results around.

Note however that for the Guerrieri and Lorenzoni economy with their parametrization there shouldn’t be any issues. It’s a published paper and was replicated by @robertdkirkby in this nice article: Quantitative Macroeconomics: Lessons Learned from Fourteen Replications | Computational Economics | Springer Nature Link.

1 Like

Was the VFI toolkit used in the replication of Guerrieri Lorenzoni? Because now the example on the toolkit website does not converge

1 Like

If you turn off grid interpolation layer the GL2017 example works.

There is something wrong with grid interpolation layer in InfHorz (more precisely the default settings are not conservative enough). I am working on fixing it now, hopefully can get it clean and pushed later this week.

Really sorry about that @javier_fernan. To try and make it up for you I am going to spend a chunk of August trying to implement new and better InfHorz Transition Path commands as I know that is the part of the toolkit you are using (I’m busy teaching atm but I have two weeks break after next week’s teaching, I will focus on some new InfHorz TPath commands to make them faster and easier).

3 Likes

Thanks a lot, Robert. No need to apologise at all, and I really appreciate you identifying the issue and working on a fix.

Those improvements to infinite horizon transition with grid interp layer will be extremely useful for me and hopefully for others. Thanks again for all the work you put into maintaining and developing the toolkit!

2 Likes

@javier_fernan, good news. GL2017 example now works with and without grid interp layer.

The transition is fine, but currently using GI in InfHorz value fn (so the stationary eqm problem) is kind of slow. You can make it faster with setting a smaller vfoptions.maxaprimediff (default is =n_a(1)/5, you can keep setting it smaller until you get a different answer, where this is depends a lot on the problem as it is about getting stuck in local optima), but I feel like I might be able to find a better way to set the default value. Going to be trying to do that on and off over the rest of the month.

I’ll also be trying some new approaches to how the transition path is being done that will hopefully speed that up.

You can of course always just turn grid interp layer off and put more grid points and get accuracy that way.

[This local optima issue only affects grid interpolation layer in InfHorz, is not relevant to FHorz]

PS. The issue was around using a coarse grid somewhere in the InfHorz transition path when it should have been using a fine grid. I’ve added more things to the toolkit test banks to ensure this issue cannot recur.

3 Likes

Actually the function SimPanelValues_TransPath_InfHorz still has a bug.

For gridinterplayer=1 SimPanelValues_TransPath_InfHorz calculates:

l_daprime = size(PolicyPath,1) - 1;

But interpolation adds two policy-index rows. It should be consistent with comparable toolkit routines:

l_daprime = size(PolicyPath,1) ...
    - 2*simoptions.gridinterplayer;

The incorrect count makes EvalFnOnSimPanelIndex request a nonexistent third column from daprime_val, producing:

Index exceeds matrix dimension.
1 Like

Thanks @robertdkirkby and @aledinola. Besides the error reported above, the transition for Guerrieri-Lorenzoni takes more than 30 min on my computer. Do you have similar timings? I have to optimize over two tax rates and using 10 grid points for each it means I have to run at least 100 transitions. Each transition taking more than 30 min makes the problem not really manageble sadly.

1 Like

Fixed.

I’ve added a lot to the test banks for InfHorz TPath to ensure they are all accurate. Next is trying to make these InfHorz TPath faster.

2 Likes

Nice! Following your message on github, I ran again my tests of the heterogeneous agents examples.

In Guerrieri and Lorenzoni example: The error with SimPanel is now solved and the code around Figure 6 runs without errors. There is however no convergence for the sticky price transition with interpolation. More in detail, the tests results are:

gridinterplayer=0: both transitions converge.
Flexible transition: 310 iterations.
Sticky transition: 30 iterations.
Full run: about 37.9 minutes.
gridinterplayer=1 with ngridinterp=15:
Flexible transition converges in 309 iterations.
Figure 6 now works after Robert’s toolkit fix.
Sticky transition does not converge. Its convergence ratio rises from 1.90 at iteration 43 to 66.73 at iteration 121, so we stopped the run after about 51.6 minutes.

See TEST_REPORT.md available on my github repo of the VFI-Examples: VFItoolkit-matlab-examples/HeterogeneousAgentModels/TEST_REPORT.md at master · aledinola/VFItoolkit-matlab-examples · GitHub

Heterogeneous-agent model test report

Tested on 13 and 19 August 2026 with MATLAB R2026a Update 4 and one NVIDIA GeForce RTX 5080 Laptop GPU. The original examples test used repository commit fbecce303f6a95b7a03aa3ace918cd2c29031877 and VFI Toolkit commit eb44124b0d68a5d6f2155480fdf4377aec1fa64b. The Guerrieri–Lorenzoni grid-interpolation rerun used examples commit 38341f855639690143087714d2dc584fcbb789d1 and VFI Toolkit commit b0ddb078def8be0b9b6cdd69db9033bc38f5df49.

Each run used a fresh MATLAB process and addpath(genpath('../VFIToolkit-matlab')). Tests ran from temporary directories so GL2017A.mat and GL2017B.mat were not written to the repository. Both modes used vfoptions.ngridinterp=15, with matching simoptions fields. No model grids, parameters, tolerances, or other options were changed.

Results

Script gridinterplayer Runtime Convergence evidence Result
Aiyagari1994.m 0 15.4 s Stationary GE returned finite results; capital-market residual -8.52e-5 Pass
Aiyagari1994.m 1 26.4 s Stationary GE returned finite results; capital-market residual -1.32e-4 Pass
Aiyagari1994TransitionPath.m 0 89.7 s Transition converged in 29 iterations; final convergence ratio 0.87 Pass
Aiyagari1994TransitionPath.m 1 195.9 s Transition converged; final convergence ratio 0.88 Pass
GuerrieriLorenzoni2017_Example.m 0 2,274.3 s Flexible and sticky transitions converged in 310 and 30 iterations; both final ratios were 1.00 Pass, but runtime needs improvement
GuerrieriLorenzoni2017_Example.m 1 3,093 s before stop Flexible transition converged in 309 iterations; Figure 6 completed; sticky transition diverged to a final ratio of 66.73 at iteration 121 Partial pass: interpolation error fixed, but sticky transition did not converge

The mode-0 Guerrieri–Lorenzoni full run took 37.9 minutes. The test did not isolate the two transition runtimes, but the flexible transition’s 310 iterations make it the likely dominant cost. In the mode-1 rerun, the checkpoint after the flexible transition, its value and policy functions, and its distribution was written after about 31.2 minutes. Both observations exceed the requested ten-minute threshold and should be improved.

Grid-interpolation rerun

The original mode-1 run failed at the first Figure 6 call to SimPanelValues_TransPath_InfHorz:

Index exceeds matrix dimension.
Error in EvalFnOnSimPanelIndex (line 174)
Error in SimPanelValues_TransPath_InfHorz (line 332)

The failure was caused by the toolkit routine SimPanelValues_TransPath_InfHorz. An interpolated policy contains two additional index rows, but that routine computed the number of actual decision/next-state values by subtracting only one row. It therefore told EvalFnOnSimPanelIndex to read a nonexistent third column from daprime_val.

VFI Toolkit commit b0ddb078def8be0b9b6cdd69db9033bc38f5df49 applies the appropriate calculation:

l_daprime = size(PolicyPath,1) - 2*simoptions.gridinterplayer;

The rerun confirmed that this correction fixes the original failure. The flexible transition converged in 309 iterations with a final convergence ratio of 1.00, and all four Figure 6 simulation calls completed. The script then reached the previously unverified sticky-wage transition.

The sticky transition did not converge under the unchanged example settings. Its convergence ratio was 1.90 at iteration 43, then increased to 5.65 at iteration 67, 16.66 at iteration 89, and 66.73 at iteration 121. The run was stopped after about 51.6 minutes rather than continue toward the default 1,000-iteration cap while the distance was increasing. No example source files were changed; only the report was updated.

@aledinola could you please rerun your test? Just pushed a whole bunch of new InfHorz test banks (including TPath), and lots of small toolkit improvements to go along with it. Part of this was better default vfoptions for Howards, so hopefully the runtimes are slightly improved too (not for TPath, just for InfHorz things like stationary eqm).

1 Like

Runtimes for Aiyagari have considerably improved (not only steady-state but also transition with gridinterplayer=1).
Runtimes for Guerrieri-Lorenzoni have improved only marginally.
Transition with gridinterplayer=1 in Guerrieri-Lorenzoni still does NOT converge.

Caveat: My test ran the scripts only once, so the runtimes results must be taken with a grain of salt.

Full updated report: