Skip to content

Commit

Permalink
Add a couple missing constructors
Browse files Browse the repository at this point in the history
If there's anything else that can be converted to a constructor, I don't know about it.
  • Loading branch information
mnwhite committed Feb 17, 2025
1 parent 0f12398 commit df5a130
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 21 deletions.
57 changes: 48 additions & 9 deletions HARK/ConsumptionSaving/ConsAggShockModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,38 @@ def make_aggmrkv_solution_terminal(CRRA, MrkvArray):
return solution_terminal


def make_exponential_MgridBase(MaggCount, MaggPerturb, MaggExpFac):
"""
Constructor function for MgridBase, the grid of aggregate market resources
relative to the steady state. This grid is always centered around 1.0.
Parameters
----------
MaggCount : int
Number of gridpoints for aggregate market resources. Should be odd.
MaggPerturb : float
Small perturbation around the steady state; the grid will always include
1+perturb and 1-perturb.
MaggExpFac : float
Log growth factor for gridpoints beyond the two adjacent to the steady state.
Returns
-------
MgridBase : np.array
Grid of aggregate market resources relative to the steady state.
"""
N = int((MaggCount - 1) / 2)
gridpoints = [1.0 - MaggPerturb, 1.0, 1.0 + MaggPerturb]
fac = np.exp(MaggExpFac)
for n in range(N - 1):
new_hi = gridpoints[-1] * fac
new_lo = gridpoints[0] / fac
gridpoints.append(new_hi)
gridpoints.insert(0, new_lo)
MgridBase = np.array(gridpoints)
return MgridBase


###############################################################################


Expand Down Expand Up @@ -879,6 +911,7 @@ def solve_KrusellSmith(
"PermShkDstn": get_PermShkDstn_from_IncShkDstn,
"TranShkDstn": get_TranShkDstn_from_IncShkDstn,
"aXtraGrid": make_assets_grid,
"MgridBase": make_exponential_MgridBase,
"solution_terminal": make_aggshock_solution_terminal,
}

Expand All @@ -904,11 +937,12 @@ def solve_KrusellSmith(
"aXtraExtra": None, # Additional other values to add in grid (optional)
}

# Choose a grid of capital-to-labor-ratios (factors relative to SS)
# TODO: Make a constructor for this
MgridBase = np.array(
[0.1, 0.3, 0.6, 0.8, 0.9, 0.98, 1.0, 1.02, 1.1, 1.2, 1.6, 2.0, 3.0]
)
# Default parameters to make MgridBase using make_exponential_MgridBase
default_MgridBase_params = {
"MaggCount": 17,
"MaggPerturb": 0.01,
"MaggExpFac": 0.15,
}

# Make a dictionary to specify an aggregate income shocks consumer type
init_agg_shocks = {
Expand All @@ -923,7 +957,6 @@ def solve_KrusellSmith(
"LivPrb": [0.98], # Survival probability after each period
"PermGroFac": [1.00], # Permanent income growth factor
"BoroCnstArt": 0.0, # Artificial borrowing constraint
"MgridBase": MgridBase,
# PARAMETERS REQUIRED TO SIMULATE THE MODEL
"AgentCount": 10000, # Number of agents of this type
"T_age": None, # Age after which simulated agents are automatically killed
Expand All @@ -941,6 +974,7 @@ def solve_KrusellSmith(
}
init_agg_shocks.update(default_IncShkDstn_params)
init_agg_shocks.update(default_aXtraGrid_params)
init_agg_shocks.update(default_MgridBase_params)


class AggShockConsumerType(IndShockConsumerType):
Expand Down Expand Up @@ -1545,6 +1579,7 @@ def get_RnextArray(transition_arrays):
"mNextArray": get_mNextArray,
"MnextArray": get_MnextArray,
"RnextArray": get_RnextArray,
"MgridBase": make_exponential_MgridBase,
}

init_KS_agents = {
Expand All @@ -1558,9 +1593,10 @@ def get_RnextArray(transition_arrays):
"aMax": 50.0,
"aCount": 32,
"aNestFac": 2,
"MgridBase": np.array(
[0.1, 0.3, 0.6, 0.8, 0.9, 0.95, 0.98, 1.0, 1.02, 1.05, 1.1, 1.2, 1.6, 2.0, 3.0]
),
"MaggCount": 25,
"MaggPerturb": 0.01,
"MaggExpFac": 0.12,
"MgridBase": np.array([0.99, 1.0, 1.01]), ## dummy, this will be overwritten
"AgentCount": 5000,
}

Expand Down Expand Up @@ -1598,11 +1634,14 @@ def __init__(self, **kwds):
temp = kwds.copy()
temp["construct"] = False
AgentType.__init__(self, **temp)
self.construct("MgridBase")

# Special case: this type *must* be initialized with construct=False
# because the data required to make its solution attributes is obtained
# from the associated economy, not passed as part of its parameters.
# To make it work properly, instantiate both this class and an instance
# of KrusellSmithEconomy, then use this class' get_economy_data method.
# Exception: MgridBase must exist

def pre_solve(self):
self.construct("solution_terminal")
Expand Down
17 changes: 15 additions & 2 deletions HARK/ConsumptionSaving/ConsRepAgentModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
IndShockConsumerType,
make_basic_CRRA_solution_terminal,
)
from HARK.ConsumptionSaving.ConsMarkovModel import MarkovConsumerType
from HARK.ConsumptionSaving.ConsMarkovModel import (
MarkovConsumerType,
make_simple_binary_markov,
)
from HARK.distributions import MarkovProcess
from HARK.interpolation import LinearInterp, MargValueFuncCRRA
from HARK.utilities import make_assets_grid
Expand Down Expand Up @@ -61,6 +64,14 @@ def make_repagent_markov_solution_terminal(CRRA, MrkvArray):
return solution_terminal


def make_simple_binary_rep_markov(Mrkv_p11, Mrkv_p22):
MrkvArray = make_simple_binary_markov(1, [Mrkv_p11], [Mrkv_p22])[0]
return MrkvArray


###############################################################################


def solve_ConsRepAgent(
solution_next, DiscFac, CRRA, IncShkDstn, CapShare, DeprFac, PermGroFac, aXtraGrid
):
Expand Down Expand Up @@ -396,10 +407,12 @@ def get_states(self):
markov_repagent_constructor_dict["solution_terminal"] = (
make_repagent_markov_solution_terminal
)
markov_repagent_constructor_dict["MrkvArray"] = make_simple_binary_rep_markov

init_markov_rep_agent = init_rep_agent.copy()
init_markov_rep_agent["PermGroFac"] = [[0.97, 1.03]]
init_markov_rep_agent["MrkvArray"] = np.array([[0.99, 0.01], [0.01, 0.99]])
init_markov_rep_agent["Mrkv_p11"] = 0.99
init_markov_rep_agent["Mrkv_p22"] = 0.99
init_markov_rep_agent["Mrkv"] = 0
init_markov_rep_agent["constructors"] = markov_repagent_constructor_dict

Expand Down
20 changes: 10 additions & 10 deletions HARK/ConsumptionSaving/tests/test_ConsAggShockModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_agent(self):
self.agents[0].solve()
self.assertAlmostEqual(
self.agents[0].solution[0].cFunc(10.0, self.economy.MSS),
3.22908,
3.23694,
places=HARK_PRECISION,
)

Expand All @@ -58,7 +58,7 @@ def test_macro(self):
self.economy.solve() # Solve for the general equilibrium of the economy

self.economy.AFunc = self.economy.dynamics.AFunc
self.assertAlmostEqual(self.economy.AFunc.slope, 1.11810, places=HARK_PRECISION)
self.assertAlmostEqual(self.economy.AFunc.slope, 1.13204, places=HARK_PRECISION)

# simulation test -- seed/generator specific
# self.assertAlmostEqual(self.economy.history["MaggNow"][10], 7.45632, place = HARK_PRECISION)
Expand All @@ -80,7 +80,7 @@ def test_agent(self):
self.agent.solve()
self.assertAlmostEqual(
self.agent.solution[0].cFunc[0](10.0, self.economy.MSS),
2.56359,
2.56379,
places=HARK_PRECISION,
)

Expand All @@ -96,7 +96,7 @@ def test_economy(self):

self.economy.AFunc = self.economy.dynamics.AFunc
self.assertAlmostEqual(
self.economy.AFunc[0].slope, 1.08987, places=HARK_PRECISION
self.economy.AFunc[0].slope, 1.08571, places=HARK_PRECISION
)

# simulation test -- seed/generator specific
Expand Down Expand Up @@ -127,7 +127,7 @@ def test_agent(self):
self.agent.solve()
self.assertAlmostEqual(
self.agent.solution[0].cFunc[0](10.0, self.economy.MSS),
1.23868,
1.24280,
places=HARK_PRECISION,
)

Expand Down Expand Up @@ -177,7 +177,7 @@ def test_methods(self):

# testing precompute_arrays()
self.assertAlmostEqual(
self.agent.mNextArray[5, 2, 3, 0], 0.34880, places=HARK_PRECISION
self.agent.mNextArray[5, 2, 3, 0], 0.35541, places=HARK_PRECISION
)

# testing make_grid()
Expand All @@ -192,7 +192,7 @@ def test_methods(self):

self.assertAlmostEqual(
self.economy.agents[0].solution[0].cFunc[0](10, self.economy.MSS).tolist(),
1.2386774,
1.24280,
places=4,
)

Expand Down Expand Up @@ -234,11 +234,11 @@ def test_methods(self):
new_dynamics = self.economy.update_dynamics()

self.assertAlmostEqual(
new_dynamics.AFunc[0].slope, 1.01779, places=HARK_PRECISION
new_dynamics.AFunc[0].slope, 1.02231, places=HARK_PRECISION
)

self.assertAlmostEqual(
new_dynamics.AFunc[1].slope, 1.02020, places=HARK_PRECISION
new_dynamics.AFunc[1].slope, 1.02515, places=HARK_PRECISION
)


Expand All @@ -256,7 +256,7 @@ def test_economy(self):

self.economy.AFunc = self.economy.dynamics.AFunc
self.assertAlmostEqual(
self.economy.AFunc[0].slope, 1.02668, places=HARK_PRECISION
self.economy.AFunc[0].slope, 1.03346, places=HARK_PRECISION
)

# simulation test -- seed/generator specific
Expand Down

0 comments on commit df5a130

Please sign in to comment.