# General Equilibrium Solver

**URL:** https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643
**Category:** Uncategorized
**Created:** [April 27, 2026, 5:08pm UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643 "2026-04-27T17:08:11Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![aledinola](https://discourse.vfitoolkit.com/letter_avatar_proxy/v4/letter/a/3ec8ea/32.png) [@aledinola](https://discourse.vfitoolkit.com/u/aledinola)
#### Post date: [April 27, 2026, 5:08pm UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/1 "2026-04-27T17:08:11Z")

</div>

The toolkit evaluates intermediate equations and general equilibrium conditions in `HeteroAgentStationaryEqm_Case1_subfn`, around lines 54-73

```auto
intermediateEqnsVec(gg)=real(GeneralEqmConditions_Case1_v3g(heteroagentoptions.intermediateEqnsCell{gg}, heteroagentoptions.intermediateEqnParamNames(gg).Names, Parameters));

GeneralEqmConditionsVec(gg)=real(GeneralEqmConditions_Case1_v3(GeneralEqmEqnsCell{gg}, GeneralEqmEqnParamNames(gg).Names, Parameters));

```

I am concerned that the trick real() can hide some mistakes or inconsistencies. It happened to me in a model where I have these intermediate equations:

```auto
heteroagentoptions.intermediateEqns.N_corp=@(L,N_noncorp) L-N_noncorp;
heteroagentoptions.intermediateEqns.K_corp=@(A,K_noncorp) A-K_noncorp;
heteroagentoptions.intermediateEqns.Y_corp=@(K_corp,N_corp,alpha,Z) Z*(K_corp^alpha)*(N_corp^(1-alpha));

```

In equilibrium it cannot happen that N\_corp or K\_corp are negative, but during the GE iterations, these two variables might be negative. This is a problem because there is a fractional power in Y\_corp and the negative numbers would give complex results in matlab.  
The toolkit prevents this from happening by taking real(), but wouldn’t it be better to remove this trick? This would force the user to become aware of the problem, otherwise the code might go on without converging…

In my case I fixed the problem by putting a zero floor to K\_corp and N\_corp:

```auto
heteroagentoptions.intermediateEqns.N_corp=@(L,N_noncorp) max(L-N_noncorp,1e-12);
heteroagentoptions.intermediateEqns.K_corp=@(A,K_noncorp) max(A-K_noncorp,1e-12);

```

Even better to modify the GE conditions for capital and labor as follows:

```auto
GeneralEqmEqns.CapitalMarket = @(r,K_corp,N_corp,alpha,delta,Z) ...
    CorpCapitalMarketResidual(r,K_corp,N_corp,alpha,delta,Z);

```

and then

```auto
function resid = CorpCapitalMarketResidual(r,K_corp,N_corp,alpha,delta,Z)

if ~isfinite(K_corp) || ~isfinite(N_corp) || K_corp <= 0 || N_corp <= 0
    resid = 1e6;
    return
end

resid = r - (alpha*Z*(K_corp/N_corp)^(alpha-1) - delta);

end %end function

```

The idea is that if either K\_corp or N\_corp are “bad” (i.e. negative or NaN etc) we do NOT evaluate the condition `r - (alpha*Z*(K_corp/N_corp)^(alpha-1) - delta)` since it would be pointless and maybe would break the code, but we return a large penalty, so hopefully the GE solver changes the GE variables to avoid these bad values. This second approach has a small downside: it is more verbose, since you have to write the GE conditions as separate m-files. But of course the toolkit does not care whether you pass a GE condition as a one-liner or as a separate function like you would do for `ReturnFn`.

It would be nice to get some feedback on this problem from other users: what would you do in this case? Do you think the `real()` shim is a good idea?

---

<div class="post-metadata">

### Author: ![robertdkirkby](https://discourse.vfitoolkit.com/user_avatar/discourse.vfitoolkit.com/robertdkirkby/32/287_2.png) [@robertdkirkby](https://discourse.vfitoolkit.com/u/robertdkirkby)
#### Post date: [April 30, 2026, 1:41am UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/2 "2026-04-30T01:41:38Z")

</div>

You used to need them because, e.g., otherwise while searching for the general eqm wage the optimization would try out a negative wage and cause an error to be thrown ending your optimization.

Nowadays though, this should all be avoidable by using _heteroagentoptions.constrainpositive_ (and _.constrain0to1_, _.constrainAtoB_).

I have just deleted the use of real() from HeteroAgentStationaryEqm\_Case1\_subfn.m.

We will see over the next few months if this seems to work fine. If it is going okay I will remove real() from the other general eqm commands in August.

---

<div class="post-metadata">

### Author: ![aledinola](https://discourse.vfitoolkit.com/letter_avatar_proxy/v4/letter/a/3ec8ea/32.png) [@aledinola](https://discourse.vfitoolkit.com/u/aledinola)
#### Post date: [May 1, 2026, 8:38am UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/3 "2026-05-01T08:38:18Z")

</div>

Yes, but sometimes you have acceptable values for the GE prices and still not admissible values for intermediate equations. The new options restrict the domain of the GE prices only (as it should be).

In my example above I had positive values for `r` and `w` but `N_corp` turned out to be negative, which makes `(K_corp/N_corp)^alpha` undefined (since `K_corp/N_corp` becomes negative and `alpha` is not integer).

In our Bruggeman 2021 example:

```auto
GEPriceParamNames={'r','w','tau_s','G','ybar'} % r,w positive
heteroagentoptions.intermediateEqns.N_corp=@(L,N_noncorp) L-N_noncorp; % This might be negative
heteroagentoptions.intermediateEqns.K_corp=@(A,K_noncorp) A-K_noncorp; % This might be negative
heteroagentoptions.intermediateEqns.Y_corp=@(K_corp,N_corp,alpha,Z) Z*(K_corp^alpha)*(N_corp^(1-alpha));

```

Clearly, if N\_corp or K\_corp are negative, Y\_corp is undefined (complex number in Matlab)

```auto
N_corp =

   -0.4890

>> K_corp

K_corp =

    1.1665

>> Y_corp

Y_corp =

  -0.3316 + 0.5608i

```

For completeness, the small test that generated the example above:

```auto
clear,clc,close all

alpha = 0.33;
delta = 0.1;
Z = 1;
L=1;
A=3.5;
N_noncorp = 1.489;
K_noncorp = 2.3335;

f_N_corp=@(L,N_noncorp) L-N_noncorp; % This might be negative
f_K_corp=@(A,K_noncorp) A-K_noncorp; % This might be negative
f_Y_corp=@(K_corp,N_corp,alpha,Z) Z*(K_corp^alpha)*(N_corp^(1-alpha));

N_corp = f_N_corp(L,N_noncorp);
K_corp = f_K_corp(A,K_noncorp);
Y_corp = f_Y_corp(K_corp,N_corp,alpha,Z);

```

---

<div class="post-metadata">

### Author: ![robertdkirkby](https://discourse.vfitoolkit.com/user_avatar/discourse.vfitoolkit.com/robertdkirkby/32/287_2.png) [@robertdkirkby](https://discourse.vfitoolkit.com/u/robertdkirkby)
#### Post date: [May 1, 2026, 8:36pm UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/4 "2026-05-01T20:36:58Z")

</div>

What is your suggestion based on this? Drop real() from intermediateEqn but keep real() on GeneralEqmEqn valuation?

Or I guess I can just further modify the heteroagentoptions.verbose=2 so that you see the intermediateEqn values before the GeneralEqmEqn ones are computed (rather than just at the end of the iteration as current)

---

<div class="post-metadata">

### Author: ![aledinola](https://discourse.vfitoolkit.com/letter_avatar_proxy/v4/letter/a/3ec8ea/32.png) [@aledinola](https://discourse.vfitoolkit.com/u/aledinola)
#### Post date: [May 1, 2026, 11:33pm UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/5 "2026-05-01T23:33:01Z")

</div>

I don’t have any good suggestion, I’m afraid 🙂

I would leave the toolkit code as it is now, without real() anywhere. It’s up to the user to take action is something goes bad.

---

<div class="post-metadata">

### Author: ![robertdkirkby](https://discourse.vfitoolkit.com/user_avatar/discourse.vfitoolkit.com/robertdkirkby/32/287_2.png) [@robertdkirkby](https://discourse.vfitoolkit.com/u/robertdkirkby)
#### Post date: [August 8, 2026, 1:44am UTC](https://discourse.vfitoolkit.com/t/general-equilibrium-solver/643/6 "2026-08-08T01:44:20Z")

</div>

> [@robertdkirkby](#):
>
> I have just deleted the use of real() from HeteroAgentStationaryEqm\_Case1\_subfn.m.
> 
> We will see over the next few months if this seems to work fine. If it is going okay I will remove real() from the other general eqm commands in August.

Seems to be going fine. I have now removed real() from all the other stationary general eqm commands.

I will wait until October to see that everything is going fine with them. If yes, then I will go clean up the comments from the old behaviour, and then make the same changes to the calibrate/estimate commands. I need to implement parameter constraints for transition paths before I can make this change to transition paths.
