Equilibria with different orders of magnitude

I’ve managed to get OLGModel14 to run, but it doesn’t converge very nicely. Looking at it from inside the debugger, what I’m seeing is that the household values are well-behaved in the range of +/- 1.0 mostly, as expected. However, the firm values are a million times smaller. I have traced this down to the fact that while the Stationary Distributions for both sum to 1.0 as expected, the (finite horizon) stationary distribution for households is rich enough (across its many dimensions) to yield meaning values when multiplying by the returned function values.

The shape of the (infinite horizon) firm stationary distribution (which does not have age parameters nor the exogenous shock vectors) is a two dimensional matrix whose top row has “nice” values, then a few rows of zeros, and then the remaining rows full of non-zero values that print as zero (ranging between 10^-6 and 10^-9). The firm return value matrix is zeros across the top row, and then seemingly normal values elsewhere. Alas, when we do the element-wise multiplication for example here:

    for ff=1:length(FnsToEvaluate)
        FnToEvaluateParamsCell=CreateCellFromParams(Parameters,FnsToEvaluateParamNames(ff).Names);        
        Values=EvalFnOnAgentDist_Grid(FnsToEvaluate{ff}, FnToEvaluateParamsCell,PolicyValuesPermute,l_daprime,n_a,n_z,a_gridvals,z_gridvals);
        Values=reshape(Values,[N_a*N_z,1]);
        % When evaluating value function (which may sometimes give -Inf values) on StationaryDistVec (which at those points will be 0) we get 'NaN'. Use temp as intermediate variable just eliminate those.
        temp=Values.*StationaryDistVec;
        AggVars(ff)=sum(temp(~isnan(temp)));
    end

this results in zeroing out the top row and leaving the rest of the matrix scaled down by the very small values remaining in the infinite horizon Stationary Distribution matrix.

I believe that if the these two set of values were within the same order of magnitude, the iteration process would converge. As it is, it seems to be randomly iterating values for dividend payments and shares issued that never quite meet the mark, while all the other GE parameters and outputs remain fixed across iterations.

Now, perhaps there are other errors in the code that I’ve introduced trying to get OLGModel14 to work. But if the above sheds any light on the problem, I’m happy for any guidance.

You’ve come across exactly what I had found the to the issue, and which I had not yet solved. Namely, you need to get the household side and the firm side to add up. Intuitively you should be able to do this by scaling up the firm side, my guess what to use the production technology level (or more accurately a scalar multiplying this) to scale up the firms so that they match the household (and just leave the households alone).

My guess, which I have not yet got to trying out, was to make it so that the total returns to capital for firms matched that for households, and also the total returns to labor for firms matching that for households.

You might also look at Anagnostopoulos, Atesagaoglu, & Cárceles-Poveda (2022). I’ve just emailed you an incomplete replication of their paper. They don’t seem to explicitly match the household and firm. My belief is that this is because they got lucky on the calibration so that households and firms just happen to be the same size. My feeling was that you should do what I described above, matching returns to labor and capital for firms and households. I have not found the time to get back to it and finish the replication up.

You are right on what is missing from the OLG Model 14, namely a way to make sure firm side and household side add up to the same. Question is just what exactly it is that you need to check is adding up, and what parameter to be determined in general eqm is used to make them the same.

Looks like the stationary dist matrix for the InfHoriz case is not well-conditioned (the 1st row dominates all the other rows) and perhaps that’s the real problem. The Tan improvement proudly declares that it can start with a very bad guess. Maybe there’s a way to seed the matrix so that it is not only solves to a stationary dist, but in a well-conditioned way.

Economic models (of this kind) form a (1st order) Markov Chain on the <endogenous state -cross- exogenous state> space (combine Policy with pi_z and you get the transition matrix of this markov). This Markov satisfies certain mixing properties that guarantee that not only will a stationary distribution exist and be unique, but further that starting from any initial distribution and iterating on it will (eventually) converge to the stationary distribution.

So it is not about a poor initial guess for the agent distribution. Plausibly, the model is not being setup correctly, and hence the solution does not presently satisfy the mixing conditions.

[The Tan improvement is not directly relevant, it is a computational implementation of iteration. Conceptually it is solving the exact same thing as iteration, just that the Tan improvement divides it into two steps instead of one step, and in doing so massively reduces the computational runtime by reducing the number of operations. It does this by taking advantage of the structure of the markov on (a,z) being that the transitions of z are independent of a (this is why you cannot use Tan improvement on semi-exogenous states, as then the transitions of z are no longer independent of a).]

PS. Roughly speaking, the mixing says that you have to be able to get from any point in the state space to any other point (for any two points that end up with non-zero mass in the stationary distribution). This is ruling out things like pi_z=[1,0;0,1], notice how here you can get ‘stuck’ in the first or second states so there is no mixing, and so how much mass you put on each in the initial distribution will influence the stationary distribution. The mixing can take a long time, maybe it takes 20 iterations for the probability of getting from one state to another to be non-zero, the pace of mixing is not important, just that there is mixing.

1 Like

This line of code in ValueFnIter_nod_HowardGreedy_raw

        VKron=(spI-DiscountFactorParamsVec*T_E)\Ftemp;

creates a matrix full of NaNs when there’s a single -Inf term in Ftemp. The downstream consequence of this is that all our beautiful Policy matrices iterate themselves into a matrix full of ones.

When I changed this “large negative number” to a finite large negative number (-1/Tolerance) things started to behave (with Policy matrices returned that had at least some interesting contours).

The iterative search for GE continues to spend a lot of time randomly swapping values for dividends paid and shares issued, but there is perceptible motion in other parameters from time to time. I’ll let you know how the search converges…

1 Like

I think the Howard greedy algorithm is not very efficient. Usually if you set howardsgreedy=0 the vfi is faster

Sounds like the implementation of ValueFnIter_nod_HowardGreedy_raw is erroneous in terms of how it handles -Inf. Howards greedy is relatively new to the toolkit so it is plausible that it fails in some edge cases, like this one, and I just didn’t notice while running some tests as those tests did not include these edge cases.

As Alessandro suggests, run twice with howardsgreedy=0 and 1, and check if they give same answer. If answers differ it is an issue with howards greedy in this edge case.

1 Like

Here’s the “results” of the first run (Howards greedy==1):

Current GE prices:
r: 0.0500
pension: 0.4019
AccidentBeq: 0.0300
G: 0.1000
w: 1.0145
firmbeta: 0.9422
D: 0.2053
P0: 1.0006
Lhscale: 0.3006
Current aggregate variables:
L_h: 0.2087
S: 0.9925
PensionSpending: 0.0617
PayrollTaxRevenue: 0.0423
AccidentalBeqLeft: 0.0090
CapitalGainsTaxRevenue: -0.0267
Output: 0.2681
L_f: 0.1718
K: 0.3346
DividendPaid: 0.3017
Sissued: 0.2521
CorpTaxRevenue: 0.0257
Current GeneralEqmEqns:
sharemarket: -0.007479
labormarket: 0.036935
pensions: 0.019323
bequests: -0.021175
govbudget: 0.059969
firmdiscounting: 0.000998
dividends: -0.096429
ShareIssuance: 0.117796
CapitalOutputRatio: -0.082010

Warning: The permanent type mass weights must sum to one (PTypeDistParamNames points to weights that do not sum to one)

LifeCycleProfiles_FHorz_Case1_PType: Ignoring the 2-th PType, firm because it is infinite horizon

Following are some aggregates of the model economy:
Output: Y= 0.27
Aggregate TFP: Y= 1.18
Capital-Output ratio (firm side): K/Y= 1.25
Total asset value (HH side): P*S= 1.13
Total firm value (firm side): Value of firm= -Inf
Consumption-Output ratio: C/Y= 1.08
Government-to-Output ratio: G/Y= 0.37
Wage: w= 1.01

Value of firm= -Inf is the most suspicious number. Looking at where that comes from, we see in OLGModel14:

% Total value of firms
temp=V.firm.*StationaryDist.firm;
temp(StationaryDist.firm==0)=0; % Get rid of points that have V=-inf but zero mass which would give nan
TotalValueOfFirms=sum(sum(temp));

Alas, there are -Inf terms from V that convey through the element-wise multiplication (not turned to NaNs). Here they are:

find(isinf(temp))

ans =

           1
         502
        1003
        1504
        2005
        2506
        3007
        3508
        4009
        4510
        5011

If we knock them out, we get a finite value of the firm:

sum(sum(temp(isfinite(temp))))

ans =

    0.8575
1 Like

As an aside, I’ve seen a number of comments in the code wondering why MATLAB sometimes returns complex results. The “fix” is to simply take the real() of the result.

I’ll bet the explanation is due to taking a root of -Inf :

(-Inf)^0.2

ans =

      Inf +    Infi

I don’t know whether its worth seeking out the conditions under which -Inf is sneaking into our maths, but this is what I’d be looking for as a source for complex numbers.

With the fix I proposed (setting -Inf to a large, but not infinite, negative number), the two versions of Howards agree.

1 Like

FYI, using GridInterp (ngridinterp=20, level1n=11) created this GE solution (which took about 10x longer than divide and conquer):

Exiting: Maximum number of function evaluations has been exceeded
         - increase MaxFunEvals option.
         Current function value: 0.134662 

 
Current GE prices: 
	r:   0.0488 
	pension:   0.3880 
	AccidentBeq:   0.0304 
	G:   0.0992 
	w:   1.0485 
	firmbeta:   0.9855 
	D:   0.2040 
	P0:   0.9878 
	Lhscale:   0.3040 
Current aggregate variables: 
	L_h:   0.2107 
	S:   1.0696 
	PensionSpending:   0.0595 
	PayrollTaxRevenue:   0.0442 
	AccidentalBeqLeft:   0.0102 
	CapitalGainsTaxRevenue:  -0.0290 
	Output:   0.1959 
	L_f:   0.1214 
	K:   0.2355 
	DividendPaid:   0.4179 
	Sissued:   0.3816 
	CorpTaxRevenue:   0.0189 
Current GeneralEqmEqns: 
	sharemarket: 0.069554 
	labormarket: 0.089235 
	pensions: 0.015355 
	bequests: -0.020415 
	govbudget: 0.068462 
	firmdiscounting: 0.044358 
	dividends: -0.213926 
	ShareIssuance: 0.246187 
	CapitalOutputRatio: -0.090450 
Warning: The permanent type mass weights must sum to one (PTypeDistParamNames points to weights that do not sum to one) 
> In StationaryDist_Case1_FHorz_PType (line 56)
In OLGModel14 (line 296) 
LifeCycleProfiles_FHorz_Case1_PType: Ignoring the 2-th PType, firm because it is infinite horizon 
Following are some aggregates of the model economy: 
Output: Y=    0.20 
Aggregate TFP: Y=    1.21 
Capital-Output ratio (firm side): K/Y=    1.20 
Total asset value (HH side): P*S=    1.20 
Total firm value (firm side): Value of firm= 4565.00 
Consumption-Output ratio: C/Y=    1.51 
Government-to-Output ratio: G/Y=    0.51 
Wage: w=    1.05 
Elapsed time is 23962.696858 seconds.
>> 
1 Like

Just to comment about the run times (not the economic model): grid interp layer being 10 times slower than pure discretization is a bit worrisome.

The comparison is against divide and conquer.

Overnight I ran a test with a smaller a_grid for households. Shrinking the grid from 501 to 301, the runtime dropped by more than half (10274s vs 23963s) and the results were identical to 6 digits except for shareholding (1.0692 vs 1.0696) and thus also a small difference in sharemarket and labormarket and bequests (both in the last digit).

Before those runs I also tried shrinking the size of the grid a_grid for the firm side, but those got lost iterating in ValueFnIter_Refine_postGI_raw (enormous currdist values and hundreds of thousands of iterations that would likely never reach the infinite maxiter).

1 Like

Because this model has both FHorz agents and InfHorz agents what you really want is different vfoptions for each, the reason being that divide-and-conquer is great for FHorz, but a liability for InfHorz.

You can do this with

vfoptions.divideandconquer.agentfhorz=1;
vfoptions.divideandconquer.agentinfhorz=0;
vfoptions.gridinterplayer=1;
vfoptions.ngridinterp=20;

notice that divide-and-conquer is by ptype, while gridinterplayer is for all ptypes.

[agentfhorz and agentinfhorz are the names you gave them in Names_i, obviously use whatever names you actually set.]

1 Like

Thanks for that explanation. Unfortunately it returns me to a previously unsolved problem: DC+GI is conflicted about return matrix shaping in ValueFnIter_FHorz_DC1_GI_e_raw (and whether we should call CreateReturnFnMatrix_Case1_Disc_DC1_Par2e with Level=3 or Level=6, or something else).

1 Like

Using divide and conquer only for FHorz, and expanding the a_grid for firms to 801 while keeping a_grid at 301 for households yields this more balanced GE:

Current GE prices: 
	r:   0.0500 
	pension:   0.4003 
	AccidentBeq:   0.0300 
	G:   0.1001 
	w:   1.0008 
	firmbeta:   0.9822 
	D:   0.2001 
	P0:   1.0007 
	Lhscale:   0.3002 
Current aggregate variables: 
	L_h:   0.2091 
	S:   0.9748 
	PensionSpending:   0.0614 
	PayrollTaxRevenue:   0.0419 
	AccidentalBeqLeft:   0.0088 
	CapitalGainsTaxRevenue:  -0.0252 
	Output:   0.2791 
	L_f:   0.1813 
	K:   0.3584 
	DividendPaid:   0.2077 
	Sissued:   0.1561 
	CorpTaxRevenue:   0.0266 
Current GeneralEqmEqns: 
	sharemarket: -0.025199 
	labormarket: 0.027858 
	pensions: 0.019560 
	bequests: -0.021386 
	govbudget: 0.058649 
	firmdiscounting: 0.041048 
	dividends: -0.007601 
	ShareIssuance: 0.026597 
	CapitalOutputRatio: -0.052991 
Warning: The permanent type mass weights must sum to one (PTypeDistParamNames points to weights that do not sum to one) 
> In StationaryDist_Case1_FHorz_PType (line 56)
In OLGModel14 (line 297) 
LifeCycleProfiles_FHorz_Case1_PType: Ignoring the 2-th PType, firm because it is infinite horizon 
Following are some aggregates of the model economy: 
Output: Y=    0.28 
Aggregate TFP: Y=    1.17 
Capital-Output ratio (firm side): K/Y=    1.28 
Total asset value (HH side): P*S=    1.10 
Total firm value (firm side): Value of firm= 8800.00 
Consumption-Output ratio: C/Y=    1.03 
Government-to-Output ratio: G/Y=    0.36 
Wage: w=    1.00 
Elapsed time is 1654.626165 seconds.

Should be fixed (just pushed to github). Turns out that because my test bank does not include a warm-glow there was a small part of this that wasn’t being tested. I will think about adding warm-glow to the test bank, and then running it twice with and without, just to make sure there is no other instance of this issue (I ran a model with z but no e and it didn’t have this issue, so certainly isn’t widespread, but this may not be the only instance).

1 Like

My takeaway:

  • Howards greedy only works for models where V does not take the value -Inf at any point in the state space (is okay for return fn to take -Inf, as long as can avoid choosing these and so V remains finite).
  • Howards iteration can handle that V takes the value -Inf at some parts of the state space.

The design philosophy of VFI Toolkit is to just work; deliver the correct answer to whatever model setup the user has given. Anything that can ‘fail’ —fail meaning to deliver the incorrect answer to what the user has setup— remains in vfoptions as something the user can do, but hopefully will only do if they ‘know’ it is okay for that model setup (e.g., divide-and-conquer can only be used for model where the policy function of next period asset is conditionally monotone, which is true for almost all models, but you can write a model where it is not true so cannot be default behaviour).

So I am going to just change the defaults so that Howards-greedy is never used by default. It will remain something that can be activated via vfoptions. I feel like this is a minor loss given that the sole point of Howards-greedy is anyway to give a speed-up to small models.

[I don’t like to code the ‘use large but finite negative number in place of -Inf’ as I expect there are some model setups in which this would fail to deliver the correct answer. Specifically, if the model actually returns an ‘even larger but finite negative number’ somewhere then this would result in an error when the ‘replacement of -Inf’ is chosen instead.]

Howards-greedy is fairly new to the toolkit, was implemented late last year, and clearly all the tests run at the time were value fns that do not contain -Inf, so had not noticed this behaviour before. Makes sense when you look at Howards greedy which is about solving,

V_{m,\infty}=(\mathbb{I} - \beta T_E)^{-1} F_{a*'}

and so if F_{a*'} contains a -Inf this operation goes wrong. I expect there is a way to modify Howards greedy to correctly handle this, but I am not currently inclined to try. Partly as such a modification may mean killing much of the speed advantage of Howards greedy over Howards iteration in small models, which means killing the whole point of using Howards greedy in the first place.

1 Like