diff --git a/Documentation/reference/ConsumptionSaving/index.rst b/Documentation/reference/ConsumptionSaving/index.rst index fb83b80de..7d257b291 100644 --- a/Documentation/reference/ConsumptionSaving/index.rst +++ b/Documentation/reference/ConsumptionSaving/index.rst @@ -15,3 +15,4 @@ Consumption Saving ConsPrefShochModel ConsRepAgentModel TractableBufferStockModel + diff --git a/Documentation/reference/index.rst b/Documentation/reference/index.rst index 71de1f91c..5281f8b08 100644 --- a/Documentation/reference/index.rst +++ b/Documentation/reference/index.rst @@ -16,3 +16,4 @@ Models :maxdepth: 3 ConsumptionSaving/index + diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index db6c8419d..f5b7ce04a 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -12,50 +12,51 @@ See NARK https://HARK.githhub.io/Documentation/NARK for information on variable naming conventions. See HARK documentation for mathematical descriptions of the models being solved. """ -from copy import copy, deepcopy -import numpy as np -from scipy.optimize import newton -from HARK import AgentType, NullFunc, MetricObject, make_one_period_oo_solver -from HARK.utilities import warnings # Because of "patch" to warnings modules -from HARK.interpolation import ( - CubicInterp, - LowerEnvelope, - LinearInterp, - ValueFuncCRRA, - MargValueFuncCRRA, - MargMargValueFuncCRRA -) -from HARK.distribution import Lognormal, MeanOneLogNormal, Uniform -from HARK.distribution import ( - DiscreteDistribution, - add_discrete_outcome_constant_mean, - calc_expectation, - combine_indep_dstns, -) -from HARK.utilities import ( - make_grid_exp_mult, - CRRAutility, - CRRAutilityP, - CRRAutilityPP, - CRRAutilityP_inv, - CRRAutility_invP, - CRRAutility_inv, - CRRAutilityP_invP, -) -from HARK import _log -from HARK import set_verbosity_level -from HARK.Calibration.Income.IncomeTools import parse_income_spec, parse_time_params, Cagetti_income -from HARK.datasets.SCF.WealthIncomeDist.SCFDistTools import income_wealth_dists_from_scf -from HARK.datasets.life_tables.us_ssa.SSATools import parse_ssa_life_table +from HARK.ConsumptionSaving.ConsIndShockModelOld \ + import ConsumerSolution as ConsumerSolutionOld +from HARK.ConsumptionSaving.ConsIndShockModel_AgentSolve \ + import ( + ConsumerSolution, ConsumerSolutionOneNrmStateCRRA, + ConsPerfForesightSolver, ConsIndShockSetup, + ConsIndShockSolverBasic, ConsIndShockSolver + ) + +from HARK.ConsumptionSaving.ConsIndShockModel_KinkedRSolver \ + import ConsKinkedRsolver + +from HARK.ConsumptionSaving.ConsIndShockModel_AgentTypes \ + import (consumer_terminal_nobequest_onestate, PerfForesightConsumerType, + IndShockConsumerType, KinkedRconsumerType, + onestate_bequest_warmglow_homothetic + ) + +from HARK.ConsumptionSaving.ConsIndShockModel_AgentDicts \ + import ( + init_perfect_foresight, + init_idiosyncratic_shocks, + init_kinked_R, + init_lifecycle, + init_cyclical) + +from HARK.utilities import CRRAutility as utility +from HARK.utilities import CRRAutilityP as utilityP +from HARK.utilities import CRRAutilityPP as utilityPP +from HARK.utilities import CRRAutilityP_inv as utilityP_inv +from HARK.utilities import CRRAutility_invP as utility_invP +from HARK.utilities import CRRAutility_inv as utility_inv +from HARK.utilities import CRRAutilityP as utilityP_invP __all__ = [ + "ConsumerSolutionOld", "ConsumerSolution", + "ConsumerSolutionOneNrmStateCRRA", "ConsPerfForesightSolver", "ConsIndShockSetup", "ConsIndShockSolverBasic", "ConsIndShockSolver", "ConsKinkedRsolver", + "consumer_terminal_nobequest_onestate", "PerfForesightConsumerType", "IndShockConsumerType", "KinkedRconsumerType", @@ -64,2994 +65,12 @@ "init_kinked_R", "init_lifecycle", "init_cyclical", + "utility", + "utilityP", + "utilityPP", + "utilityP_inv", + "utility_invP", + "utility_inv", + "utilityP_invP", + "onestate_bequest_warmglow_homothetic" ] - -utility = CRRAutility -utilityP = CRRAutilityP -utilityPP = CRRAutilityPP -utilityP_inv = CRRAutilityP_inv -utility_invP = CRRAutility_invP -utility_inv = CRRAutility_inv -utilityP_invP = CRRAutilityP_invP - -# ===================================================================== -# === Classes that help solve consumption-saving models === -# ===================================================================== - - -class ConsumerSolution(MetricObject): - """ - A class representing the solution of a single period of a consumption-saving - problem. The solution must include a consumption function and marginal - value function. - - Here and elsewhere in the code, Nrm indicates that variables are normalized - by permanent income. - - Parameters - ---------- - cFunc : function - The consumption function for this period, defined over market - resources: c = cFunc(m). - vFunc : function - The beginning-of-period value function for this period, defined over - market resources: v = vFunc(m). - vPfunc : function - The beginning-of-period marginal value function for this period, - defined over market resources: vP = vPfunc(m). - vPPfunc : function - The beginning-of-period marginal marginal value function for this - period, defined over market resources: vPP = vPPfunc(m). - mNrmMin : float - The minimum allowable market resources for this period; the consump- - tion function (etc) are undefined for m < mNrmMin. - hNrm : float - Human wealth after receiving income this period: PDV of all future - income, ignoring mortality. - MPCmin : float - Infimum of the marginal propensity to consume this period. - MPC --> MPCmin as m --> infinity. - MPCmax : float - Supremum of the marginal propensity to consume this period. - MPC --> MPCmax as m --> mNrmMin. - - """ - - distance_criteria = ["vPfunc"] - - def __init__( - self, - cFunc=None, - vFunc=None, - vPfunc=None, - vPPfunc=None, - mNrmMin=None, - hNrm=None, - MPCmin=None, - MPCmax=None, - ): - # Change any missing function inputs to NullFunc - self.cFunc = cFunc if cFunc is not None else NullFunc() - self.vFunc = vFunc if vFunc is not None else NullFunc() - self.vPfunc = vPfunc if vPfunc is not None else NullFunc() - # vPFunc = NullFunc() if vPfunc is None else vPfunc - self.vPPfunc = vPPfunc if vPPfunc is not None else NullFunc() - self.mNrmMin = mNrmMin - self.hNrm = hNrm - self.MPCmin = MPCmin - self.MPCmax = MPCmax - - def append_solution(self, new_solution): - """ - Appends one solution to another to create a ConsumerSolution whose - attributes are lists. Used in ConsMarkovModel, where we append solutions - *conditional* on a particular value of a Markov state to each other in - order to get the entire solution. - - Parameters - ---------- - new_solution : ConsumerSolution - The solution to a consumption-saving problem; each attribute is a - list representing state-conditional values or functions. - - Returns - ------- - None - """ - if type(self.cFunc) != list: - # Then we assume that self is an empty initialized solution instance. - # Begin by checking this is so. - assert ( - NullFunc().distance(self.cFunc) == 0 - ), "append_solution called incorrectly!" - - # We will need the attributes of the solution instance to be lists. Do that here. - self.cFunc = [new_solution.cFunc] - self.vFunc = [new_solution.vFunc] - self.vPfunc = [new_solution.vPfunc] - self.vPPfunc = [new_solution.vPPfunc] - self.mNrmMin = [new_solution.mNrmMin] - else: - self.cFunc.append(new_solution.cFunc) - self.vFunc.append(new_solution.vFunc) - self.vPfunc.append(new_solution.vPfunc) - self.vPPfunc.append(new_solution.vPPfunc) - self.mNrmMin.append(new_solution.mNrmMin) - - -# ===================================================================== -# === Classes and functions that solve consumption-saving models === -# ===================================================================== - - -class ConsPerfForesightSolver(MetricObject): - """ - A class for solving a one period perfect foresight - consumption-saving problem. - An instance of this class is created by the function solvePerfForesight - in each period. - - Parameters - ---------- - solution_next : ConsumerSolution - The solution to next period's one-period problem. - DiscFac : float - Intertemporal discount factor for future utility. - LivPrb : float - Survival probability; likelihood of being alive at the beginning of - the next period. - CRRA : float - Coefficient of relative risk aversion. - Rfree : float - Risk free interest factor on end-of-period assets. - PermGroFac : float - Expected permanent income growth factor at the end of this period. - BoroCnstArt : float or None - Artificial borrowing constraint, as a multiple of permanent income. - Can be None, indicating no artificial constraint. - MaxKinks : int - Maximum number of kink points to allow in the consumption function; - additional points will be thrown out. Only relevant in infinite - horizon model with artificial borrowing constraint. - """ - - def __init__( - self, - solution_next, - DiscFac, - LivPrb, - CRRA, - Rfree, - PermGroFac, - BoroCnstArt, - MaxKinks, - ): - self.solution_next = solution_next - self.DiscFac = DiscFac - self.LivPrb = LivPrb - self.CRRA = CRRA - self.Rfree = Rfree - self.PermGroFac = PermGroFac - self.BoroCnstArt = BoroCnstArt - self.MaxKinks = MaxKinks - - def def_utility_funcs(self): - """ - Defines CRRA utility function for this period (and its derivatives), - saving them as attributes of self for other methods to use. - - Parameters - ---------- - None - - Returns - ------- - None - """ - self.u = lambda c: utility(c, gam=self.CRRA) # utility function - self.uP = lambda c: utilityP(c, gam=self.CRRA) # marginal utility function - self.uPP = lambda c: utilityPP( - c, gam=self.CRRA - ) # marginal marginal utility function - - def def_value_funcs(self): - """ - Defines the value and marginal value functions for this period. - Uses the fact that for a perfect foresight CRRA utility problem, - if the MPC in period t is :math:`\kappa_{t}`, and relative risk - aversion :math:`\rho`, then the inverse value vFuncNvrs has a - constant slope of :math:`\kappa_{t}^{-\rho/(1-\rho)}` and - vFuncNvrs has value of zero at the lower bound of market resources - mNrmMin. See PerfForesightConsumerType.ipynb documentation notebook - for a brief explanation and the links below for a fuller treatment. - - https://www.econ2.jhu.edu/people/ccarroll/public/lecturenotes/consumption/PerfForesightCRRA/#vFuncAnalytical - https://www.econ2.jhu.edu/people/ccarroll/SolvingMicroDSOPs/#vFuncPF - - Parameters - ---------- - None - - Returns - ------- - None - """ - - # See the PerfForesightConsumerType.ipynb documentation notebook for the derivations - vFuncNvrsSlope = self.MPCmin ** (-self.CRRA / (1.0 - self.CRRA)) - vFuncNvrs = LinearInterp( - np.array([self.mNrmMinNow, self.mNrmMinNow + 1.0]), - np.array([0.0, vFuncNvrsSlope]), - ) - self.vFunc = ValueFuncCRRA(vFuncNvrs, self.CRRA) - self.vPfunc = MargValueFuncCRRA(self.cFunc, self.CRRA) - - def make_cFunc_PF(self): - """ - Makes the (linear) consumption function for this period. - - Parameters - ---------- - None - - Returns - ------- - None - """ - # Use a local value of BoroCnstArt to prevent comparing None and float below. - if self.BoroCnstArt is None: - BoroCnstArt = -np.inf - else: - BoroCnstArt = self.BoroCnstArt - - # Calculate human wealth this period - self.hNrmNow = (self.PermGroFac / self.Rfree) * (self.solution_next.hNrm + 1.0) - - # Calculate the lower bound of the marginal propensity to consume - PatFac = ((self.Rfree * self.DiscFacEff) ** (1.0 / self.CRRA)) / self.Rfree - self.MPCmin = 1.0 / (1.0 + PatFac / self.solution_next.MPCmin) - - # Extract the discrete kink points in next period's consumption function; - # don't take the last one, as it only defines the extrapolation and is not a kink. - mNrmNext = self.solution_next.cFunc.x_list[:-1] - cNrmNext = self.solution_next.cFunc.y_list[:-1] - - # Calculate the end-of-period asset values that would reach those kink points - # next period, then invert the first order condition to get consumption. Then - # find the endogenous gridpoint (kink point) today that corresponds to each kink - aNrmNow = (self.PermGroFac / self.Rfree) * (mNrmNext - 1.0) - cNrmNow = (self.DiscFacEff * self.Rfree) ** (-1.0 / self.CRRA) * ( - self.PermGroFac * cNrmNext - ) - mNrmNow = aNrmNow + cNrmNow - - # Add an additional point to the list of gridpoints for the extrapolation, - # using the new value of the lower bound of the MPC. - mNrmNow = np.append(mNrmNow, mNrmNow[-1] + 1.0) - cNrmNow = np.append(cNrmNow, cNrmNow[-1] + self.MPCmin) - - # If the artificial borrowing constraint binds, combine the constrained and - # unconstrained consumption functions. - if BoroCnstArt > mNrmNow[0]: - # Find the highest index where constraint binds - cNrmCnst = mNrmNow - BoroCnstArt - CnstBinds = cNrmCnst < cNrmNow - idx = np.where(CnstBinds)[0][-1] - - if idx < (mNrmNow.size - 1): - # If it is not the *very last* index, find the the critical level - # of mNrm where the artificial borrowing contraint begins to bind. - d0 = cNrmNow[idx] - cNrmCnst[idx] - d1 = cNrmCnst[idx + 1] - cNrmNow[idx + 1] - m0 = mNrmNow[idx] - m1 = mNrmNow[idx + 1] - alpha = d0 / (d0 + d1) - mCrit = m0 + alpha * (m1 - m0) - - # Adjust the grids of mNrm and cNrm to account for the borrowing constraint. - cCrit = mCrit - BoroCnstArt - mNrmNow = np.concatenate(([BoroCnstArt, mCrit], mNrmNow[(idx + 1):])) - cNrmNow = np.concatenate(([0.0, cCrit], cNrmNow[(idx + 1):])) - - else: - # If it *is* the very last index, then there are only three points - # that characterize the consumption function: the artificial borrowing - # constraint, the constraint kink, and the extrapolation point. - mXtra = (cNrmNow[-1] - cNrmCnst[-1]) / (1.0 - self.MPCmin) - mCrit = mNrmNow[-1] + mXtra - cCrit = mCrit - BoroCnstArt - mNrmNow = np.array([BoroCnstArt, mCrit, mCrit + 1.0]) - cNrmNow = np.array([0.0, cCrit, cCrit + self.MPCmin]) - - # If the mNrm and cNrm grids have become too large, throw out the last - # kink point, being sure to adjust the extrapolation. - if mNrmNow.size > self.MaxKinks: - mNrmNow = np.concatenate((mNrmNow[:-2], [mNrmNow[-3] + 1.0])) - cNrmNow = np.concatenate((cNrmNow[:-2], [cNrmNow[-3] + self.MPCmin])) - - # Construct the consumption function as a linear interpolation. - self.cFunc = LinearInterp(mNrmNow, cNrmNow) - - # Calculate the upper bound of the MPC as the slope of the bottom segment. - self.MPCmax = (cNrmNow[1] - cNrmNow[0]) / (mNrmNow[1] - mNrmNow[0]) - - # Add two attributes to enable calculation of steady state market resources. - self.Ex_IncNext = 1.0 # Perfect foresight income of 1 - self.mNrmMinNow = mNrmNow[0] # Relabeling for compatibility with add_mNrmStE - - def add_mNrmTrg(self, solution): - """ - Finds value of (normalized) market resources m at which individual consumer - expects m not to change. - This will exist if the GICNrm holds. - - https://econ-ark.github.io/BufferStockTheory#UniqueStablePoints - - Parameters - ---------- - solution : ConsumerSolution - Solution to this period's problem, which must have attribute cFunc. - Returns - ------- - solution : ConsumerSolution - Same solution that was passed, but now with the attribute mNrmStE. - """ - - # If no uncertainty, return the degenerate targets for the PF model - if hasattr(self, "TranShkMinNext"): # Then it has transitory shocks - # Handle the degenerate case where shocks are of size zero - if ((self.TranShkMinNext == 1.0) and (self.PermShkMinNext == 1.0)): - # but they are of zero size (and also permanent are zero) - if self.GICRaw: # max of nat and art boro cnst - if type(self.BoroCnstArt) == type(None): - solution.mNrmStE = -self.hNrmNow - solution.mNrmTrg = -self.hNrmNow - else: - bNrmNxt = -self.BoroCnstArt * self.Rfree/self.PermGroFac - solution.mNrmStE = bNrmNxt + 1.0 - solution.mNrmTrg = bNrmNxt + 1.0 - else: # infinity - solution.mNrmStE = float('inf') - solution.mNrmTrg = float('inf') - return solution - - # First find - # \bar{\mathcal{R}} = E_t[R/Gamma_{t+1}] = R/Gamma E_t[1/psi_{t+1}] - if type(self) == ConsPerfForesightSolver: - Ex_PermShkInv = 1.0 - else: - Ex_PermShkInv = np.dot(1/self.PermShkValsNext, self.ShkPrbsNext) - - Ex_RNrmFac = (self.Rfree/self.PermGroFac)*Ex_PermShkInv - - # mNrmTrg solves Rcalbar*(m - c(m)) + E[inc_next] = m. Define a - # rearranged version. - Ex_m_tp1_minus_m_t = ( - lambda m: Ex_RNrmFac * (m - solution.cFunc(m)) + self.Ex_IncNext - m - ) - - # Minimum market resources plus next income is okay starting guess - m_init_guess = self.mNrmMinNow + self.Ex_IncNext - try: - mNrmTrg = newton(Ex_m_tp1_minus_m_t, m_init_guess) - except: - mNrmTrg = None - - # Add mNrmTrg to the solution and return it - solution.mNrmTrg = mNrmTrg - return solution - - def add_mNrmStE(self, solution): - """ - Finds market resources ratio at which 'balanced growth' is expected. - This is the m ratio such that the expected growth rate of the M level - matches the expected growth rate of permanent income. This value does - not exist if the Growth Impatience Condition does not hold. - - https://econ-ark.github.io/BufferStockTheory#Unique-Stable-Points - - Parameters - ---------- - solution : ConsumerSolution - Solution to this period's problem, which must have attribute cFunc. - Returns - ------- - solution : ConsumerSolution - Same solution that was passed, but now with the attribute mNrmStE - """ - # Probably should test whether GICRaw holds and log error if it does not - # using check_conditions - # All combinations of c and m that yield E[PermGroFac PermShkVal mNext] = mNow - # https://econ-ark.github.io/BufferStockTheory/#The-Individual-Steady-State - - PF_RNrm = self.Rfree/self.PermGroFac - # If we are working with a model that permits uncertainty but that - # uncertainty has been set to zero, return the correct answer - # by hand because in this degenerate case numerical search may - # have trouble - if hasattr(self, "TranShkMinNext"): # Then it has transitory shocks - if ((self.TranShkMinNext == 1.0) and (self.PermShkMinNext == 1.0)): - # but they are of zero size (and permanent shocks also not there) - if self.GICRaw: # max of nat and art boro cnst - # breakpoint() - if type(self.BoroCnstArt) == type(None): - solution.mNrmStE = -self.hNrmNow - solution.mNrmTrg = -self.hNrmNow - else: - bNrmNxt = -self.BoroCnstArt * self.Rfree/self.PermGroFac - solution.mNrmStE = bNrmNxt + 1.0 - solution.mNrmTrg = bNrmNxt + 1.0 - else: # infinity - solution.mNrmStE = float('inf') - solution.mNrmTrg = float('inf') - return solution - - Ex_PermShk_tp1_times_m_tp1_minus_m_t = ( - lambda mStE: PF_RNrm * (mStE - solution.cFunc(mStE)) + 1.0 - mStE - ) - - # Minimum market resources plus next income is okay starting guess - m_init_guess = self.mNrmMinNow + self.Ex_IncNext - try: - mNrmStE = newton(Ex_PermShk_tp1_times_m_tp1_minus_m_t, m_init_guess) - except: - mNrmStE = None - - solution.mNrmStE = mNrmStE - return solution - - def add_stable_points(self, solution): - """ - Checks necessary conditions for the existence of the individual steady - state and target levels of market resources (see above). - If the conditions are satisfied, computes and adds the stable points - to the solution. - - Parameters - ---------- - solution : ConsumerSolution - Solution to this period's problem, which must have attribute cFunc. - Returns - ------- - solution : ConsumerSolution - Same solution that was provided, augmented with attributes mNrmStE and - mNrmTrg, if they exist. - - """ - - # 0. There is no non-degenerate steady state for any unconstrained PF model. - # 1. There is a non-degenerate SS for constrained PF model if GICRaw holds. - # Therefore - # Check if (GICRaw and BoroCnstArt) and if so compute them both - thorn = (self.Rfree*self.DiscFacEff)**(1/self.CRRA) - GICRaw = 1 > thorn/self.PermGroFac - if self.BoroCnstArt is not None and GICRaw: - solution = self.add_mNrmStE(solution) - solution = self.add_mNrmTrg(solution) - return solution - - def solve(self): - """ - Solves the one period perfect foresight consumption-saving problem. - - Parameters - ---------- - None - - Returns - ------- - solution : ConsumerSolution - The solution to this period's problem. - """ - self.def_utility_funcs() - self.DiscFacEff = self.DiscFac * self.LivPrb # Effective=pure x LivPrb - self.make_cFunc_PF() - self.def_value_funcs() - - solution = ConsumerSolution( - cFunc=self.cFunc, - vFunc=self.vFunc, - vPfunc=self.vPfunc, - mNrmMin=self.mNrmMinNow, - hNrm=self.hNrmNow, - MPCmin=self.MPCmin, - MPCmax=self.MPCmax, - ) - - solution = self.add_stable_points(solution) - - return solution - - -############################################################################### -############################################################################### -class ConsIndShockSetup(ConsPerfForesightSolver): - """ - A superclass for solvers of one period consumption-saving problems with - constant relative risk aversion utility and permanent and transitory shocks - to income. Has methods to set up but not solve the one period problem. - - Parameters - ---------- - solution_next : ConsumerSolution - The solution to next period's one period problem. - IncShkDstn : distribution.Distribution - A discrete - approximation to the income process between the period being solved - and the one immediately following (in solution_next). - LivPrb : float - Survival probability; likelihood of being alive at the beginning of - the succeeding period. - DiscFac : float - Intertemporal discount factor for future utility. - CRRA : float - Coefficient of relative risk aversion. - Rfree : float - Risk free interest factor on end-of-period assets. - PermGroFac : float - Expected permanent income growth factor at the end of this period. - BoroCnstArt: float or None - Borrowing constraint for the minimum allowable assets to end the - period with. If it is less than the natural borrowing constraint, - then it is irrelevant; BoroCnstArt=None indicates no artificial bor- - rowing constraint. - aXtraGrid: np.array - Array of "extra" end-of-period asset values-- assets above the - absolute minimum acceptable level. - vFuncBool: boolean - An indicator for whether the value function should be computed and - included in the reported solution. - CubicBool: boolean - An indicator for whether the solver should use cubic or linear inter- - polation. - """ - - def __init__( - self, - solution_next, - IncShkDstn, - LivPrb, - DiscFac, - CRRA, - Rfree, - PermGroFac, - BoroCnstArt, - aXtraGrid, - vFuncBool, - CubicBool, - ): - """ - Constructor for a new solver-setup for problems with income subject to - permanent and transitory shocks. - """ - self.solution_next = solution_next - self.IncShkDstn = IncShkDstn - self.LivPrb = LivPrb - self.DiscFac = DiscFac - self.CRRA = CRRA - self.Rfree = Rfree - self.PermGroFac = PermGroFac - self.BoroCnstArt = BoroCnstArt - self.aXtraGrid = aXtraGrid - self.vFuncBool = vFuncBool - self.CubicBool = CubicBool - - self.def_utility_funcs() - - def def_utility_funcs(self): - """ - Defines CRRA utility function for this period (and its derivatives, - and their inverses), saving them as attributes of self for other methods - to use. - - Parameters - ---------- - none - - Returns - ------- - none - """ - ConsPerfForesightSolver.def_utility_funcs(self) - self.uPinv = lambda u: utilityP_inv(u, gam=self.CRRA) - self.uPinvP = lambda u: utilityP_invP(u, gam=self.CRRA) - self.uinvP = lambda u: utility_invP(u, gam=self.CRRA) - if self.vFuncBool: - self.uinv = lambda u: utility_inv(u, gam=self.CRRA) - - def set_and_update_values(self, solution_next, IncShkDstn, LivPrb, DiscFac): - """ - Unpacks some of the inputs (and calculates simple objects based on them), - storing the results in self for use by other methods. These include: - income shocks and probabilities, next period's marginal value function - (etc), the probability of getting the worst income shock next period, - the patience factor, human wealth, and the bounding MPCs. - - Parameters - ---------- - solution_next : ConsumerSolution - The solution to next period's one period problem. - IncShkDstn : distribution.DiscreteDistribution - A DiscreteDistribution with a pmf - and two point value arrays in X, order: - permanent shocks, transitory shocks. - LivPrb : float - Survival probability; likelihood of being alive at the beginning of - the succeeding period. - DiscFac : float - Intertemporal discount factor for future utility. - - Returns - ------- - None - """ - self.DiscFacEff = DiscFac * LivPrb # "effective" discount factor - self.IncShkDstn = IncShkDstn - self.ShkPrbsNext = IncShkDstn.pmf - self.PermShkValsNext = IncShkDstn.X[0] - self.TranShkValsNext = IncShkDstn.X[1] - self.PermShkMinNext = np.min(self.PermShkValsNext) - self.TranShkMinNext = np.min(self.TranShkValsNext) - self.vPfuncNext = solution_next.vPfunc - self.WorstIncPrb = np.sum( - self.ShkPrbsNext[ - (self.PermShkValsNext * self.TranShkValsNext) - == (self.PermShkMinNext * self.TranShkMinNext) - ] - ) - - if self.CubicBool: - self.vPPfuncNext = solution_next.vPPfunc - - if self.vFuncBool: - self.vFuncNext = solution_next.vFunc - - # Update the bounding MPCs and PDV of human wealth: - self.PatFac = ((self.Rfree * self.DiscFacEff) ** (1.0 / self.CRRA)) / self.Rfree - self.MPCminNow = 1.0 / (1.0 + self.PatFac / solution_next.MPCmin) - self.Ex_IncNext = np.dot( - self.ShkPrbsNext, self.TranShkValsNext * self.PermShkValsNext - ) - self.hNrmNow = ( - self.PermGroFac / self.Rfree * (self.Ex_IncNext + solution_next.hNrm) - ) - self.MPCmaxNow = 1.0 / ( - 1.0 - + (self.WorstIncPrb ** (1.0 / self.CRRA)) - * self.PatFac - / solution_next.MPCmax - ) - - self.cFuncLimitIntercept = self.MPCminNow * self.hNrmNow - self.cFuncLimitSlope = self.MPCminNow - - def def_BoroCnst(self, BoroCnstArt): - """ - Defines the constrained portion of the consumption function as cFuncNowCnst, - an attribute of self. Uses the artificial and natural borrowing constraints. - - Parameters - ---------- - BoroCnstArt : float or None - Borrowing constraint for the minimum allowable assets to end the - period with. If it is less than the natural borrowing constraint, - then it is irrelevant; BoroCnstArt=None indicates no artificial bor- - rowing constraint. - - Returns - ------- - none - """ - # Calculate the minimum allowable value of money resources in this period - self.BoroCnstNat = ( - (self.solution_next.mNrmMin - self.TranShkMinNext) - * (self.PermGroFac * self.PermShkMinNext) - / self.Rfree - ) - - # Note: need to be sure to handle BoroCnstArt==None appropriately. - # In Py2, this would evaluate to 5.0: np.max([None, 5.0]). - # However in Py3, this raises a TypeError. Thus here we need to directly - # address the situation in which BoroCnstArt == None: - if BoroCnstArt is None: - self.mNrmMinNow = self.BoroCnstNat - else: - self.mNrmMinNow = np.max([self.BoroCnstNat, BoroCnstArt]) - if self.BoroCnstNat < self.mNrmMinNow: - self.MPCmaxEff = 1.0 # If actually constrained, MPC near limit is 1 - else: - self.MPCmaxEff = self.MPCmaxNow - - # Define the borrowing constraint (limiting consumption function) - self.cFuncNowCnst = LinearInterp( - np.array([self.mNrmMinNow, self.mNrmMinNow + 1]), np.array([0.0, 1.0]) - ) - - def prepare_to_solve(self): - """ - Perform preparatory work before calculating the unconstrained consumption - function. - - Parameters - ---------- - none - - Returns - ------- - none - """ - self.set_and_update_values( - self.solution_next, self.IncShkDstn, self.LivPrb, self.DiscFac - ) - self.def_BoroCnst(self.BoroCnstArt) - - -#################################################################################################### -#################################################################################################### - - -class ConsIndShockSolverBasic(ConsIndShockSetup): - """ - This class solves a single period of a standard consumption-saving problem, - using linear interpolation and without the ability to calculate the value - function. ConsIndShockSolver inherits from this class and adds the ability - to perform cubic interpolation and to calculate the value function. - - Note that this class does not have its own initializing method. It initial- - izes the same problem in the same way as ConsIndShockSetup, from which it - inherits. - """ - - def prepare_to_calc_EndOfPrdvP(self): - """ - Prepare to calculate end-of-period marginal value by creating an array - of market resources that the agent could have next period, considering - the grid of end-of-period assets and the distribution of shocks he might - experience next period. - - Parameters - ---------- - none - - Returns - ------- - aNrmNow : np.array - A 1D array of end-of-period assets; also stored as attribute of self. - """ - - # We define aNrmNow all the way from BoroCnstNat up to max(self.aXtraGrid) - # even if BoroCnstNat < BoroCnstArt, so we can construct the consumption - # function as the lower envelope of the (by the artificial borrowing con- - # straint) uconstrained consumption function, and the artificially con- - # strained consumption function. - self.aNrmNow = np.asarray(self.aXtraGrid) + self.BoroCnstNat - - return self.aNrmNow - - def m_nrm_next(self, shocks, a_nrm): - """ - Computes normalized market resources of the next period - from income shocks and current normalized market resources. - - Parameters - ---------- - shocks: [float] - Permanent and transitory income shock levels. a_nrm: float - Normalized market assets this period - - Returns - ------- - float - normalized market resources in the next period - """ - return self.Rfree / (self.PermGroFac * shocks[0]) \ - * a_nrm + shocks[1] - - def calc_EndOfPrdvP(self): - """ - Calculate end-of-period marginal value of assets at each point in aNrmNow. - Does so by taking a weighted sum of next period marginal values across - income shocks (in a preconstructed grid self.mNrmNext). - - Parameters - ---------- - none - - Returns - ------- - EndOfPrdvP : np.array - A 1D array of end-of-period marginal value of assets - """ - - def vp_next(shocks, a_nrm): - return shocks[0] ** (-self.CRRA) \ - * self.vPfuncNext(self.m_nrm_next(shocks, a_nrm)) - - EndOfPrdvP = ( - self.DiscFacEff - * self.Rfree - * self.PermGroFac ** (-self.CRRA) - * calc_expectation( - self.IncShkDstn, - vp_next, - self.aNrmNow - ) - ) - - return EndOfPrdvP - - def get_points_for_interpolation(self, EndOfPrdvP, aNrmNow): - """ - Finds interpolation points (c,m) for the consumption function. - - Parameters - ---------- - EndOfPrdvP : np.array - Array of end-of-period marginal values. - aNrmNow : np.array - Array of end-of-period asset values that yield the marginal values - in EndOfPrdvP. - - Returns - ------- - c_for_interpolation : np.array - Consumption points for interpolation. - m_for_interpolation : np.array - Corresponding market resource points for interpolation. - """ - cNrmNow = self.uPinv(EndOfPrdvP) - mNrmNow = cNrmNow + aNrmNow - - # Limiting consumption is zero as m approaches mNrmMin - c_for_interpolation = np.insert(cNrmNow, 0, 0.0, axis=-1) - m_for_interpolation = np.insert(mNrmNow, 0, self.BoroCnstNat, axis=-1) - - # Store these for calcvFunc - self.cNrmNow = cNrmNow - self.mNrmNow = mNrmNow - - return c_for_interpolation, m_for_interpolation - - def use_points_for_interpolation(self, cNrm, mNrm, interpolator): - """ - Constructs a basic solution for this period, including the consumption - function and marginal value function. - - Parameters - ---------- - cNrm : np.array - (Normalized) consumption points for interpolation. - mNrm : np.array - (Normalized) corresponding market resource points for interpolation. - interpolator : function - A function that constructs and returns a consumption function. - - Returns - ------- - solution_now : ConsumerSolution - The solution to this period's consumption-saving problem, with a - consumption function, marginal value function, and minimum m. - """ - # Construct the unconstrained consumption function - cFuncNowUnc = interpolator(mNrm, cNrm) - - # Combine the constrained and unconstrained functions into the true consumption function - # breakpoint() # LowerEnvelope should only be used when BoroCnstArt is true - cFuncNow = LowerEnvelope(cFuncNowUnc, self.cFuncNowCnst, nan_bool=False) - - # Make the marginal value function and the marginal marginal value function - vPfuncNow = MargValueFuncCRRA(cFuncNow, self.CRRA) - - # Pack up the solution and return it - solution_now = ConsumerSolution( - cFunc=cFuncNow, vPfunc=vPfuncNow, mNrmMin=self.mNrmMinNow - ) - - return solution_now - - def make_basic_solution(self, EndOfPrdvP, aNrm, interpolator): - """ - Given end of period assets and end of period marginal value, construct - the basic solution for this period. - - Parameters - ---------- - EndOfPrdvP : np.array - Array of end-of-period marginal values. - aNrm : np.array - Array of end-of-period asset values that yield the marginal values - in EndOfPrdvP. - - interpolator : function - A function that constructs and returns a consumption function. - - Returns - ------- - solution_now : ConsumerSolution - The solution to this period's consumption-saving problem, with a - consumption function, marginal value function, and minimum m. - """ - cNrm, mNrm = self.get_points_for_interpolation(EndOfPrdvP, aNrm) - solution_now = self.use_points_for_interpolation(cNrm, mNrm, interpolator) - - return solution_now - - def add_MPC_and_human_wealth(self, solution): - """ - Take a solution and add human wealth and the bounding MPCs to it. - - Parameters - ---------- - solution : ConsumerSolution - The solution to this period's consumption-saving problem. - - Returns: - ---------- - solution : ConsumerSolution - The solution to this period's consumption-saving problem, but now - with human wealth and the bounding MPCs. - """ - solution.hNrm = self.hNrmNow - solution.MPCmin = self.MPCminNow - solution.MPCmax = self.MPCmaxEff - return solution - - def add_stable_points(self, solution): - """ - Checks necessary conditions for the existence of the individual steady - state and target levels of market resources (see above). - If the conditions are satisfied, computes and adds the stable points - to the solution. - - Parameters - ---------- - solution : ConsumerSolution - Solution to this period's problem, which must have attribute cFunc. - Returns - ------- - solution : ConsumerSolution - Same solution that was passed, but now with attributes mNrmStE and - mNrmTrg, if they exist. - - """ - - # 0. Check if GICRaw holds. If so, then mNrmStE will exist. So, compute it. - # 1. Check if GICNrm holds. If so, then mNrmTrg will exist. So, compute it. - - thorn = (self.Rfree*self.DiscFacEff)**(1/self.CRRA) - - GPFRaw = thorn / self.PermGroFac - self.GPFRaw = GPFRaw - GPFNrm = thorn / self.PermGroFac / np.dot(1/self.PermShkValsNext, self.ShkPrbsNext) - self.GPFNrm = GPFNrm - GICRaw = 1 > thorn/self.PermGroFac - self.GICRaw = GICRaw - GICNrm = 1 > GPFNrm - self.GICNrm = GICNrm - - if GICRaw: - solution = self.add_mNrmStE(solution) # find steady state m, if it exists - if GICNrm: - solution = self.add_mNrmTrg(solution) # find target m, if it exists - - return solution - - def make_linear_cFunc(self, mNrm, cNrm): - """ - Makes a linear interpolation to represent the (unconstrained) consumption function. - - Parameters - ---------- - mNrm : np.array - Corresponding market resource points for interpolation. - cNrm : np.array - Consumption points for interpolation. - - Returns - ------- - cFuncUnc : LinearInterp - The unconstrained consumption function for this period. - """ - cFuncUnc = LinearInterp( - mNrm, cNrm, self.cFuncLimitIntercept, self.cFuncLimitSlope - ) - return cFuncUnc - - def solve(self): - """ - Solves a one period consumption saving problem with risky income. - - Parameters - ---------- - None - - Returns - ------- - solution : ConsumerSolution - The solution to the one period problem. - """ - self.aNrmNow = np.asarray(self.aXtraGrid) + self.BoroCnstNat - aNrm = self.aNrmNow - EndOfPrdvP = self.calc_EndOfPrdvP() - solution = self.make_basic_solution(EndOfPrdvP, aNrm, self.make_linear_cFunc) - solution = self.add_MPC_and_human_wealth(solution) - solution = self.add_stable_points(solution) - - return solution - - -############################################################################### -############################################################################### - - -class ConsIndShockSolver(ConsIndShockSolverBasic): - """ - This class solves a single period of a standard consumption-saving problem. - It inherits from ConsIndShockSolverBasic, adding the ability to perform cubic - interpolation and to calculate the value function. - """ - - def make_cubic_cFunc(self, mNrm, cNrm): - """ - Makes a cubic spline interpolation of the unconstrained consumption - function for this period. - - Parameters - ---------- - mNrm : np.array - Corresponding market resource points for interpolation. - cNrm : np.array - Consumption points for interpolation. - - Returns - ------- - cFuncUnc : CubicInterp - The unconstrained consumption function for this period. - """ - def vpp_next(shocks, a_nrm): - return shocks[0] ** (- self.CRRA - 1.0) \ - * self.vPPfuncNext(self.m_nrm_next(shocks, a_nrm)) - - EndOfPrdvPP = ( - self.DiscFacEff - * self.Rfree - * self.Rfree - * self.PermGroFac ** (-self.CRRA - 1.0) - * calc_expectation( - self.IncShkDstn, - vpp_next, - self.aNrmNow - ) - ) - dcda = EndOfPrdvPP / self.uPP(np.array(cNrm[1:])) - MPC = dcda / (dcda + 1.0) - MPC = np.insert(MPC, 0, self.MPCmaxNow) - - cFuncNowUnc = CubicInterp( - mNrm, cNrm, MPC, self.MPCminNow * self.hNrmNow, self.MPCminNow - ) - return cFuncNowUnc - - def make_EndOfPrdvFunc(self, EndOfPrdvP): - """ - Construct the end-of-period value function for this period, storing it - as an attribute of self for use by other methods. - - Parameters - ---------- - EndOfPrdvP : np.array - Array of end-of-period marginal value of assets corresponding to the - asset values in self.aNrmNow. - - Returns - ------- - none - """ - def v_lvl_next(shocks, a_nrm): - return ( - shocks[0] ** (1.0 - self.CRRA) - * self.PermGroFac ** (1.0 - self.CRRA) - ) * self.vFuncNext(self.m_nrm_next(shocks, a_nrm)) - EndOfPrdv = self.DiscFacEff * calc_expectation( - self.IncShkDstn, v_lvl_next, self.aNrmNow - ) - EndOfPrdvNvrs = self.uinv( - EndOfPrdv - ) # value transformed through inverse utility - EndOfPrdvNvrsP = EndOfPrdvP * self.uinvP(EndOfPrdv) - EndOfPrdvNvrs = np.insert(EndOfPrdvNvrs, 0, 0.0) - EndOfPrdvNvrsP = np.insert( - EndOfPrdvNvrsP, 0, EndOfPrdvNvrsP[0] - ) # This is a very good approximation, vNvrsPP = 0 at the asset minimum - aNrm_temp = np.insert(self.aNrmNow, 0, self.BoroCnstNat) - EndOfPrdvNvrsFunc = CubicInterp(aNrm_temp, EndOfPrdvNvrs, EndOfPrdvNvrsP) - self.EndOfPrdvFunc = ValueFuncCRRA(EndOfPrdvNvrsFunc, self.CRRA) - - def add_vFunc(self, solution, EndOfPrdvP): - """ - Creates the value function for this period and adds it to the solution. - - Parameters - ---------- - solution : ConsumerSolution - The solution to this single period problem, likely including the - consumption function, marginal value function, etc. - EndOfPrdvP : np.array - Array of end-of-period marginal value of assets corresponding to the - asset values in self.aNrmNow. - - Returns - ------- - solution : ConsumerSolution - The single period solution passed as an input, but now with the - value function (defined over market resources m) as an attribute. - """ - self.make_EndOfPrdvFunc(EndOfPrdvP) - solution.vFunc = self.make_vFunc(solution) - return solution - - def make_vFunc(self, solution): - """ - Creates the value function for this period, defined over market resources m. - self must have the attribute EndOfPrdvFunc in order to execute. - - Parameters - ---------- - solution : ConsumerSolution - The solution to this single period problem, which must include the - consumption function. - - Returns - ------- - vFuncNow : ValueFuncCRRA - A representation of the value function for this period, defined over - normalized market resources m: v = vFuncNow(m). - """ - # Compute expected value and marginal value on a grid of market resources - mNrm_temp = self.mNrmMinNow + self.aXtraGrid - cNrmNow = solution.cFunc(mNrm_temp) - aNrmNow = mNrm_temp - cNrmNow - vNrmNow = self.u(cNrmNow) + self.EndOfPrdvFunc(aNrmNow) - vPnow = self.uP(cNrmNow) - - # Construct the beginning-of-period value function - vNvrs = self.uinv(vNrmNow) # value transformed through inverse utility - vNvrsP = vPnow * self.uinvP(vNrmNow) - mNrm_temp = np.insert(mNrm_temp, 0, self.mNrmMinNow) - vNvrs = np.insert(vNvrs, 0, 0.0) - vNvrsP = np.insert( - vNvrsP, 0, self.MPCmaxEff ** (-self.CRRA / (1.0 - self.CRRA)) - ) - MPCminNvrs = self.MPCminNow ** (-self.CRRA / (1.0 - self.CRRA)) - vNvrsFuncNow = CubicInterp( - mNrm_temp, vNvrs, vNvrsP, MPCminNvrs * self.hNrmNow, MPCminNvrs - ) - vFuncNow = ValueFuncCRRA(vNvrsFuncNow, self.CRRA) - return vFuncNow - - def add_vPPfunc(self, solution): - """ - Adds the marginal marginal value function to an existing solution, so - that the next solver can evaluate vPP and thus use cubic interpolation. - - Parameters - ---------- - solution : ConsumerSolution - The solution to this single period problem, which must include the - consumption function. - - Returns - ------- - solution : ConsumerSolution - The same solution passed as input, but with the marginal marginal - value function for this period added as the attribute vPPfunc. - """ - vPPfuncNow = MargMargValueFuncCRRA(solution.cFunc, self.CRRA) - solution.vPPfunc = vPPfuncNow - return solution - - def solve(self): - """ - Solves the single period consumption-saving problem using the method of - endogenous gridpoints. Solution includes a consumption function cFunc - (using cubic or linear splines), a marginal value function vPfunc, a min- - imum acceptable level of normalized market resources mNrmMin, normalized - human wealth hNrm, and bounding MPCs MPCmin and MPCmax. It might also - have a value function vFunc and marginal marginal value function vPPfunc. - - Parameters - ---------- - none - - Returns - ------- - solution : ConsumerSolution - The solution to the single period consumption-saving problem. - """ - # Make arrays of end-of-period assets and end-of-period marginal value - aNrm = self.prepare_to_calc_EndOfPrdvP() - EndOfPrdvP = self.calc_EndOfPrdvP() - - # Construct a basic solution for this period - if self.CubicBool: - solution = self.make_basic_solution( - EndOfPrdvP, aNrm, interpolator=self.make_cubic_cFunc - ) - else: - solution = self.make_basic_solution( - EndOfPrdvP, aNrm, interpolator=self.make_linear_cFunc - ) - - solution = self.add_MPC_and_human_wealth(solution) # add a few things - solution = self.add_stable_points(solution) - - # Add the value function if requested, as well as the marginal marginal - # value function if cubic splines were used (to prepare for next period) - if self.vFuncBool: - solution = self.add_vFunc(solution, EndOfPrdvP) - if self.CubicBool: - solution = self.add_vPPfunc(solution) - return solution - - -#################################################################################################### -#################################################################################################### - - -class ConsKinkedRsolver(ConsIndShockSolver): - """ - A class to solve a single period consumption-saving problem where the interest - rate on debt differs from the interest rate on savings. Inherits from - ConsIndShockSolver, with nearly identical inputs and outputs. The key diff- - erence is that Rfree is replaced by Rsave (a>0) and Rboro (a<0). The solver - can handle Rboro == Rsave, which makes it identical to ConsIndShocksolver, but - it terminates immediately if Rboro < Rsave, as this has a different solution. - - Parameters - ---------- - solution_next : ConsumerSolution - The solution to next period's one period problem. - IncShkDstn : distribution.Distribution - A discrete - approximation to the income process between the period being solved - and the one immediately following (in solution_next). - LivPrb : float - Survival probability; likelihood of being alive at the beginning of - the succeeding period. - DiscFac : float - Intertemporal discount factor for future utility. - CRRA : float - Coefficient of relative risk aversion. - Rboro: float - Interest factor on assets between this period and the succeeding - period when assets are negative. - Rsave: float - Interest factor on assets between this period and the succeeding - period when assets are positive. - PermGroFac : float - Expected permanent income growth factor at the end of this period. - BoroCnstArt: float or None - Borrowing constraint for the minimum allowable assets to end the - period with. If it is less than the natural borrowing constraint, - then it is irrelevant; BoroCnstArt=None indicates no artificial bor- - rowing constraint. - aXtraGrid: np.array - Array of "extra" end-of-period asset values-- assets above the - absolute minimum acceptable level. - vFuncBool: boolean - An indicator for whether the value function should be computed and - included in the reported solution. - CubicBool: boolean - An indicator for whether the solver should use cubic or linear inter- - polation. - """ - - def __init__( - self, - solution_next, - IncShkDstn, - LivPrb, - DiscFac, - CRRA, - Rboro, - Rsave, - PermGroFac, - BoroCnstArt, - aXtraGrid, - vFuncBool, - CubicBool, - ): - assert ( - Rboro >= Rsave - ), "Interest factor on debt less than interest factor on savings!" - - # Initialize the solver. Most of the steps are exactly the same as in - # the non-kinked-R basic case, so start with that. - ConsIndShockSolver.__init__( - self, - solution_next, - IncShkDstn, - LivPrb, - DiscFac, - CRRA, - Rboro, - PermGroFac, - BoroCnstArt, - aXtraGrid, - vFuncBool, - CubicBool, - ) - - # Assign the interest rates as class attributes, to use them later. - self.Rboro = Rboro - self.Rsave = Rsave - - def make_cubic_cFunc(self, mNrm, cNrm): - """ - Makes a cubic spline interpolation that contains the kink of the unconstrained - consumption function for this period. - - Parameters - ---------- - mNrm : np.array - Corresponding market resource points for interpolation. - cNrm : np.array - Consumption points for interpolation. - - Returns - ------- - cFuncUnc : CubicInterp - The unconstrained consumption function for this period. - """ - # Call the make_cubic_cFunc from ConsIndShockSolver. - cFuncNowUncKink = super().make_cubic_cFunc(mNrm, cNrm) - - # Change the coeffients at the kinked points. - cFuncNowUncKink.coeffs[self.i_kink + 1] = [ - cNrm[self.i_kink], - mNrm[self.i_kink + 1] - mNrm[self.i_kink], - 0, - 0, - ] - - return cFuncNowUncKink - - def add_stable_points(self, solution): - """ - TODO: - Placeholder method for a possible future implementation of stable - points in the kinked R model. For now it simply serves to override - ConsIndShock's method, which does not apply here given the multiple - interest rates. - - Discusson: - - The target and steady state should exist under the same conditions - as in ConsIndShock. - - The ConsIndShock code as it stands can not be directly applied - because it assumes that R is a constant, and in this model R depends - on the level of wealth. - - After allowing for wealth-depending interest rates, the existing - code might work without modification to add the stable points. If not, - it should be possible to find these values by checking within three - distinct intervals: - - From h_min to the lower kink. - - From the lower kink to the upper kink - - From the upper kink to infinity. - the stable points must be in one of these regions. - - """ - return solution - - def prepare_to_calc_EndOfPrdvP(self): - """ - Prepare to calculate end-of-period marginal value by creating an array - of market resources that the agent could have next period, considering - the grid of end-of-period assets and the distribution of shocks he might - experience next period. This differs from the baseline case because - different savings choices yield different interest rates. - - Parameters - ---------- - none - - Returns - ------- - aNrmNow : np.array - A 1D array of end-of-period assets; also stored as attribute of self. - """ - KinkBool = ( - self.Rboro > self.Rsave - ) # Boolean indicating that there is actually a kink. - # When Rboro == Rsave, this method acts just like it did in IndShock. - # When Rboro < Rsave, the solver would have terminated when it was called. - - # Make a grid of end-of-period assets, including *two* copies of a=0 - if KinkBool: - aNrmNow = np.sort( - np.hstack( - (np.asarray(self.aXtraGrid) + self.mNrmMinNow, np.array([0.0, 0.0])) - ) - ) - else: - aNrmNow = np.asarray(self.aXtraGrid) + self.mNrmMinNow - aXtraCount = aNrmNow.size - - # Make tiled versions of the assets grid and income shocks - ShkCount = self.TranShkValsNext.size - aNrm_temp = np.tile(aNrmNow, (ShkCount, 1)) - PermShkVals_temp = (np.tile(self.PermShkValsNext, (aXtraCount, 1))).transpose() - TranShkVals_temp = (np.tile(self.TranShkValsNext, (aXtraCount, 1))).transpose() - ShkPrbs_temp = (np.tile(self.ShkPrbsNext, (aXtraCount, 1))).transpose() - - # Make a 1D array of the interest factor at each asset gridpoint - Rfree_vec = self.Rsave * np.ones(aXtraCount) - if KinkBool: - self.i_kink = ( - np.sum(aNrmNow <= 0) - 1 - ) # Save the index of the kink point as an attribute - Rfree_vec[0: self.i_kink] = self.Rboro - self.Rfree = Rfree_vec - Rfree_temp = np.tile(Rfree_vec, (ShkCount, 1)) - - # Make an array of market resources that we could have next period, - # considering the grid of assets and the income shocks that could occur - mNrmNext = ( - Rfree_temp / (self.PermGroFac * PermShkVals_temp) * aNrm_temp - + TranShkVals_temp - ) - - # Recalculate the minimum MPC and human wealth using the interest factor on saving. - # This overwrites values from set_and_update_values, which were based on Rboro instead. - if KinkBool: - PatFacTop = ( - (self.Rsave * self.DiscFacEff) ** (1.0 / self.CRRA) - ) / self.Rsave - self.MPCminNow = 1.0 / (1.0 + PatFacTop / self.solution_next.MPCmin) - self.hNrmNow = ( - self.PermGroFac - / self.Rsave - * ( - np.dot( - self.ShkPrbsNext, self.TranShkValsNext * self.PermShkValsNext - ) - + self.solution_next.hNrm - ) - ) - - # Store some of the constructed arrays for later use and return the assets grid - self.PermShkVals_temp = PermShkVals_temp - self.ShkPrbs_temp = ShkPrbs_temp - self.mNrmNext = mNrmNext - self.aNrmNow = aNrmNow - return aNrmNow - - -# ============================================================================ -# == Classes for representing types of consumer agents (and things they do) == -# ============================================================================ - -# Make a dictionary to specify a perfect foresight consumer type -init_perfect_foresight = { - 'cycles' : 1, # Finite, non-cyclic model - 'CRRA': 2.0, # Coefficient of relative risk aversion, - 'Rfree': 1.03, # Interest factor on assets - 'DiscFac': 0.96, # Intertemporal discount factor - 'LivPrb': [0.98], # Survival probability - 'PermGroFac': [1.01], # Permanent income growth factor - 'BoroCnstArt': None, # Artificial borrowing constraint - 'MaxKinks': 400, # Maximum number of grid points to allow in cFunc (should be large) - 'AgentCount': 10000, # Number of agents of this type (only matters for simulation) - 'aNrmInitMean': 0.0, # Mean of log initial assets (only matters for simulation) - 'aNrmInitStd': 1.0, # Standard deviation of log initial assets (only for simulation) - 'pLvlInitMean': 0.0, # Mean of log initial permanent income (only matters for simulation) - # Standard deviation of log initial permanent income (only matters for simulation) - 'pLvlInitStd': 0.0, - # Aggregate permanent income growth factor: portion of PermGroFac attributable to aggregate productivity growth (only matters for simulation) - 'PermGroFacAgg': 1.0, - 'T_age': None, # Age after which simulated agents are automatically killed - 'T_cycle': 1, # Number of periods in the cycle for this agent type - "PerfMITShk": False # Do Perfect Foresight MIT Shock: Forces Newborns to follow solution path of the agent he/she replaced when True -} - - -class PerfForesightConsumerType(AgentType): - """ - A perfect foresight consumer type who has no uncertainty other than mortality. - His problem is defined by a coefficient of relative risk aversion, intertemporal - discount factor, interest factor, an artificial borrowing constraint (maybe) - and time sequences of the permanent income growth rate and survival probability. - - Parameters - ---------- - - """ - - # Define some universal values for all consumer types - cFunc_terminal_ = LinearInterp([0.0, 1.0], [0.0, 1.0]) # c=m in terminal period - vFunc_terminal_ = LinearInterp([0.0, 1.0], [0.0, 0.0]) # This is overwritten - solution_terminal_ = ConsumerSolution( - cFunc=cFunc_terminal_, - vFunc=vFunc_terminal_, - mNrmMin=0.0, - hNrm=0.0, - MPCmin=1.0, - MPCmax=1.0, - ) - time_vary_ = ["LivPrb", "PermGroFac"] - time_inv_ = ["CRRA", "Rfree", "DiscFac", "MaxKinks", "BoroCnstArt" ] - state_vars = ['pLvl', 'PlvlAgg', 'bNrm', 'mNrm', "aNrm"] - shock_vars_ = [] - - def __init__(self, verbose=1, quiet=False, **kwds): - params = init_perfect_foresight.copy() - params.update(kwds) - kwds = params - - # Initialize a basic AgentType - AgentType.__init__( - self, - solution_terminal=deepcopy(self.solution_terminal_), - pseudo_terminal=False, - **kwds - ) - - # Add consumer-type specific objects, copying to create independent versions - self.time_vary = deepcopy(self.time_vary_) - self.time_inv = deepcopy(self.time_inv_) - - self.shock_vars = deepcopy(self.shock_vars_) - self.verbose = verbose - self.quiet = quiet - self.solve_one_period = make_one_period_oo_solver(ConsPerfForesightSolver) - set_verbosity_level((4 - verbose) * 10) - - def pre_solve(self): - self.update_solution_terminal() # Solve the terminal period problem - - # Fill in BoroCnstArt and MaxKinks if they're not specified or are irrelevant. - if not hasattr(self, "BoroCnstArt"): # If no borrowing constraint specified... - self.BoroCnstArt = None # ...assume the user wanted none - if not hasattr(self, "MaxKinks"): - if self.cycles > 0: # If it's not an infinite horizon model... - self.MaxKinks = np.inf # ...there's no need to set MaxKinks - elif self.BoroCnstArt is None: # If there's no borrowing constraint... - self.MaxKinks = np.inf # ...there's no need to set MaxKinks - else: - raise ( - AttributeError( - "PerfForesightConsumerType requires the attribute MaxKinks to be specified when BoroCnstArt is not None and cycles == 0." - ) - ) - - def check_restrictions(self): - """ - A method to check that various restrictions are met for the model class. - """ - if self.DiscFac < 0: - raise Exception("DiscFac is below zero with value: " + str(self.DiscFac)) - - return - - def update_solution_terminal(self): - """ - Update the terminal period solution. This method should be run when a - new AgentType is created or when CRRA changes. - - Parameters - ---------- - none - - Returns - ------- - none - """ - self.solution_terminal.vFunc = ValueFuncCRRA(self.cFunc_terminal_, self.CRRA) - self.solution_terminal.vPfunc = MargValueFuncCRRA(self.cFunc_terminal_, self.CRRA) - self.solution_terminal.vPPfunc = MargMargValueFuncCRRA( - self.cFunc_terminal_, self.CRRA - ) - - def unpack_cFunc(self): - """ DEPRECATED: Use solution.unpack('cFunc') instead. - "Unpacks" the consumption functions into their own field for easier access. - After the model has been solved, the consumption functions reside in the - attribute cFunc of each element of ConsumerType.solution. This method - creates a (time varying) attribute cFunc that contains a list of consumption - functions. - Parameters - ---------- - none - Returns - ------- - none - """ - _log.critical( - "unpack_cFunc is deprecated and it will soon be removed, " - "please use unpack('cFunc') instead." - ) - self.unpack("cFunc") - - def initialize_sim(self): - self.PermShkAggNow = self.PermGroFacAgg # This never changes during simulation - self.state_now['PlvlAgg'] = 1.0 - AgentType.initialize_sim(self) - - def sim_birth(self, which_agents): - """ - Makes new consumers for the given indices. Initialized variables include aNrm and pLvl, as - well as time variables t_age and t_cycle. Normalized assets and permanent income levels - are drawn from lognormal distributions given by aNrmInitMean and aNrmInitStd (etc). - - Parameters - ---------- - which_agents : np.array(Bool) - Boolean array of size self.AgentCount indicating which agents should be "born". - - Returns - ------- - None - """ - # Get and store states for newly born agents - N = np.sum(which_agents) # Number of new consumers to make - self.state_now['aNrm'][which_agents] = Lognormal( - mu=self.aNrmInitMean, - sigma=self.aNrmInitStd, - seed=self.RNG.randint(0, 2 ** 31 - 1), - ).draw(N) - # why is a now variable set here? Because it's an aggregate. - pLvlInitMeanNow = self.pLvlInitMean + np.log( - self.state_now['PlvlAgg'] - ) # Account for newer cohorts having higher permanent income - self.state_now['pLvl'][which_agents] = Lognormal( - pLvlInitMeanNow, - self.pLvlInitStd, - seed=self.RNG.randint(0, 2 ** 31 - 1) - ).draw(N) - self.t_age[which_agents] = 0 # How many periods since each agent was born - if self.PerfMITShk == False: # If True, Newborns inherit t_cycle of agent they replaced (i.e. t_cycles are not reset). - self.t_cycle[ - which_agents - ] = 0 # Which period of the cycle each agent is currently in - - return None - - def sim_death(self): - """ - Determines which agents die this period and must be replaced. Uses the sequence in LivPrb - to determine survival probabilities for each agent. - - Parameters - ---------- - None - - Returns - ------- - which_agents : np.array(bool) - Boolean array of size AgentCount indicating which agents die. - """ - # Determine who dies - DiePrb_by_t_cycle = 1.0 - np.asarray(self.LivPrb) - DiePrb = DiePrb_by_t_cycle[ - self.t_cycle - 1 - ] # Time has already advanced, so look back one - - # In finite-horizon problems the previous line gives newborns the - # survival probability of the last non-terminal period. This is okay, - # however, since they will be instantly replaced by new newborns if - # they die. - # See: https://github.com/econ-ark/HARK/pull/981 - - DeathShks = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw( - N=self.AgentCount - ) - which_agents = DeathShks < DiePrb - if self.T_age is not None: # Kill agents that have lived for too many periods - too_old = self.t_age >= self.T_age - which_agents = np.logical_or(which_agents, too_old) - return which_agents - - def get_shocks(self): - """ - Finds permanent and transitory income "shocks" for each agent this period. As this is a - perfect foresight model, there are no stochastic shocks: PermShkNow = PermGroFac for each - agent (according to their t_cycle) and TranShkNow = 1.0 for all agents. - - Parameters - ---------- - None - - Returns - ------- - None - """ - PermGroFac = np.array(self.PermGroFac) - self.shocks['PermShk'] = PermGroFac[ - self.t_cycle - 1 - ] # cycle time has already been advanced - self.shocks['TranShk'] = np.ones(self.AgentCount) - - def get_Rfree(self): - """ - Returns an array of size self.AgentCount with self.Rfree in every entry. - - Parameters - ---------- - None - - Returns - ------- - RfreeNow : np.array - Array of size self.AgentCount with risk free interest rate for each agent. - """ - RfreeNow = self.Rfree * np.ones(self.AgentCount) - return RfreeNow - - def transition(self): - pLvlPrev = self.state_prev['pLvl'] - aNrmPrev = self.state_prev['aNrm'] - RfreeNow = self.get_Rfree() - - # Calculate new states: normalized market resources and permanent income level - pLvlNow = pLvlPrev*self.shocks['PermShk'] # Updated permanent income level - # Updated aggregate permanent productivity level - PlvlAggNow = self.state_prev['PlvlAgg']*self.PermShkAggNow - # "Effective" interest factor on normalized assets - ReffNow = RfreeNow/self.shocks['PermShk'] - bNrmNow = ReffNow*aNrmPrev # Bank balances before labor income - mNrmNow = bNrmNow + self.shocks['TranShk'] # Market resources after income - - return pLvlNow, PlvlAggNow, bNrmNow, mNrmNow, None - - def get_controls(self): - """ - Calculates consumption for each consumer of this type using the consumption functions. - - Parameters - ---------- - None - - Returns - ------- - None - """ - cNrmNow = np.zeros(self.AgentCount) + np.nan - MPCnow = np.zeros(self.AgentCount) + np.nan - for t in range(self.T_cycle): - these = t == self.t_cycle - cNrmNow[these], MPCnow[these] = self.solution[t].cFunc.eval_with_derivative( - self.state_now['mNrm'][these] - ) - self.controls['cNrm'] = cNrmNow - - # MPCnow is not really a control - self.MPCnow = MPCnow - return None - - def get_poststates(self): - """ - Calculates end-of-period assets for each consumer of this type. - - Parameters - ---------- - None - - Returns - ------- - None - """ - # should this be "Now", or "Prev"?!? - self.state_now['aNrm'] = self.state_now['mNrm'] - self.controls['cNrm'] - # Useful in some cases to precalculate asset level - self.state_now['aLvl'] = self.state_now['aNrm'] * self.state_now['pLvl'] - - # moves now to prev - super().get_poststates() - - return None - - def check_condition(self, name, test, messages, verbose, verbose_messages=None): - """ - Checks one condition. - - Parameters - ---------- - name : string - Name for the condition. - - test : function(self -> boolean) - A function (of self) which tests the condition - - messages : dict{boolean : string} - A dictiomary with boolean keys containing values - for messages to print if the condition is - true or false. - - verbose_messages : dict{boolean : string} - (Optional) A dictiomary with boolean keys containing values - for messages to print if the condition is - true or false under verbose printing. - """ - self.conditions[name] = test(self) - set_verbosity_level((4 - verbose) * 10) - _log.info(messages[self.conditions[name]].format(self)) - if verbose_messages: - _log.debug(verbose_messages[self.conditions[name]].format(self)) - - def check_AIC(self, verbose=None): - """ - Evaluate and report on the Absolute Impatience Condition - """ - name = "AIC" - def test(agent): return agent.thorn < 1 - - messages = { - True: "The value of the Absolute Patience Factor (APF) for the supplied parameter values satisfies the Absolute Impatience Condition.", - False: "The given type violates the Absolute Impatience Condition with the supplied parameter values; the APF is {0.thorn}", - } - verbose_messages = { - True: " Because the APF < 1, the absolute amount of consumption is expected to fall over time.", - False: " Because the APF > 1, the absolute amount of consumption is expected to grow over time.", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_GICRaw(self, verbose=None): - """ - Evaluate and report on the Growth Impatience Condition for the Perfect Foresight model - """ - name = "GICRaw" - - self.GPFRaw = self.thorn / self.PermGroFac[0] - - def test(agent): return agent.GPFRaw < 1 - - messages = { - True: "The value of the Growth Patience Factor for the supplied parameter values satisfies the Perfect Foresight Growth Impatience Condition.", - False: "The value of the Growth Patience Factor for the supplied parameter values fails the Perfect Foresight Growth Impatience Condition; the GPFRaw is: {0.GPFRaw}", - } - - verbose_messages = { - True: " Therefore, for a perfect foresight consumer, the ratio of individual wealth to permanent income will fall indefinitely.", - False: " Therefore, for a perfect foresight consumer, the ratio of individual wealth to permanent income is expected to grow toward infinity.", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_RIC(self, verbose=None): - """ - Evaluate and report on the Return Impatience Condition - """ - - self.RPF = self.thorn / self.Rfree - - name = "RIC" - def test(agent): return self.RPF < 1 - - messages = { - True: "The value of the Return Patience Factor for the supplied parameter values satisfies the Return Impatience Condition.", - False: "The value of the Return Patience Factor for the supplied parameter values fails the Return Impatience Condition; the factor is {0.RPF}", - } - - verbose_messages = { - True: " Therefore, the limiting consumption function is not c(m)=0 for all m", - False: " Therefore, if the FHWC is satisfied, the limiting consumption function is c(m)=0 for all m.", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_FHWC(self, verbose=None): - """ - Evaluate and report on the Finite Human Wealth Condition - """ - - self.FHWF = self.PermGroFac[0] / self.Rfree - self.cNrmPDV = 1.0 / (1.0 - self.thorn / self.Rfree) - - name = "FHWC" - def test(agent): return self.FHWF < 1 - - messages = { - True: "The Finite Human wealth factor value for the supplied parameter values satisfies the Finite Human Wealth Condition.", - False: "The given type violates the Finite Human Wealth Condition; the Finite Human wealth factor value is {0.FHWF}", - } - - verbose_messages = { - True: " Therefore, the limiting consumption function is not c(m)=Infinity\nand human wealth normalized by permanent income is {0.hNrm}\nand the PDV of future consumption growth is {0.cNrmPDV}", - False: " Therefore, the limiting consumption function is c(m)=Infinity for all m unless the RIC is also violated. If both FHWC and RIC fail and the consumer faces a liquidity constraint, the limiting consumption function is nondegenerate but has a limiting slope of 0. (https://econ-ark.github.io/BufferStockTheory#PFGICRawHoldsFHWCFailsRICFailsDiscuss)", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose) - - def check_conditions(self, verbose=None): - """ - This method checks whether the instance's type satisfies the - Absolute Impatience Condition (AIC), - the Return Impatience Condition (RIC), - the Finite Human Wealth Condition (FHWC), the perfect foresight - model's Growth Impatience Condition (GICRaw) and - Perfect Foresight Finite Value of Autarky Condition (FVACPF). Depending on the configuration of parameter values, some - combination of these conditions must be satisfied in order for the problem to have - a nondegenerate solution. To check which conditions are required, in the verbose mode - a reference to the relevant theoretical literature is made. - - - Parameters - ---------- - verbose : boolean - Specifies different levels of verbosity of feedback. When False, it only reports whether the - instance's type fails to satisfy a particular condition. When True, it reports all results, i.e. - the factor values for all conditions. - - Returns - ------- - None - """ - self.conditions = {} - - self.violated = False - - # This method only checks for the conditions for infinite horizon models - # with a 1 period cycle. If these conditions are not met, we exit early. - if self.cycles != 0 or self.T_cycle > 1: - return - - self.thorn = (self.Rfree * self.DiscFac * self.LivPrb[0]) ** (1 / self.CRRA) - - verbose = self.verbose if verbose is None else verbose - self.check_AIC(verbose) - self.check_GICRaw(verbose) - self.check_RIC(verbose) - self.check_FHWC(verbose) - - if hasattr(self, "BoroCnstArt") and self.BoroCnstArt is not None: - self.violated = not self.conditions["RIC"] - else: - self.violated = not self.conditions["RIC"] or not self.conditions["FHWC"] - - -# Make a dictionary to specify an idiosyncratic income shocks consumer -init_idiosyncratic_shocks = dict( - init_perfect_foresight, - **{ - # assets above grid parameters - "aXtraMin": 0.001, # Minimum end-of-period "assets above minimum" value - "aXtraMax": 20, # Maximum end-of-period "assets above minimum" value - "aXtraNestFac": 3, # Exponential nesting factor when constructing "assets above minimum" grid - "aXtraCount": 48, # Number of points in the grid of "assets above minimum" - "aXtraExtra": [ - None - ], # Some other value of "assets above minimum" to add to the grid, not used - # Income process variables - "PermShkStd": [0.1], # Standard deviation of log permanent income shocks - "PermShkCount": 7, # Number of points in discrete approximation to permanent income shocks - "TranShkStd": [0.1], # Standard deviation of log transitory income shocks - "TranShkCount": 7, # Number of points in discrete approximation to transitory income shocks - "UnempPrb": 0.05, # Probability of unemployment while working - "UnempPrbRet": 0.005, # Probability of "unemployment" while retired - "IncUnemp": 0.3, # Unemployment benefits replacement rate - "IncUnempRet": 0.0, # "Unemployment" benefits when retired - "BoroCnstArt": 0.0, # Artificial borrowing constraint; imposed minimum level of end-of period assets - "tax_rate": 0.0, # Flat income tax rate - "T_retire": 0, # Period of retirement (0 --> no retirement) - "vFuncBool": False, # Whether to calculate the value function during solution - "CubicBool": False, # Use cubic spline interpolation when True, linear interpolation when False - } -) - - -class IndShockConsumerType(PerfForesightConsumerType): - """ - A consumer type with idiosyncratic shocks to permanent and transitory income. - His problem is defined by a sequence of income distributions, survival prob- - abilities, and permanent income growth rates, as well as time invariant values - for risk aversion, discount factor, the interest rate, the grid of end-of- - period assets, and an artificial borrowing constraint. - - Parameters - ---------- - cycles : int - Number of times the sequence of periods should be solved. - """ - - time_inv_ = PerfForesightConsumerType.time_inv_ + [ - "BoroCnstArt", - "vFuncBool", - "CubicBool", - ] - time_inv_.remove( - "MaxKinks" - ) # This is in the PerfForesight model but not ConsIndShock - shock_vars_ = ['PermShk', 'TranShk'] - - def __init__(self, verbose=1, quiet=False, **kwds): - params = init_idiosyncratic_shocks.copy() - params.update(kwds) - - # Initialize a basic AgentType - PerfForesightConsumerType.__init__( - self, verbose=verbose, quiet=quiet, **params - ) - - # Add consumer-type specific objects, copying to create independent versions - if (not self.CubicBool) and (not self.vFuncBool): - solver = ConsIndShockSolverBasic - else: # Use the "advanced" solver if either is requested - solver = ConsIndShockSolver - self.solve_one_period = make_one_period_oo_solver(solver) - - self.update() # Make assets grid, income process, terminal solution - - def update_income_process(self): - """ - Updates this agent's income process based on his own attributes. - - Parameters - ---------- - none - - Returns: - ----------- - none - """ - ( - IncShkDstn, - PermShkDstn, - TranShkDstn, - ) = self.construct_lognormal_income_process_unemployment() - self.IncShkDstn = IncShkDstn - self.PermShkDstn = PermShkDstn - self.TranShkDstn = TranShkDstn - self.add_to_time_vary("IncShkDstn", "PermShkDstn", "TranShkDstn") - - def update_assets_grid(self): - """ - Updates this agent's end-of-period assets grid by constructing a multi- - exponentially spaced grid of aXtra values. - - Parameters - ---------- - none - - Returns - ------- - none - """ - aXtraGrid = construct_assets_grid(self) - self.aXtraGrid = aXtraGrid - self.add_to_time_inv("aXtraGrid") - - def update(self): - """ - Update the income process, the assets grid, and the terminal solution. - - Parameters - ---------- - None - - Returns - ------- - None - """ - self.update_income_process() - self.update_assets_grid() - self.update_solution_terminal() - - def reset_rng(self): - """ - Reset the RNG behavior of this type. This method is called automatically - by initialize_sim(), ensuring that each simulation run uses the same sequence - of random shocks; this is necessary for structural estimation to work. - This method extends AgentType.reset_rng() to also reset elements of IncShkDstn. - - Parameters - ---------- - None - - Returns - ------- - None - """ - PerfForesightConsumerType.reset_rng(self) - - # Reset IncShkDstn if it exists (it might not because reset_rng is called at init) - if hasattr(self, "IncShkDstn"): - for dstn in self.IncShkDstn: - dstn.reset() - - def get_shocks(self): - """ - Gets permanent and transitory income shocks for this period. Samples from IncShkDstn for - each period in the cycle. - - Parameters - ---------- - None - - Returns - ------- - None - """ - PermShkNow = np.zeros(self.AgentCount) # Initialize shock arrays - TranShkNow = np.zeros(self.AgentCount) - newborn = self.t_age == 0 - for t in range(self.T_cycle): - these = t == self.t_cycle - N = np.sum(these) - if N > 0: - IncShkDstnNow = self.IncShkDstn[ - t - 1 - ] # set current income distribution - PermGroFacNow = self.PermGroFac[t - 1] # and permanent growth factor - # Get random draws of income shocks from the discrete distribution - IncShks = IncShkDstnNow.draw(N) - - PermShkNow[these] = ( - IncShks[0, :] * PermGroFacNow - ) # permanent "shock" includes expected growth - TranShkNow[these] = IncShks[1, :] - - # That procedure used the *last* period in the sequence for newborns, but that's not right - # Redraw shocks for newborns, using the *first* period in the sequence. Approximation. - N = np.sum(newborn) - if N > 0: - these = newborn - IncShkDstnNow = self.IncShkDstn[0] # set current income distribution - PermGroFacNow = self.PermGroFac[0] # and permanent growth factor - - # Get random draws of income shocks from the discrete distribution - EventDraws = IncShkDstnNow.draw_events(N) - PermShkNow[these] = ( - IncShkDstnNow.X[0][EventDraws] * PermGroFacNow - ) # permanent "shock" includes expected growth - TranShkNow[these] = IncShkDstnNow.X[1][EventDraws] - # PermShkNow[newborn] = 1.0 - TranShkNow[newborn] = 1.0 - - # Store the shocks in self - self.EmpNow = np.ones(self.AgentCount, dtype=bool) - self.EmpNow[TranShkNow == self.IncUnemp] = False - self.shocks['PermShk'] = PermShkNow - self.shocks['TranShk'] = TranShkNow - - def calc_bounding_values(self): - """ - Calculate human wealth plus minimum and maximum MPC in an infinite - horizon model with only one period repeated indefinitely. Store results - as attributes of self. Human wealth is the present discounted value of - expected future income after receiving income this period, ignoring mort- - ality (because your income matters to you only if you are still alive). - The maximum MPC is the limit of the MPC as m --> mNrmMin. The - minimum MPC is the limit of the MPC as m --> infty. - - Parameters - ---------- - None - - Returns - ------- - None - """ - # Unpack the income distribution and get average and worst outcomes - PermShkValsNext = self.IncShkDstn[0][1] - TranShkValsNext = self.IncShkDstn[0][2] - ShkPrbsNext = self.IncShkDstn[0][0] - Ex_IncNext = np.dot(ShkPrbsNext, PermShkValsNext * TranShkValsNext) - PermShkMinNext = np.min(PermShkValsNext) - TranShkMinNext = np.min(TranShkValsNext) - WorstIncNext = PermShkMinNext * TranShkMinNext - WorstIncPrb = np.sum( - ShkPrbsNext[(PermShkValsNext * TranShkValsNext) == WorstIncNext] - ) - - # Calculate human wealth and the infinite horizon natural borrowing constraint - hNrm = (Ex_IncNext * self.PermGroFac[0] / self.Rfree) / ( - 1.0 - self.PermGroFac[0] / self.Rfree - ) - temp = self.PermGroFac[0] * PermShkMinNext / self.Rfree - BoroCnstNat = -TranShkMinNext * temp / (1.0 - temp) - - PatFac = (self.DiscFac * self.LivPrb[0] * self.Rfree) ** ( - 1.0 / self.CRRA - ) / self.Rfree - if BoroCnstNat < self.BoroCnstArt: - MPCmax = 1.0 # if natural borrowing constraint is overridden by artificial one, MPCmax is 1 - else: - MPCmax = 1.0 - WorstIncPrb ** (1.0 / self.CRRA) * PatFac - MPCmin = 1.0 - PatFac - - # Store the results as attributes of self - self.hNrm = hNrm - self.MPCmin = MPCmin - self.MPCmax = MPCmax - - def make_euler_error_func(self, mMax=100, approx_inc_dstn=True): - """ - Creates a "normalized Euler error" function for this instance, mapping - from market resources to "consumption error per dollar of consumption." - Stores result in attribute eulerErrorFunc as an interpolated function. - Has option to use approximate income distribution stored in self.IncShkDstn - or to use a (temporary) very dense approximation. - - Only works on (one period) infinite horizon models at this time, will - be generalized later. - - Parameters - ---------- - mMax : float - Maximum normalized market resources for the Euler error function. - approx_inc_dstn : Boolean - Indicator for whether to use the approximate discrete income distri- - bution stored in self.IncShkDstn[0], or to use a very accurate - discrete approximation instead. When True, uses approximation in - IncShkDstn; when False, makes and uses a very dense approximation. - - Returns - ------- - None - - Notes - ----- - This method is not used by any other code in the library. Rather, it is here - for expository and benchmarking purposes. - """ - # Get the income distribution (or make a very dense one) - if approx_inc_dstn: - IncShkDstn = self.IncShkDstn[0] - else: - TranShkDstn = MeanOneLogNormal(sigma=self.TranShkStd[0]).approx( - N=200, tail_N=50, tail_order=1.3, tail_bound=[0.05, 0.95] - ) - TranShkDstn = add_discrete_outcome_constant_mean( - TranShkDstn, self.UnempPrb, self.IncUnemp - ) - PermShkDstn = MeanOneLogNormal(sigma=self.PermShkStd[0]).approx( - N=200, tail_N=50, tail_order=1.3, tail_bound=[0.05, 0.95] - ) - IncShkDstn = combine_indep_dstns(PermShkDstn, TranShkDstn) - - # Make a grid of market resources - mNowMin = self.solution[0].mNrmMin + 10 ** ( - -15 - ) # add tiny bit to get around 0/0 problem - mNowMax = mMax - mNowGrid = np.linspace(mNowMin, mNowMax, 1000) - - # Get the consumption function this period and the marginal value function - # for next period. Note that this part assumes a one period cycle. - cFuncNow = self.solution[0].cFunc - vPfuncNext = self.solution[0].vPfunc - - # Calculate consumption this period at each gridpoint (and assets) - cNowGrid = cFuncNow(mNowGrid) - aNowGrid = mNowGrid - cNowGrid - - # Tile the grids for fast computation - ShkCount = IncShkDstn[0].size - aCount = aNowGrid.size - aNowGrid_tiled = np.tile(aNowGrid, (ShkCount, 1)) - PermShkVals_tiled = (np.tile(IncShkDstn[1], (aCount, 1))).transpose() - TranShkVals_tiled = (np.tile(IncShkDstn[2], (aCount, 1))).transpose() - ShkPrbs_tiled = (np.tile(IncShkDstn[0], (aCount, 1))).transpose() - - # Calculate marginal value next period for each gridpoint and each shock - mNextArray = ( - self.Rfree / (self.PermGroFac[0] * PermShkVals_tiled) * aNowGrid_tiled - + TranShkVals_tiled - ) - vPnextArray = vPfuncNext(mNextArray) - - # Calculate expected marginal value and implied optimal consumption - ExvPnextGrid = ( - self.DiscFac - * self.Rfree - * self.LivPrb[0] - * self.PermGroFac[0] ** (-self.CRRA) - * np.sum( - PermShkVals_tiled ** (-self.CRRA) * vPnextArray * ShkPrbs_tiled, axis=0 - ) - ) - cOptGrid = ExvPnextGrid ** ( - -1.0 / self.CRRA - ) # This is the 'Endogenous Gridpoints' step - - # Calculate Euler error and store an interpolated function - EulerErrorNrmGrid = (cNowGrid - cOptGrid) / cOptGrid - eulerErrorFunc = LinearInterp(mNowGrid, EulerErrorNrmGrid) - self.eulerErrorFunc = eulerErrorFunc - - def pre_solve(self): - # AgentType.pre_solve(self) - # Update all income process variables to match any attributes that might - # have been changed since `__init__` or `solve()` was last called. - # self.update_income_process() - self.update_solution_terminal() - if not self.quiet: - self.check_conditions(verbose=self.verbose) - - def check_GICNrm(self, verbose=None): - """ - Check Individual Growth Patience Factor. - """ - self.GPFNrm = self.thorn / ( - self.PermGroFac[0] * self.InvEx_PermShkInv - ) # [url]/#GICRawI - - name = "GICRaw" - def test(agent): return agent.GPFNrm <= 1 - - messages = { - True: "\nThe value of the Individual Growth Patience Factor for the supplied parameter values satisfies the Growth Impatience Condition; the value of the GPFNrm is: {0.GPFNrm}", - False: "\nThe given parameter values violate the Normalized Growth Impatience Condition; the GPFNrm is: {0.GPFNrm}", - } - - verbose_messages = { - True: " Therefore, a target level of the individual market resources ratio m exists (see {0.url}/#onetarget for more).\n", - False: " Therefore, a target ratio of individual market resources to individual permanent income does not exist. (see {0.url}/#onetarget for more).\n", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_GICAggLivPrb(self, verbose=None): - name = "GICAggLivPrb" - def test(agent): return agent.GPFAggLivPrb <= 1 - - messages = { - True: "\nThe value of the Mortality Adjusted Aggregate Growth Patience Factor for the supplied parameter values satisfies the Mortality Adjusted Aggregate Growth Imatience Condition; the value of the GPFAggLivPrb is: {0.GPFAggLivPrb}", - False: "\nThe given parameter values violate the Mortality Adjusted Aggregate Growth Imatience Condition; the GPFAggLivPrb is: {0.GPFAggLivPrb}", - } - - verbose_messages = { - # (see {0.url}/#WRIC for more).', - True: " Therefore, a target level of the ratio of aggregate market resources to aggregate permanent income exists.\n", - # (see {0.url}/#WRIC for more).' - False: " Therefore, a target ratio of aggregate resources to aggregate permanent income may not exist.\n", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_WRIC(self, verbose=None): - """ - Evaluate and report on the Weak Return Impatience Condition - [url]/#WRPF modified to incorporate LivPrb - """ - self.WRPF = ( - (self.UnempPrb ** (1 / self.CRRA)) - * (self.Rfree * self.DiscFac * self.LivPrb[0]) ** (1 / self.CRRA) - / self.Rfree - ) - - name = "WRIC" - def test(agent): return agent.WRPF <= 1 - - messages = { - True: "\nThe Weak Return Patience Factor value for the supplied parameter values satisfies the Weak Return Impatience Condition; the WRPF is {0.WRPF}.", - False: "\nThe Weak Return Patience Factor value for the supplied parameter values fails the Weak Return Impatience Condition; the WRPF is {0.WRPF} (see {0.url}/#WRIC for more).", - } - - verbose_messages = { - True: " Therefore, a nondegenerate solution exists if the FVAC is also satisfied. (see {0.url}/#WRIC for more) \n", - False: " Therefore, a nondegenerate solution is not available (see {0.url}/#WRIC for more). \n", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_FVAC(self, verbose=None): - """ - Evaluate and report on the Finite Value of Autarky Condition - Hyperlink to paper: [url]/#Autarky-Value - """ - EpShkuInv = calc_expectation( - self.PermShkDstn[0], - lambda x: x ** (1 - self.CRRA) - ) - - if self.CRRA != 1.0: - uInvEpShkuInv = EpShkuInv ** ( - 1 / (1 - self.CRRA) - ) # The term that gives a utility-consequence-adjusted utility growth - else: - uInvEpShkuInv = 1.0 - - self.uInvEpShkuInv = uInvEpShkuInv - - self.VAF = self.LivPrb[0] * self.DiscFac * self.uInvEpShkuInv - - name = "FVAC" - def test(agent): return agent.VAF <= 1 - - messages = { - True: "\nThe Value of Autarky Factor (VAF) for the supplied parameter values satisfies the Finite Value of Autarky Condition; the VAF is {0.VAF}", - False: "\nThe Value of Autarky Factor (VAF) for the supplied parameter values fails the Finite Value of Autarky Condition; the VAF is {0.VAF}", - } - - verbose_messages = { - True: " Therefore, a nondegenerate solution exists if the WRIC also holds; see {0.url}/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping\n", - False: " Therefore, a nondegenerate solution is not available (see {0.url}/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping\n", - } - verbose = self.verbose if verbose is None else verbose - self.check_condition(name, test, messages, verbose, verbose_messages) - - def check_conditions(self, verbose=None): - """ - This method checks whether the instance's type satisfies the Absolute Impatience Condition (AIC), Weak Return - Impatience Condition (WRIC), Finite Human Wealth Condition (FHWC) and Finite Value of - Autarky Condition (FVAC). When combinations of these conditions are satisfied, the - solution to the problem exhibits different characteristics. (For an exposition of the - conditions, see https://econ-ark.github.io/BufferStockTheory/) - - Parameters - ---------- - verbose : boolean - Specifies different levels of verbosity of feedback. When False, it only reports whether the - instance's type fails to satisfy a particular condition. When True, it reports all results, i.e. - the factor values for all conditions. - - Returns - ------- - None - """ - self.conditions = {} - - # PerfForesightConsumerType.check_conditions(self, verbose=False, verbose_reference=False) - self.violated = False - - if self.cycles != 0 or self.T_cycle > 1: - return - - # For theory, see hyperlink targets to expressions in - # url=https://econ-ark.github.io/BufferStockTheory - # For example, the hyperlink to the relevant section of the paper - self.url = "https://econ-ark.github.io/BufferStockTheory" - # would be referenced below as: - # [url]/#Uncertainty-Modified-Conditions - - self.Ex_PermShkInv = calc_expectation( - self.PermShkDstn[0], lambda x: 1 / x - ) - # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec) - - # [url]/#Pat, adjusted to include mortality - - self.InvEx_PermShkInv = ( - 1 / self.Ex_PermShkInv - ) # $\underline{\psi}$ in the paper (\bar{\isp} in private version) - self.PermGroFacAdj = self.PermGroFac[0] * self.InvEx_PermShkInv # [url]/#PGroAdj - - self.thorn = ((self.Rfree * self.DiscFac)) ** (1 / self.CRRA) - - # self.Ex_RNrm = self.Rfree*Ex_PermShkInv/(self.PermGroFac[0]*self.LivPrb[0]) - self.GPFRaw = self.thorn / (self.PermGroFac[0]) # [url]/#GPF - # Lower bound of aggregate wealth growth if all inheritances squandered - - self.GPFAggLivPrb = self.thorn * self.LivPrb[0] / self.PermGroFac[0] - - self.DiscFacGPFRawMax = ((self.PermGroFac[0]) ** (self.CRRA)) / ( - self.Rfree - ) # DiscFac at growth impatience knife edge - self.DiscFacGPFNrmMax = ( - (self.PermGroFac[0] * self.InvEx_PermShkInv) ** (self.CRRA) - ) / ( - self.Rfree - ) # DiscFac at growth impatience knife edge - self.DiscFacGPFAggLivPrbMax = ((self.PermGroFac[0]) ** (self.CRRA)) / ( - self.Rfree * self.LivPrb[0] - ) # DiscFac at growth impatience knife edge - verbose = self.verbose if verbose is None else verbose - - # self.check_GICRaw(verbose) - self.check_GICNrm(verbose) - self.check_GICAggLivPrb(verbose) - self.check_WRIC(verbose) - self.check_FVAC(verbose) - - self.violated = not self.conditions["WRIC"] or not self.conditions["FVAC"] - - if self.violated: - _log.warning( - '\n[!] For more information on the conditions, see Tables 3 and 4 in "Theoretical Foundations of Buffer Stock Saving" at ' - + self.url - + "/#Factors-Defined-And-Compared" - ) - - _log.warning("GPFRaw = %2.6f " % (self.GPFRaw)) - _log.warning("GPFNrm = %2.6f " % (self.GPFNrm)) - _log.warning("GPFAggLivPrb = %2.6f " % (self.GPFAggLivPrb)) - _log.warning("Thorn = APF = %2.6f " % (self.thorn)) - _log.warning("PermGroFacAdj = %2.6f " % (self.PermGroFacAdj)) - _log.warning("uInvEpShkuInv = %2.6f " % (self.uInvEpShkuInv)) - _log.warning("VAF = %2.6f " % (self.VAF)) - _log.warning("WRPF = %2.6f " % (self.WRPF)) - _log.warning("DiscFacGPFNrmMax = %2.6f " % (self.DiscFacGPFNrmMax)) - _log.warning("DiscFacGPFAggLivPrbMax = %2.6f " % (self.DiscFacGPFAggLivPrbMax)) - - def Ex_Mtp1_over_Ex_Ptp1(self, mNrm): - cNrm = self.solution[-1].cFunc(mNrm) - aNrm = mNrm - cNrm - Ex_Ptp1 = PermGroFac[0] - Ex_bLev_tp1 = aNrm * self.Rfree - Ex_Mtp1 = Ex_bLev_tp1 - return Ex_Mtp1 / Ex_Ptp1 - - def Ex_mtp1(self, mNrm): - cNrm = self.solution[-1].cFunc(mNrm) - aNrm = mNrm - cNrm - Ex_bNrm_tp1 = aNrm * self.Rfree * self.Ex_PermShkInv / self.PermGroFac[0] - Ex_Mtp1 = (Ex_bNrm_tp1 + 1) * Ex_Ptp1 # mean TranShk and PermShk are 1 - return Ex_Mtp1 / Ex_Ptp1 - - def calc_stable_points(self): - """ - If the problem is one that satisfies the conditions required for target ratios of different - variables to permanent income to exist, and has been solved to within the self-defined - tolerance, this method calculates the target values of market resources, consumption, - and assets. - - Parameters - ---------- - None - - Returns - ------- - None - """ - infinite_horizon = cycles_left == 0 - if not infinite_horizon: - _log.warning( - "The calc_stable_points method works only for infinite horizon models." - ) - return - - # = Functions for generating discrete income processes and - # simulated income shocks = - # ======================================================== - - def construct_lognormal_income_process_unemployment(self): - """ - Generates a list of discrete approximations to the income process for each - life period, from end of life to beginning of life. Permanent shocks are mean - one lognormally distributed with standard deviation PermShkStd[t] during the - working life, and degenerate at 1 in the retirement period. Transitory shocks - are mean one lognormally distributed with a point mass at IncUnemp with - probability UnempPrb while working; they are mean one with a point mass at - IncUnempRet with probability UnempPrbRet. Retirement occurs - after t=T_retire periods of working. - - Note 1: All time in this function runs forward, from t=0 to t=T - - Note 2: All parameters are passed as attributes of the input parameters. - - Parameters (passed as attributes of the input parameters) - ---------- - PermShkStd : [float] - List of standard deviations in log permanent income uncertainty during - the agent's life. - PermShkCount : int - The number of approximation points to be used in the discrete approxima- - tion to the permanent income shock distribution. - TranShkStd : [float] - List of standard deviations in log transitory income uncertainty during - the agent's life. - TranShkCount : int - The number of approximation points to be used in the discrete approxima- - tion to the permanent income shock distribution. - UnempPrb : float - The probability of becoming unemployed during the working period. - UnempPrbRet : float - The probability of not receiving typical retirement income when retired. - T_retire : int - The index value for the final working period in the agent's life. - If T_retire <= 0 then there is no retirement. - IncUnemp : float - Transitory income received when unemployed. - IncUnempRet : float - Transitory income received while "unemployed" when retired. - T_cycle : int - Total number of non-terminal periods in the consumer's sequence of periods. - - Returns - ------- - IncShkDstn : [distribution.Distribution] - A list with T_cycle elements, each of which is a - discrete approximation to the income process in a period. - PermShkDstn : [[distribution.Distributiony]] - A list with T_cycle elements, each of which - a discrete approximation to the permanent income shocks. - TranShkDstn : [[distribution.Distribution]] - A list with T_cycle elements, each of which - a discrete approximation to the transitory income shocks. - """ - # Unpack the parameters from the input - PermShkStd = self.PermShkStd - PermShkCount = self.PermShkCount - TranShkStd = self.TranShkStd - TranShkCount = self.TranShkCount - T_cycle = self.T_cycle - T_retire = self.T_retire - UnempPrb = self.UnempPrb - IncUnemp = self.IncUnemp - UnempPrbRet = self.UnempPrbRet - IncUnempRet = self.IncUnempRet - - IncShkDstn = [] # Discrete approximations to income process in each period - PermShkDstn = [] # Discrete approximations to permanent income shocks - TranShkDstn = [] # Discrete approximations to transitory income shocks - - # Fill out a simple discrete RV for retirement, with value 1.0 (mean of shocks) - # in normal times; value 0.0 in "unemployment" times with small prob. - if T_retire > 0: - if UnempPrbRet > 0: - PermShkValsRet = np.array( - [1.0, 1.0] - ) # Permanent income is deterministic in retirement (2 states for temp income shocks) - TranShkValsRet = np.array( - [ - IncUnempRet, - (1.0 - UnempPrbRet * IncUnempRet) / (1.0 - UnempPrbRet), - ] - ) - ShkPrbsRet = np.array([UnempPrbRet, 1.0 - UnempPrbRet]) - else: - PermShkValsRet = np.array([1.0]) - TranShkValsRet = np.array([1.0]) - ShkPrbsRet = np.array([1.0]) - IncShkDstnRet = DiscreteDistribution( - ShkPrbsRet, - [PermShkValsRet, TranShkValsRet], - seed=self.RNG.randint(0, 2 ** 31 - 1), - ) - - # Loop to fill in the list of IncShkDstn random variables. - for t in range(T_cycle): # Iterate over all periods, counting forward - - if T_retire > 0 and t >= T_retire: - # Then we are in the "retirement period" and add a retirement income object. - IncShkDstn.append(deepcopy(IncShkDstnRet)) - PermShkDstn.append([np.array([1.0]), np.array([1.0])]) - TranShkDstn.append([ShkPrbsRet, TranShkValsRet]) - else: - # We are in the "working life" periods. - TranShkDstn_t = MeanOneLogNormal(sigma=TranShkStd[t]).approx( - TranShkCount, tail_N=0 - ) - if UnempPrb > 0: - TranShkDstn_t = add_discrete_outcome_constant_mean( - TranShkDstn_t, p=UnempPrb, x=IncUnemp - ) - PermShkDstn_t = MeanOneLogNormal(sigma=PermShkStd[t]).approx( - PermShkCount, tail_N=0 - ) - - IncShkDstn.append( - combine_indep_dstns( - PermShkDstn_t, - TranShkDstn_t, - seed=self.RNG.randint(0, 2 ** 31 - 1), - ) - ) # mix the independent distributions - PermShkDstn.append(PermShkDstn_t) - TranShkDstn.append(TranShkDstn_t) - return IncShkDstn, PermShkDstn, TranShkDstn - - -# Make a dictionary to specify a "kinked R" idiosyncratic shock consumer -init_kinked_R = dict( - init_idiosyncratic_shocks, - **{ - "Rboro": 1.20, # Interest factor on assets when borrowing, a < 0 - "Rsave": 1.02, # Interest factor on assets when saving, a > 0 - "BoroCnstArt": None, # kinked R is a bit silly if borrowing not allowed - "CubicBool": True, # kinked R is now compatible with linear cFunc and cubic cFunc - "aXtraCount": 48, # ...so need lots of extra gridpoints to make up for it - } -) -del init_kinked_R["Rfree"] # get rid of constant interest factor - - -class KinkedRconsumerType(IndShockConsumerType): - """ - A consumer type that faces idiosyncratic shocks to income and has a different - interest factor on saving vs borrowing. Extends IndShockConsumerType, with - very small changes. Solver for this class is currently only compatible with - linear spline interpolation. - - Same parameters as AgentType. - - - Parameters - ---------- - """ - - time_inv_ = copy(IndShockConsumerType.time_inv_) - time_inv_.remove("Rfree") - time_inv_ += ["Rboro", "Rsave"] - - def __init__(self, **kwds): - params = init_kinked_R.copy() - params.update(kwds) - - # Initialize a basic AgentType - PerfForesightConsumerType.__init__(self, **params) - - # Add consumer-type specific objects, copying to create independent versions - self.solve_one_period = make_one_period_oo_solver(ConsKinkedRsolver) - self.update() # Make assets grid, income process, terminal solution - - def pre_solve(self): - # AgentType.pre_solve(self) - self.update_solution_terminal() - - def calc_bounding_values(self): - """ - Calculate human wealth plus minimum and maximum MPC in an infinite - horizon model with only one period repeated indefinitely. Store results - as attributes of self. Human wealth is the present discounted value of - expected future income after receiving income this period, ignoring mort- - ality. The maximum MPC is the limit of the MPC as m --> mNrmMin. The - minimum MPC is the limit of the MPC as m --> infty. This version deals - with the different interest rates on borrowing vs saving. - - Parameters - ---------- - None - - Returns - ------- - None - """ - # Unpack the income distribution and get average and worst outcomes - PermShkValsNext = self.IncShkDstn[0][1] - TranShkValsNext = self.IncShkDstn[0][2] - ShkPrbsNext = self.IncShkDstn[0][0] - Ex_IncNext = calc_expectation( - IncShkDstn, - lambda trans, perm: trans * perm - ) - PermShkMinNext = np.min(PermShkValsNext) - TranShkMinNext = np.min(TranShkValsNext) - WorstIncNext = PermShkMinNext * TranShkMinNext - WorstIncPrb = np.sum( - ShkPrbsNext[(PermShkValsNext * TranShkValsNext) == WorstIncNext] - ) - - # Calculate human wealth and the infinite horizon natural borrowing constraint - hNrm = (Ex_IncNext * self.PermGroFac[0] / self.Rsave) / ( - 1.0 - self.PermGroFac[0] / self.Rsave - ) - temp = self.PermGroFac[0] * PermShkMinNext / self.Rboro - BoroCnstNat = -TranShkMinNext * temp / (1.0 - temp) - - PatFacTop = (self.DiscFac * self.LivPrb[0] * self.Rsave) ** ( - 1.0 / self.CRRA - ) / self.Rsave - PatFacBot = (self.DiscFac * self.LivPrb[0] * self.Rboro) ** ( - 1.0 / self.CRRA - ) / self.Rboro - if BoroCnstNat < self.BoroCnstArt: - MPCmax = 1.0 # if natural borrowing constraint is overridden by artificial one, MPCmax is 1 - else: - MPCmax = 1.0 - WorstIncPrb ** (1.0 / self.CRRA) * PatFacBot - MPCmin = 1.0 - PatFacTop - - # Store the results as attributes of self - self.hNrm = hNrm - self.MPCmin = MPCmin - self.MPCmax = MPCmax - - def make_euler_error_func(self, mMax=100, approx_inc_dstn=True): - """ - Creates a "normalized Euler error" function for this instance, mapping - from market resources to "consumption error per dollar of consumption." - Stores result in attribute eulerErrorFunc as an interpolated function. - Has option to use approximate income distribution stored in self.IncShkDstn - or to use a (temporary) very dense approximation. - - SHOULD BE INHERITED FROM ConsIndShockModel - - Parameters - ---------- - mMax : float - Maximum normalized market resources for the Euler error function. - approx_inc_dstn : Boolean - Indicator for whether to use the approximate discrete income distri- - bution stored in self.IncShkDstn[0], or to use a very accurate - discrete approximation instead. When True, uses approximation in - IncShkDstn; when False, makes and uses a very dense approximation. - - Returns - ------- - None - - Notes - ----- - This method is not used by any other code in the library. Rather, it is here - for expository and benchmarking purposes. - """ - raise NotImplementedError() - - def get_Rfree(self): - """ - Returns an array of size self.AgentCount with self.Rboro or self.Rsave in each entry, based - on whether self.aNrmNow >< 0. - - Parameters - ---------- - None - - Returns - ------- - RfreeNow : np.array - Array of size self.AgentCount with risk free interest rate for each agent. - """ - RfreeNow = self.Rboro * np.ones(self.AgentCount) - RfreeNow[self.state_prev['aNrm'] > 0] = self.Rsave - return RfreeNow - - def check_conditions(self): - """ - This method checks whether the instance's type satisfies the Absolute Impatience Condition (AIC), - the Return Impatience Condition (RIC), the Growth Impatience Condition (GICRaw), the Normalized Growth Impatience Condition (GIC-Nrm), the Weak Return - Impatience Condition (WRIC), the Finite Human Wealth Condition (FHWC) and the Finite Value of - Autarky Condition (FVAC). To check which conditions are relevant to the model at hand, a - reference to the relevant theoretical literature is made. - - Parameters - ---------- - None - - Returns - ------- - None - """ - raise NotImplementedError() - - -def apply_flat_income_tax( - IncShkDstn, tax_rate, T_retire, unemployed_indices=None, transitory_index=2 -): - """ - Applies a flat income tax rate to all employed income states during the working - period of life (those before T_retire). Time runs forward in this function. - - Parameters - ---------- - IncShkDstn : [distribution.Distribution] - The discrete approximation to the income distribution in each time period. - tax_rate : float - A flat income tax rate to be applied to all employed income. - T_retire : int - The time index after which the agent retires. - unemployed_indices : [int] - Indices of transitory shocks that represent unemployment states (no tax). - transitory_index : int - The index of each element of IncShkDstn representing transitory shocks. - - Returns - ------- - IncShkDstn_new : [distribution.Distribution] - The updated income distributions, after applying the tax. - """ - unemployed_indices = ( - unemployed_indices if unemployed_indices is not None else list() - ) - IncShkDstn_new = deepcopy(IncShkDstn) - i = transitory_index - for t in range(len(IncShkDstn)): - if t < T_retire: - for j in range((IncShkDstn[t][i]).size): - if j not in unemployed_indices: - IncShkDstn_new[t][i][j] = IncShkDstn[t][i][j] * (1 - tax_rate) - return IncShkDstn_new - - -# ======================================================= -# ================ Other useful functions =============== -# ======================================================= - - -def construct_assets_grid(parameters): - """ - Constructs the base grid of post-decision states, representing end-of-period - assets above the absolute minimum. - - All parameters are passed as attributes of the single input parameters. The - input can be an instance of a ConsumerType, or a custom Parameters class. - - Parameters - ---------- - aXtraMin: float - Minimum value for the a-grid - aXtraMax: float - Maximum value for the a-grid - aXtraCount: int - Size of the a-grid - aXtraExtra: [float] - Extra values for the a-grid. - exp_nest: int - Level of nesting for the exponentially spaced grid - - Returns - ------- - aXtraGrid: np.ndarray - Base array of values for the post-decision-state grid. - """ - # Unpack the parameters - aXtraMin = parameters.aXtraMin - aXtraMax = parameters.aXtraMax - aXtraCount = parameters.aXtraCount - aXtraExtra = parameters.aXtraExtra - grid_type = "exp_mult" - exp_nest = parameters.aXtraNestFac - - # Set up post decision state grid: - aXtraGrid = None - if grid_type == "linear": - aXtraGrid = np.linspace(aXtraMin, aXtraMax, aXtraCount) - elif grid_type == "exp_mult": - aXtraGrid = make_grid_exp_mult( - ming=aXtraMin, maxg=aXtraMax, ng=aXtraCount, timestonest=exp_nest - ) - else: - raise Exception( - "grid_type not recognized in __init__." - + "Please ensure grid_type is 'linear' or 'exp_mult'" - ) - - # Add in additional points for the grid: - for a in aXtraExtra: - if a is not None: - if a not in aXtraGrid: - j = aXtraGrid.searchsorted(a) - aXtraGrid = np.insert(aXtraGrid, j, a) - - return aXtraGrid - - -# Make a dictionary to specify a lifecycle consumer with a finite horizon - -# Main calibration characteristics -birth_age = 25 -death_age = 90 -adjust_infl_to = 1992 -# Use income estimates from Cagetti (2003) for High-school graduates -education = "HS" -income_calib = Cagetti_income[education] - -# Income specification -income_params = parse_income_spec( - age_min=birth_age, - age_max=death_age, - adjust_infl_to=adjust_infl_to, - **income_calib, - SabelhausSong=True -) - -# Initial distribution of wealth and permanent income -dist_params = income_wealth_dists_from_scf( - base_year=adjust_infl_to, age=birth_age, education=education, wave=1995 -) - -# We need survival probabilities only up to death_age-1, because survival -# probability at death_age is 1. -liv_prb = parse_ssa_life_table( - female=False, cross_sec=True, year=2004, min_age=birth_age, max_age=death_age - 1 -) - -# Parameters related to the number of periods implied by the calibration -time_params = parse_time_params(age_birth=birth_age, age_death=death_age) - -# Update all the new parameters -init_lifecycle = copy(init_idiosyncratic_shocks) -init_lifecycle.update(time_params) -init_lifecycle.update(dist_params) -# Note the income specification overrides the pLvlInitMean from the SCF. -init_lifecycle.update(income_params) -init_lifecycle.update({"LivPrb": liv_prb}) - - -# Make a dictionary to specify an infinite consumer with a four period cycle -init_cyclical = copy(init_idiosyncratic_shocks) -init_cyclical['PermGroFac'] = [1.082251, 2.8, 0.3, 1.1] -init_cyclical['PermShkStd'] = [0.1, 0.1, 0.1, 0.1] -init_cyclical['TranShkStd'] = [0.1, 0.1, 0.1, 0.1] -init_cyclical['LivPrb'] = 4*[0.98] -init_cyclical['T_cycle'] = 4 \ No newline at end of file diff --git a/HARK/ConsumptionSaving/ConsIndShockModelOld.py b/HARK/ConsumptionSaving/ConsIndShockModelOld.py new file mode 100644 index 000000000..43c76ff37 --- /dev/null +++ b/HARK/ConsumptionSaving/ConsIndShockModelOld.py @@ -0,0 +1,3054 @@ +""" +Classes to solve canonical consumption-saving models with idiosyncratic shocks +to income. All models here assume CRRA utility with geometric discounting, no +bequest motive, and income shocks that are fully transitory or fully permanent. + +It currently solves three types of models: + 1) A very basic "perfect foresight" consumption-savings model with no uncertainty. + 2) A consumption-savings model with risk over transitory and permanent income shocks. + 3) The model described in (2), with an interest rate for debt that differs + from the interest rate for savings. + +See NARK https://HARK.githhub.io/Documentation/NARK for information on variable naming conventions. +See HARK documentation for mathematical descriptions of the models being solved. +""" +from copy import copy, deepcopy +import numpy as np +from scipy.optimize import newton +from HARK import AgentType, NullFunc, MetricObject, make_one_period_oo_solver +from HARK.utilities import warnings # Because of "patch" to warnings modules +from HARK.interpolation import ( + CubicInterp, + LowerEnvelope, + LinearInterp, + ValueFuncCRRA, + MargValueFuncCRRA, + MargMargValueFuncCRRA +) +from HARK.distribution import Lognormal, MeanOneLogNormal, Uniform +from HARK.distribution import ( + DiscreteDistribution, + add_discrete_outcome_constant_mean, + calc_expectation, + combine_indep_dstns, +) +from HARK.utilities import ( + make_grid_exp_mult, + CRRAutility, + CRRAutilityP, + CRRAutilityPP, + CRRAutilityP_inv, + CRRAutility_invP, + CRRAutility_inv, + CRRAutilityP_invP, +) +from HARK import _log +from HARK import set_verbosity_level + +from HARK.Calibration.Income.IncomeTools import parse_income_spec, parse_time_params, Cagetti_income +from HARK.datasets.SCF.WealthIncomeDist.SCFDistTools import income_wealth_dists_from_scf +from HARK.datasets.life_tables.us_ssa.SSATools import parse_ssa_life_table + +__all__ = [ + "ConsumerSolution", + "ConsPerfForesightSolver", + "ConsIndShockSetup", + "ConsIndShockSolverBasic", + "ConsIndShockSolver", + "ConsKinkedRsolver", + "PerfForesightConsumerType", + "IndShockConsumerType", + "KinkedRconsumerType", + "init_perfect_foresight", + "init_idiosyncratic_shocks", + "init_kinked_R", + "init_lifecycle", + "init_cyclical", +] + +utility = CRRAutility +utilityP = CRRAutilityP +utilityPP = CRRAutilityPP +utilityP_inv = CRRAutilityP_inv +utility_invP = CRRAutility_invP +utility_inv = CRRAutility_inv +utilityP_invP = CRRAutilityP_invP + +# ===================================================================== +# === Classes that help solve consumption-saving models === +# ===================================================================== + + +class ConsumerSolution(MetricObject): + """ + A class representing the solution of a single period of a consumption-saving + problem. The solution must include a consumption function and marginal + value function. + + Here and elsewhere in the code, Nrm indicates that variables are normalized + by permanent income. + + Parameters + ---------- + cFunc : function + The consumption function for this period, defined over market + resources: c = cFunc(m). + vFunc : function + The beginning-of-period value function for this period, defined over + market resources: v = vFunc(m). + vPfunc : function + The beginning-of-period marginal value function for this period, + defined over market resources: vP = vPfunc(m). + vPPfunc : function + The beginning-of-period marginal marginal value function for this + period, defined over market resources: vPP = vPPfunc(m). + mNrmMin : float + The minimum allowable market resources for this period; the consump- + tion function (etc) are undefined for m < mNrmMin. + hNrm : float + Human wealth after receiving income this period: PDV of all future + income, ignoring mortality. + MPCmin : float + Infimum of the marginal propensity to consume this period. + MPC --> MPCmin as m --> infinity. + MPCmax : float + Supremum of the marginal propensity to consume this period. + MPC --> MPCmax as m --> mNrmMin. + + """ + + distance_criteria = ["vPfunc"] + + def __init__( + self, + cFunc=None, + vFunc=None, + vPfunc=None, + vPPfunc=None, + mNrmMin=None, + hNrm=None, + MPCmin=None, + MPCmax=None, + ): + # Change any missing function inputs to NullFunc + self.cFunc = cFunc if cFunc is not None else NullFunc() + self.vFunc = vFunc if vFunc is not None else NullFunc() + self.vPfunc = vPfunc if vPfunc is not None else NullFunc() + # vPFunc = NullFunc() if vPfunc is None else vPfunc + self.vPPfunc = vPPfunc if vPPfunc is not None else NullFunc() + self.mNrmMin = mNrmMin + self.hNrm = hNrm + self.MPCmin = MPCmin + self.MPCmax = MPCmax + + def append_solution(self, new_solution): + """ + Appends one solution to another to create a ConsumerSolution whose + attributes are lists. Used in ConsMarkovModel, where we append solutions + *conditional* on a particular value of a Markov state to each other in + order to get the entire solution. + + Parameters + ---------- + new_solution : ConsumerSolution + The solution to a consumption-saving problem; each attribute is a + list representing state-conditional values or functions. + + Returns + ------- + None + """ + if type(self.cFunc) != list: + # Then we assume that self is an empty initialized solution instance. + # Begin by checking this is so. + assert ( + NullFunc().distance(self.cFunc) == 0 + ), "append_solution called incorrectly!" + + # We will need the attributes of the solution instance to be lists. Do that here. + self.cFunc = [new_solution.cFunc] + self.vFunc = [new_solution.vFunc] + self.vPfunc = [new_solution.vPfunc] + self.vPPfunc = [new_solution.vPPfunc] + self.mNrmMin = [new_solution.mNrmMin] + else: + self.cFunc.append(new_solution.cFunc) + self.vFunc.append(new_solution.vFunc) + self.vPfunc.append(new_solution.vPfunc) + self.vPPfunc.append(new_solution.vPPfunc) + self.mNrmMin.append(new_solution.mNrmMin) + + +# ===================================================================== +# === Classes and functions that solve consumption-saving models === +# ===================================================================== + + +class ConsPerfForesightSolver(MetricObject): + """ + A class for solving a one period perfect foresight + consumption-saving problem. + An instance of this class is created by the function solvePerfForesight + in each period. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one-period problem. + DiscFac : float + Intertemporal discount factor for future utility. + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the next period. + CRRA : float + Coefficient of relative risk aversion. + Rfree : float + Risk free interest factor on end-of-period assets. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt : float or None + Artificial borrowing constraint, as a multiple of permanent income. + Can be None, indicating no artificial constraint. + MaxKinks : int + Maximum number of kink points to allow in the consumption function; + additional points will be thrown out. Only relevant in infinite + horizon model with artificial borrowing constraint. + """ + + def __init__( + self, + solution_next, + DiscFac, + LivPrb, + CRRA, + Rfree, + PermGroFac, + BoroCnstArt, + MaxKinks, + ): + self.solution_next = solution_next + self.DiscFac = DiscFac + self.LivPrb = LivPrb + self.CRRA = CRRA + self.Rfree = Rfree + self.PermGroFac = PermGroFac + self.BoroCnstArt = BoroCnstArt + self.MaxKinks = MaxKinks + + def def_utility_funcs(self): + """ + Defines CRRA utility function for this period (and its derivatives), + saving them as attributes of self for other methods to use. + + Parameters + ---------- + None + + Returns + ------- + None + """ + self.u = lambda c: utility(c, gam=self.CRRA) # utility function + self.uP = lambda c: utilityP(c, gam=self.CRRA) # marginal utility function + self.uPP = lambda c: utilityPP( + c, gam=self.CRRA + ) # marginal marginal utility function + + def def_value_funcs(self): + """ + Defines the value and marginal value functions for this period. + Uses the fact that for a perfect foresight CRRA utility problem, + if the MPC in period t is :math:`\kappa_{t}`, and relative risk + aversion :math:`\rho`, then the inverse value vFuncNvrs has a + constant slope of :math:`\kappa_{t}^{-\rho/(1-\rho)}` and + vFuncNvrs has value of zero at the lower bound of market resources + mNrmMin. See PerfForesightConsumerType.ipynb documentation notebook + for a brief explanation and the links below for a fuller treatment. + + https://www.econ2.jhu.edu/people/ccarroll/public/lecturenotes/consumption/PerfForesightCRRA/#vFuncAnalytical + https://www.econ2.jhu.edu/people/ccarroll/SolvingMicroDSOPs/#vFuncPF + + Parameters + ---------- + None + + Returns + ------- + None + """ + + # See the PerfForesightConsumerType.ipynb documentation notebook for the derivations + vFuncNvrsSlope = self.MPCmin ** (-self.CRRA / (1.0 - self.CRRA)) + vFuncNvrs = LinearInterp( + np.array([self.mNrmMinNow, self.mNrmMinNow + 1.0]), + np.array([0.0, vFuncNvrsSlope]), + ) + self.vFunc = ValueFuncCRRA(vFuncNvrs, self.CRRA) + self.vPfunc = MargValueFuncCRRA(self.cFunc, self.CRRA) + + def make_cFunc_PF(self): + """ + Makes the (linear) consumption function for this period. + + Parameters + ---------- + None + + Returns + ------- + None + """ + # Use a local value of BoroCnstArt to prevent comparing None and float below. + if self.BoroCnstArt is None: + BoroCnstArt = -np.inf + else: + BoroCnstArt = self.BoroCnstArt + + # Calculate human wealth this period + self.hNrmNow = (self.PermGroFac / self.Rfree) * (self.solution_next.hNrm + 1.0) + + # Calculate the lower bound of the marginal propensity to consume + PatFac = ((self.Rfree * self.DiscFacEff) ** (1.0 / self.CRRA)) / self.Rfree + self.MPCmin = 1.0 / (1.0 + PatFac / self.solution_next.MPCmin) + + # Extract the discrete kink points in next period's consumption function; + # don't take the last one, as it only defines the extrapolation and is not a kink. + mNrmNext = self.solution_next.cFunc.x_list[:-1] + cNrmNext = self.solution_next.cFunc.y_list[:-1] + + # Calculate the end-of-period asset values that would reach those kink points + # next period, then invert the first order condition to get consumption. Then + # find the endogenous gridpoint (kink point) today that corresponds to each kink + aNrmNow = (self.PermGroFac / self.Rfree) * (mNrmNext - 1.0) + cNrmNow = (self.DiscFacEff * self.Rfree) ** (-1.0 / self.CRRA) * ( + self.PermGroFac * cNrmNext + ) + mNrmNow = aNrmNow + cNrmNow + + # Add an additional point to the list of gridpoints for the extrapolation, + # using the new value of the lower bound of the MPC. + mNrmNow = np.append(mNrmNow, mNrmNow[-1] + 1.0) + cNrmNow = np.append(cNrmNow, cNrmNow[-1] + self.MPCmin) + + # If the artificial borrowing constraint binds, combine the constrained and + # unconstrained consumption functions. + if BoroCnstArt > mNrmNow[0]: + # Find the highest index where constraint binds + cNrmCnst = mNrmNow - BoroCnstArt + CnstBinds = cNrmCnst < cNrmNow + idx = np.where(CnstBinds)[0][-1] + + if idx < (mNrmNow.size - 1): + # If it is not the *very last* index, find the the critical level + # of mNrm where the artificial borrowing contraint begins to bind. + d0 = cNrmNow[idx] - cNrmCnst[idx] + d1 = cNrmCnst[idx + 1] - cNrmNow[idx + 1] + m0 = mNrmNow[idx] + m1 = mNrmNow[idx + 1] + alpha = d0 / (d0 + d1) + mCrit = m0 + alpha * (m1 - m0) + + # Adjust the grids of mNrm and cNrm to account for the borrowing constraint. + cCrit = mCrit - BoroCnstArt + mNrmNow = np.concatenate(([BoroCnstArt, mCrit], mNrmNow[(idx + 1):])) + cNrmNow = np.concatenate(([0.0, cCrit], cNrmNow[(idx + 1):])) + + else: + # If it *is* the very last index, then there are only three points + # that characterize the consumption function: the artificial borrowing + # constraint, the constraint kink, and the extrapolation point. + mXtra = (cNrmNow[-1] - cNrmCnst[-1]) / (1.0 - self.MPCmin) + mCrit = mNrmNow[-1] + mXtra + cCrit = mCrit - BoroCnstArt + mNrmNow = np.array([BoroCnstArt, mCrit, mCrit + 1.0]) + cNrmNow = np.array([0.0, cCrit, cCrit + self.MPCmin]) + + # If the mNrm and cNrm grids have become too large, throw out the last + # kink point, being sure to adjust the extrapolation. + if mNrmNow.size > self.MaxKinks: + mNrmNow = np.concatenate((mNrmNow[:-2], [mNrmNow[-3] + 1.0])) + cNrmNow = np.concatenate((cNrmNow[:-2], [cNrmNow[-3] + self.MPCmin])) + + # Construct the consumption function as a linear interpolation. + self.cFunc = LinearInterp(mNrmNow, cNrmNow) + + # Calculate the upper bound of the MPC as the slope of the bottom segment. + self.MPCmax = (cNrmNow[1] - cNrmNow[0]) / (mNrmNow[1] - mNrmNow[0]) + + # Add two attributes to enable calculation of steady state market resources. + self.Ex_IncNext = 1.0 # Perfect foresight income of 1 + self.mNrmMinNow = mNrmNow[0] # Relabeling for compatibility with add_mNrmStE + + def add_mNrmTrg(self, solution): + """ + Finds value of (normalized) market resources m at which individual consumer + expects m not to change. + This will exist if the GICNrm holds. + + https://econ-ark.github.io/BufferStockTheory#UniqueStablePoints + + Parameters + ---------- + solution : ConsumerSolution + Solution to this period's problem, which must have attribute cFunc. + Returns + ------- + solution : ConsumerSolution + Same solution that was passed, but now with the attribute mNrmStE. + """ + + # If no uncertainty, return the degenerate targets for the PF model + if hasattr(self, "TranShkMinNext"): # Then it has transitory shocks + # Handle the degenerate case where shocks are of size zero + if ((self.TranShkMinNext == 1.0) and (self.PermShkMinNext == 1.0)): + # but they are of zero size (and also permanent are zero) + if self.GICRaw: # max of nat and art boro cnst + if type(self.BoroCnstArt) == type(None): + solution.mNrmStE = -self.hNrmNow + solution.mNrmTrg = -self.hNrmNow + else: + bNrmNxt = -self.BoroCnstArt * self.Rfree/self.PermGroFac + solution.mNrmStE = bNrmNxt + 1.0 + solution.mNrmTrg = bNrmNxt + 1.0 + else: # infinity + solution.mNrmStE = float('inf') + solution.mNrmTrg = float('inf') + return solution + + # First find + # \bar{\mathcal{R}} = E_t[R/Gamma_{t+1}] = R/Gamma E_t[1/psi_{t+1}] + if type(self) == ConsPerfForesightSolver: + Ex_PermShkInv = 1.0 + else: + Ex_PermShkInv = np.dot(1/self.PermShkValsNext, self.ShkPrbsNext) + + Ex_RNrmFac = (self.Rfree/self.PermGroFac)*Ex_PermShkInv + + # mNrmTrg solves Rcalbar*(m - c(m)) + E[inc_next] = m. Define a + # rearranged version. + Ex_m_tp1_minus_m_t = ( + lambda m: Ex_RNrmFac * (m - solution.cFunc(m)) + self.Ex_IncNext - m + ) + + # Minimum market resources plus next income is okay starting guess + m_init_guess = self.mNrmMinNow + self.Ex_IncNext + try: + mNrmTrg = newton(Ex_m_tp1_minus_m_t, m_init_guess) + except: + mNrmTrg = None + + # Add mNrmTrg to the solution and return it + solution.mNrmTrg = mNrmTrg + return solution + + def add_mNrmStE(self, solution): + """ + Finds market resources ratio at which 'balanced growth' is expected. + This is the m ratio such that the expected growth rate of the M level + matches the expected growth rate of permanent income. This value does + not exist if the Growth Impatience Condition does not hold. + + https://econ-ark.github.io/BufferStockTheory#Unique-Stable-Points + + Parameters + ---------- + solution : ConsumerSolution + Solution to this period's problem, which must have attribute cFunc. + Returns + ------- + solution : ConsumerSolution + Same solution that was passed, but now with the attribute mNrmStE + """ + # Probably should test whether GICRaw holds and log error if it does not + # using check_conditions + # All combinations of c and m that yield E[PermGroFac PermShkVal mNext] = mNow + # https://econ-ark.github.io/BufferStockTheory/#The-Individual-Steady-State + + PF_RNrm = self.Rfree/self.PermGroFac + # If we are working with a model that permits uncertainty but that + # uncertainty has been set to zero, return the correct answer + # by hand because in this degenerate case numerical search may + # have trouble + if hasattr(self, "TranShkMinNext"): # Then it has transitory shocks + if ((self.TranShkMinNext == 1.0) and (self.PermShkMinNext == 1.0)): + # but they are of zero size (and permanent shocks also not there) + if self.GICRaw: # max of nat and art boro cnst + # breakpoint() + if type(self.BoroCnstArt) == type(None): + solution.mNrmStE = -self.hNrmNow + solution.mNrmTrg = -self.hNrmNow + else: + bNrmNxt = -self.BoroCnstArt * self.Rfree/self.PermGroFac + solution.mNrmStE = bNrmNxt + 1.0 + solution.mNrmTrg = bNrmNxt + 1.0 + else: # infinity + solution.mNrmStE = float('inf') + solution.mNrmTrg = float('inf') + return solution + + Ex_PermShk_tp1_times_m_tp1_minus_m_t = ( + lambda mStE: PF_RNrm * (mStE - solution.cFunc(mStE)) + 1.0 - mStE + ) + + # Minimum market resources plus next income is okay starting guess + m_init_guess = self.mNrmMinNow + self.Ex_IncNext + try: + mNrmStE = newton(Ex_PermShk_tp1_times_m_tp1_minus_m_t, m_init_guess) + except: + mNrmStE = None + + solution.mNrmStE = mNrmStE + return solution + + def add_stable_points(self, solution): + """ + Checks necessary conditions for the existence of the individual steady + state and target levels of market resources (see above). + If the conditions are satisfied, computes and adds the stable points + to the solution. + + Parameters + ---------- + solution : ConsumerSolution + Solution to this period's problem, which must have attribute cFunc. + Returns + ------- + solution : ConsumerSolution + Same solution that was provided, augmented with attributes mNrmStE and + mNrmTrg, if they exist. + + """ + + # 0. There is no non-degenerate steady state for any unconstrained PF model. + # 1. There is a non-degenerate SS for constrained PF model if GICRaw holds. + # Therefore + # Check if (GICRaw and BoroCnstArt) and if so compute them both + thorn = (self.Rfree*self.DiscFacEff)**(1/self.CRRA) + GICRaw = 1 > thorn/self.PermGroFac + if self.BoroCnstArt is not None and GICRaw: + solution = self.add_mNrmStE(solution) + solution = self.add_mNrmTrg(solution) + return solution + + def solve(self): + """ + Solves the one period perfect foresight consumption-saving problem. + + Parameters + ---------- + None + + Returns + ------- + solution : ConsumerSolution + The solution to this period's problem. + """ + self.def_utility_funcs() + self.DiscFacEff = self.DiscFac * self.LivPrb # Effective=pure x LivPrb + self.make_cFunc_PF() + self.def_value_funcs() + + solution = ConsumerSolution( + cFunc=self.cFunc, + vFunc=self.vFunc, + vPfunc=self.vPfunc, + mNrmMin=self.mNrmMinNow, + hNrm=self.hNrmNow, + MPCmin=self.MPCmin, + MPCmax=self.MPCmax, + ) + + solution = self.add_stable_points(solution) + + return solution + + +############################################################################### +############################################################################### +class ConsIndShockSetup(ConsPerfForesightSolver): + """ + A superclass for solvers of one period consumption-saving problems with + constant relative risk aversion utility and permanent and transitory shocks + to income. Has methods to set up but not solve the one period problem. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one period problem. + IncShkDstn : distribution.Distribution + A discrete + approximation to the income process between the period being solved + and the one immediately following (in solution_next). + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the succeeding period. + DiscFac : float + Intertemporal discount factor for future utility. + CRRA : float + Coefficient of relative risk aversion. + Rfree : float + Risk free interest factor on end-of-period assets. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt: float or None + Borrowing constraint for the minimum allowable assets to end the + period with. If it is less than the natural borrowing constraint, + then it is irrelevant; BoroCnstArt=None indicates no artificial bor- + rowing constraint. + aXtraGrid: np.array + Array of "extra" end-of-period asset values-- assets above the + absolute minimum acceptable level. + vFuncBool: boolean + An indicator for whether the value function should be computed and + included in the reported solution. + CubicBool: boolean + An indicator for whether the solver should use cubic or linear inter- + polation. + """ + + def __init__( + self, + solution_next, + IncShkDstn, + LivPrb, + DiscFac, + CRRA, + Rfree, + PermGroFac, + BoroCnstArt, + aXtraGrid, + vFuncBool, + CubicBool, + ): + """ + Constructor for a new solver-setup for problems with income subject to + permanent and transitory shocks. + """ + self.solution_next = solution_next + self.IncShkDstn = IncShkDstn + self.LivPrb = LivPrb + self.DiscFac = DiscFac + self.CRRA = CRRA + self.Rfree = Rfree + self.PermGroFac = PermGroFac + self.BoroCnstArt = BoroCnstArt + self.aXtraGrid = aXtraGrid + self.vFuncBool = vFuncBool + self.CubicBool = CubicBool + + self.def_utility_funcs() + + def def_utility_funcs(self): + """ + Defines CRRA utility function for this period (and its derivatives, + and their inverses), saving them as attributes of self for other methods + to use. + + Parameters + ---------- + none + + Returns + ------- + none + """ + ConsPerfForesightSolver.def_utility_funcs(self) + self.uPinv = lambda u: utilityP_inv(u, gam=self.CRRA) + self.uPinvP = lambda u: utilityP_invP(u, gam=self.CRRA) + self.uinvP = lambda u: utility_invP(u, gam=self.CRRA) + if self.vFuncBool: + self.uinv = lambda u: utility_inv(u, gam=self.CRRA) + + def set_and_update_values(self, solution_next, IncShkDstn, LivPrb, DiscFac): + """ + Unpacks some of the inputs (and calculates simple objects based on them), + storing the results in self for use by other methods. These include: + income shocks and probabilities, next period's marginal value function + (etc), the probability of getting the worst income shock next period, + the patience factor, human wealth, and the bounding MPCs. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one period problem. + IncShkDstn : distribution.DiscreteDistribution + A DiscreteDistribution with a pmf + and two point value arrays in X, order: + permanent shocks, transitory shocks. + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the succeeding period. + DiscFac : float + Intertemporal discount factor for future utility. + + Returns + ------- + None + """ + self.DiscFacEff = DiscFac * LivPrb # "effective" discount factor + self.IncShkDstn = IncShkDstn + self.ShkPrbsNext = IncShkDstn.pmf + self.PermShkValsNext = IncShkDstn.X[0] + self.TranShkValsNext = IncShkDstn.X[1] + self.PermShkMinNext = np.min(self.PermShkValsNext) + self.TranShkMinNext = np.min(self.TranShkValsNext) + self.vPfuncNext = solution_next.vPfunc + self.WorstIncPrb = np.sum( + self.ShkPrbsNext[ + (self.PermShkValsNext * self.TranShkValsNext) + == (self.PermShkMinNext * self.TranShkMinNext) + ] + ) + + if self.CubicBool: + self.vPPfuncNext = solution_next.vPPfunc + + if self.vFuncBool: + self.vFuncNext = solution_next.vFunc + + # Update the bounding MPCs and PDV of human wealth: + self.PatFac = ((self.Rfree * self.DiscFacEff) ** (1.0 / self.CRRA)) / self.Rfree + self.MPCminNow = 1.0 / (1.0 + self.PatFac / solution_next.MPCmin) + self.Ex_IncNext = np.dot( + self.ShkPrbsNext, self.TranShkValsNext * self.PermShkValsNext + ) + self.hNrmNow = ( + self.PermGroFac / self.Rfree * (self.Ex_IncNext + solution_next.hNrm) + ) + self.MPCmaxNow = 1.0 / ( + 1.0 + + (self.WorstIncPrb ** (1.0 / self.CRRA)) + * self.PatFac + / solution_next.MPCmax + ) + + self.cFuncLimitIntercept = self.MPCminNow * self.hNrmNow + self.cFuncLimitSlope = self.MPCminNow + + def def_BoroCnst(self, BoroCnstArt): + """ + Defines the constrained portion of the consumption function as cFuncNowCnst, + an attribute of self. Uses the artificial and natural borrowing constraints. + + Parameters + ---------- + BoroCnstArt : float or None + Borrowing constraint for the minimum allowable assets to end the + period with. If it is less than the natural borrowing constraint, + then it is irrelevant; BoroCnstArt=None indicates no artificial bor- + rowing constraint. + + Returns + ------- + none + """ + # Calculate the minimum allowable value of money resources in this period + self.BoroCnstNat = ( + (self.solution_next.mNrmMin - self.TranShkMinNext) + * (self.PermGroFac * self.PermShkMinNext) + / self.Rfree + ) + + # Note: need to be sure to handle BoroCnstArt==None appropriately. + # In Py2, this would evaluate to 5.0: np.max([None, 5.0]). + # However in Py3, this raises a TypeError. Thus here we need to directly + # address the situation in which BoroCnstArt == None: + if BoroCnstArt is None: + self.mNrmMinNow = self.BoroCnstNat + else: + self.mNrmMinNow = np.max([self.BoroCnstNat, BoroCnstArt]) + if self.BoroCnstNat < self.mNrmMinNow: + self.MPCmaxEff = 1.0 # If actually constrained, MPC near limit is 1 + else: + self.MPCmaxEff = self.MPCmaxNow + + # Define the borrowing constraint (limiting consumption function) + self.cFuncNowCnst = LinearInterp( + np.array([self.mNrmMinNow, self.mNrmMinNow + 1]), np.array([0.0, 1.0]) + ) + + def prepare_to_solve(self): + """ + Perform preparatory work before calculating the unconstrained consumption + function. + + Parameters + ---------- + none + + Returns + ------- + none + """ + self.set_and_update_values( + self.solution_next, self.IncShkDstn, self.LivPrb, self.DiscFac + ) + self.def_BoroCnst(self.BoroCnstArt) + + +#################################################################################################### +#################################################################################################### + + +class ConsIndShockSolverBasic(ConsIndShockSetup): + """ + This class solves a single period of a standard consumption-saving problem, + using linear interpolation and without the ability to calculate the value + function. ConsIndShockSolver inherits from this class and adds the ability + to perform cubic interpolation and to calculate the value function. + + Note that this class does not have its own initializing method. It initial- + izes the same problem in the same way as ConsIndShockSetup, from which it + inherits. + """ + + def prepare_to_calc_EndOfPrdvP(self): + """ + Prepare to calculate end-of-period marginal value by creating an array + of market resources that the agent could have next period, considering + the grid of end-of-period assets and the distribution of shocks he might + experience next period. + + Parameters + ---------- + none + + Returns + ------- + aNrmNow : np.array + A 1D array of end-of-period assets; also stored as attribute of self. + """ + + # We define aNrmNow all the way from BoroCnstNat up to max(self.aXtraGrid) + # even if BoroCnstNat < BoroCnstArt, so we can construct the consumption + # function as the lower envelope of the (by the artificial borrowing con- + # straint) uconstrained consumption function, and the artificially con- + # strained consumption function. + self.aNrmNow = np.asarray(self.aXtraGrid) + self.BoroCnstNat + + return self.aNrmNow + + def m_nrm_next(self, shocks, a_nrm): + """ + Computes normalized market resources of the next period + from income shocks and current normalized market resources. + + Parameters + ---------- + shocks: [float] + Permanent and transitory income shock levels. a_nrm: float + Normalized market assets this period + + Returns + ------- + float + normalized market resources in the next period + """ + return self.Rfree / (self.PermGroFac * shocks[0]) \ + * a_nrm + shocks[1] + + def calc_EndOfPrdvP(self): + """ + Calculate end-of-period marginal value of assets at each point in aNrmNow. + Does so by taking a weighted sum of next period marginal values across + income shocks (in a preconstructed grid self.mNrmNext). + + Parameters + ---------- + none + + Returns + ------- + EndOfPrdvP : np.array + A 1D array of end-of-period marginal value of assets + """ + + def vp_next(shocks, a_nrm): + return shocks[0] ** (-self.CRRA) \ + * self.vPfuncNext(self.m_nrm_next(shocks, a_nrm)) + + EndOfPrdvP = ( + self.DiscFacEff + * self.Rfree + * self.PermGroFac ** (-self.CRRA) + * calc_expectation( + self.IncShkDstn, + vp_next, + self.aNrmNow + ) + ) + + return EndOfPrdvP + + def get_points_for_interpolation(self, EndOfPrdvP, aNrmNow): + """ + Finds interpolation points (c,m) for the consumption function. + + Parameters + ---------- + EndOfPrdvP : np.array + Array of end-of-period marginal values. + aNrmNow : np.array + Array of end-of-period asset values that yield the marginal values + in EndOfPrdvP. + + Returns + ------- + c_for_interpolation : np.array + Consumption points for interpolation. + m_for_interpolation : np.array + Corresponding market resource points for interpolation. + """ + cNrmNow = self.uPinv(EndOfPrdvP) + mNrmNow = cNrmNow + aNrmNow + + # Limiting consumption is zero as m approaches mNrmMin + c_for_interpolation = np.insert(cNrmNow, 0, 0.0, axis=-1) + m_for_interpolation = np.insert(mNrmNow, 0, self.BoroCnstNat, axis=-1) + + # Store these for calcvFunc + self.cNrmNow = cNrmNow + self.mNrmNow = mNrmNow + + return c_for_interpolation, m_for_interpolation + + def use_points_for_interpolation(self, cNrm, mNrm, interpolator): + """ + Constructs a basic solution for this period, including the consumption + function and marginal value function. + + Parameters + ---------- + cNrm : np.array + (Normalized) consumption points for interpolation. + mNrm : np.array + (Normalized) corresponding market resource points for interpolation. + interpolator : function + A function that constructs and returns a consumption function. + + Returns + ------- + solution_now : ConsumerSolution + The solution to this period's consumption-saving problem, with a + consumption function, marginal value function, and minimum m. + """ + # Construct the unconstrained consumption function + cFuncNowUnc = interpolator(mNrm, cNrm) + + # Combine the constrained and unconstrained functions into the true consumption function + # breakpoint() # LowerEnvelope should only be used when BoroCnstArt is true + cFuncNow = LowerEnvelope(cFuncNowUnc, self.cFuncNowCnst, nan_bool=False) + + # Make the marginal value function and the marginal marginal value function + vPfuncNow = MargValueFuncCRRA(cFuncNow, self.CRRA) + + # Pack up the solution and return it + solution_now = ConsumerSolution( + cFunc=cFuncNow, vPfunc=vPfuncNow, mNrmMin=self.mNrmMinNow + ) + + return solution_now + + def make_basic_solution(self, EndOfPrdvP, aNrm, interpolator): + """ + Given end of period assets and end of period marginal value, construct + the basic solution for this period. + + Parameters + ---------- + EndOfPrdvP : np.array + Array of end-of-period marginal values. + aNrm : np.array + Array of end-of-period asset values that yield the marginal values + in EndOfPrdvP. + + interpolator : function + A function that constructs and returns a consumption function. + + Returns + ------- + solution_now : ConsumerSolution + The solution to this period's consumption-saving problem, with a + consumption function, marginal value function, and minimum m. + """ + cNrm, mNrm = self.get_points_for_interpolation(EndOfPrdvP, aNrm) + solution_now = self.use_points_for_interpolation(cNrm, mNrm, interpolator) + + return solution_now + + def add_MPC_and_human_wealth(self, solution): + """ + Take a solution and add human wealth and the bounding MPCs to it. + + Parameters + ---------- + solution : ConsumerSolution + The solution to this period's consumption-saving problem. + + Returns: + ---------- + solution : ConsumerSolution + The solution to this period's consumption-saving problem, but now + with human wealth and the bounding MPCs. + """ + solution.hNrm = self.hNrmNow + solution.MPCmin = self.MPCminNow + solution.MPCmax = self.MPCmaxEff + return solution + + def add_stable_points(self, solution): + """ + Checks necessary conditions for the existence of the individual steady + state and target levels of market resources (see above). + If the conditions are satisfied, computes and adds the stable points + to the solution. + + Parameters + ---------- + solution : ConsumerSolution + Solution to this period's problem, which must have attribute cFunc. + Returns + ------- + solution : ConsumerSolution + Same solution that was passed, but now with attributes mNrmStE and + mNrmTrg, if they exist. + + """ + + # 0. Check if GICRaw holds. If so, then mNrmStE will exist. So, compute it. + # 1. Check if GICNrm holds. If so, then mNrmTrg will exist. So, compute it. + + thorn = (self.Rfree*self.DiscFacEff)**(1/self.CRRA) + + GPFRaw = thorn / self.PermGroFac + self.GPFRaw = GPFRaw + GPFNrm = thorn / self.PermGroFac / np.dot(1/self.PermShkValsNext, self.ShkPrbsNext) + self.GPFNrm = GPFNrm + GICRaw = 1 > thorn/self.PermGroFac + self.GICRaw = GICRaw + GICNrm = 1 > GPFNrm + self.GICNrm = GICNrm + + if GICRaw: + solution = self.add_mNrmStE(solution) # find steady state m, if it exists + if GICNrm: + solution = self.add_mNrmTrg(solution) # find target m, if it exists + + return solution + + def make_linear_cFunc(self, mNrm, cNrm): + """ + Makes a linear interpolation to represent the (unconstrained) consumption function. + + Parameters + ---------- + mNrm : np.array + Corresponding market resource points for interpolation. + cNrm : np.array + Consumption points for interpolation. + + Returns + ------- + cFuncUnc : LinearInterp + The unconstrained consumption function for this period. + """ + cFuncUnc = LinearInterp( + mNrm, cNrm, self.cFuncLimitIntercept, self.cFuncLimitSlope + ) + return cFuncUnc + + def solve(self): + """ + Solves a one period consumption saving problem with risky income. + + Parameters + ---------- + None + + Returns + ------- + solution : ConsumerSolution + The solution to the one period problem. + """ + self.aNrmNow = np.asarray(self.aXtraGrid) + self.BoroCnstNat + aNrm = self.aNrmNow + EndOfPrdvP = self.calc_EndOfPrdvP() + solution = self.make_basic_solution(EndOfPrdvP, aNrm, self.make_linear_cFunc) + solution = self.add_MPC_and_human_wealth(solution) + solution = self.add_stable_points(solution) + + return solution + + +############################################################################### +############################################################################### + + +class ConsIndShockSolver(ConsIndShockSolverBasic): + """ + This class solves a single period of a standard consumption-saving problem. + It inherits from ConsIndShockSolverBasic, adding the ability to perform cubic + interpolation and to calculate the value function. + """ + + def make_cubic_cFunc(self, mNrm, cNrm): + """ + Makes a cubic spline interpolation of the unconstrained consumption + function for this period. + + Parameters + ---------- + mNrm : np.array + Corresponding market resource points for interpolation. + cNrm : np.array + Consumption points for interpolation. + + Returns + ------- + cFuncUnc : CubicInterp + The unconstrained consumption function for this period. + """ + def vpp_next(shocks, a_nrm): + return shocks[0] ** (- self.CRRA - 1.0) \ + * self.vPPfuncNext(self.m_nrm_next(shocks, a_nrm)) + + EndOfPrdvPP = ( + self.DiscFacEff + * self.Rfree + * self.Rfree + * self.PermGroFac ** (-self.CRRA - 1.0) + * calc_expectation( + self.IncShkDstn, + vpp_next, + self.aNrmNow + ) + ) + dcda = EndOfPrdvPP / self.uPP(np.array(cNrm[1:])) + MPC = dcda / (dcda + 1.0) + MPC = np.insert(MPC, 0, self.MPCmaxNow) + + cFuncNowUnc = CubicInterp( + mNrm, cNrm, MPC, self.MPCminNow * self.hNrmNow, self.MPCminNow + ) + return cFuncNowUnc + + def make_EndOfPrdvFunc(self, EndOfPrdvP): + """ + Construct the end-of-period value function for this period, storing it + as an attribute of self for use by other methods. + + Parameters + ---------- + EndOfPrdvP : np.array + Array of end-of-period marginal value of assets corresponding to the + asset values in self.aNrmNow. + + Returns + ------- + none + """ + def v_lvl_next(shocks, a_nrm): + return ( + shocks[0] ** (1.0 - self.CRRA) + * self.PermGroFac ** (1.0 - self.CRRA) + ) * self.vFuncNext(self.m_nrm_next(shocks, a_nrm)) + EndOfPrdv = self.DiscFacEff * calc_expectation( + self.IncShkDstn, v_lvl_next, self.aNrmNow + ) + EndOfPrdvNvrs = self.uinv( + EndOfPrdv + ) # value transformed through inverse utility + EndOfPrdvNvrsP = EndOfPrdvP * self.uinvP(EndOfPrdv) + EndOfPrdvNvrs = np.insert(EndOfPrdvNvrs, 0, 0.0) + EndOfPrdvNvrsP = np.insert( + EndOfPrdvNvrsP, 0, EndOfPrdvNvrsP[0] + ) # This is a very good approximation, vNvrsPP = 0 at the asset minimum + aNrm_temp = np.insert(self.aNrmNow, 0, self.BoroCnstNat) + EndOfPrdvNvrsFunc = CubicInterp(aNrm_temp, EndOfPrdvNvrs, EndOfPrdvNvrsP) + self.EndOfPrdvFunc = ValueFuncCRRA(EndOfPrdvNvrsFunc, self.CRRA) + + def add_vFunc(self, solution, EndOfPrdvP): + """ + Creates the value function for this period and adds it to the solution. + + Parameters + ---------- + solution : ConsumerSolution + The solution to this single period problem, likely including the + consumption function, marginal value function, etc. + EndOfPrdvP : np.array + Array of end-of-period marginal value of assets corresponding to the + asset values in self.aNrmNow. + + Returns + ------- + solution : ConsumerSolution + The single period solution passed as an input, but now with the + value function (defined over market resources m) as an attribute. + """ + self.make_EndOfPrdvFunc(EndOfPrdvP) + solution.vFunc = self.make_vFunc(solution) + return solution + + def make_vFunc(self, solution): + """ + Creates the value function for this period, defined over market resources m. + self must have the attribute EndOfPrdvFunc in order to execute. + + Parameters + ---------- + solution : ConsumerSolution + The solution to this single period problem, which must include the + consumption function. + + Returns + ------- + vFuncNow : ValueFuncCRRA + A representation of the value function for this period, defined over + normalized market resources m: v = vFuncNow(m). + """ + # Compute expected value and marginal value on a grid of market resources + mNrm_temp = self.mNrmMinNow + self.aXtraGrid + cNrmNow = solution.cFunc(mNrm_temp) + aNrmNow = mNrm_temp - cNrmNow + vNrmNow = self.u(cNrmNow) + self.EndOfPrdvFunc(aNrmNow) + vPnow = self.uP(cNrmNow) + + # Construct the beginning-of-period value function + vNvrs = self.uinv(vNrmNow) # value transformed through inverse utility + vNvrsP = vPnow * self.uinvP(vNrmNow) + mNrm_temp = np.insert(mNrm_temp, 0, self.mNrmMinNow) + vNvrs = np.insert(vNvrs, 0, 0.0) + vNvrsP = np.insert( + vNvrsP, 0, self.MPCmaxEff ** (-self.CRRA / (1.0 - self.CRRA)) + ) + MPCminNvrs = self.MPCminNow ** (-self.CRRA / (1.0 - self.CRRA)) + vNvrsFuncNow = CubicInterp( + mNrm_temp, vNvrs, vNvrsP, MPCminNvrs * self.hNrmNow, MPCminNvrs + ) + vFuncNow = ValueFuncCRRA(vNvrsFuncNow, self.CRRA) + return vFuncNow + + def add_vPPfunc(self, solution): + """ + Adds the marginal marginal value function to an existing solution, so + that the next solver can evaluate vPP and thus use cubic interpolation. + + Parameters + ---------- + solution : ConsumerSolution + The solution to this single period problem, which must include the + consumption function. + + Returns + ------- + solution : ConsumerSolution + The same solution passed as input, but with the marginal marginal + value function for this period added as the attribute vPPfunc. + """ + vPPfuncNow = MargMargValueFuncCRRA(solution.cFunc, self.CRRA) + solution.vPPfunc = vPPfuncNow + return solution + + def solve(self): + """ + Solves the single period consumption-saving problem using the method of + endogenous gridpoints. Solution includes a consumption function cFunc + (using cubic or linear splines), a marginal value function vPfunc, a min- + imum acceptable level of normalized market resources mNrmMin, normalized + human wealth hNrm, and bounding MPCs MPCmin and MPCmax. It might also + have a value function vFunc and marginal marginal value function vPPfunc. + + Parameters + ---------- + none + + Returns + ------- + solution : ConsumerSolution + The solution to the single period consumption-saving problem. + """ + # Make arrays of end-of-period assets and end-of-period marginal value + aNrm = self.prepare_to_calc_EndOfPrdvP() + EndOfPrdvP = self.calc_EndOfPrdvP() + + # Construct a basic solution for this period + if self.CubicBool: + solution = self.make_basic_solution( + EndOfPrdvP, aNrm, interpolator=self.make_cubic_cFunc + ) + else: + solution = self.make_basic_solution( + EndOfPrdvP, aNrm, interpolator=self.make_linear_cFunc + ) + + solution = self.add_MPC_and_human_wealth(solution) # add a few things + solution = self.add_stable_points(solution) + + # Add the value function if requested, as well as the marginal marginal + # value function if cubic splines were used (to prepare for next period) + if self.vFuncBool: + solution = self.add_vFunc(solution, EndOfPrdvP) + if self.CubicBool: + solution = self.add_vPPfunc(solution) + return solution + + +#################################################################################################### +#################################################################################################### + + +class ConsKinkedRsolver(ConsIndShockSolver): + """ + A class to solve a single period consumption-saving problem where the interest + rate on debt differs from the interest rate on savings. Inherits from + ConsIndShockSolver, with nearly identical inputs and outputs. The key diff- + erence is that Rfree is replaced by Rsave (a>0) and Rboro (a<0). The solver + can handle Rboro == Rsave, which makes it identical to ConsIndShocksolver, but + it terminates immediately if Rboro < Rsave, as this has a different solution. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one period problem. + IncShkDstn : distribution.Distribution + A discrete + approximation to the income process between the period being solved + and the one immediately following (in solution_next). + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the succeeding period. + DiscFac : float + Intertemporal discount factor for future utility. + CRRA : float + Coefficient of relative risk aversion. + Rboro: float + Interest factor on assets between this period and the succeeding + period when assets are negative. + Rsave: float + Interest factor on assets between this period and the succeeding + period when assets are positive. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt: float or None + Borrowing constraint for the minimum allowable assets to end the + period with. If it is less than the natural borrowing constraint, + then it is irrelevant; BoroCnstArt=None indicates no artificial bor- + rowing constraint. + aXtraGrid: np.array + Array of "extra" end-of-period asset values-- assets above the + absolute minimum acceptable level. + vFuncBool: boolean + An indicator for whether the value function should be computed and + included in the reported solution. + CubicBool: boolean + An indicator for whether the solver should use cubic or linear inter- + polation. + """ + + def __init__( + self, + solution_next, + IncShkDstn, + LivPrb, + DiscFac, + CRRA, + Rboro, + Rsave, + PermGroFac, + BoroCnstArt, + aXtraGrid, + vFuncBool, + CubicBool, + ): + assert ( + Rboro >= Rsave + ), "Interest factor on debt less than interest factor on savings!" + + # Initialize the solver. Most of the steps are exactly the same as in + # the non-kinked-R basic case, so start with that. + ConsIndShockSolver.__init__( + self, + solution_next, + IncShkDstn, + LivPrb, + DiscFac, + CRRA, + Rboro, + PermGroFac, + BoroCnstArt, + aXtraGrid, + vFuncBool, + CubicBool, + ) + + # Assign the interest rates as class attributes, to use them later. + self.Rboro = Rboro + self.Rsave = Rsave + + def make_cubic_cFunc(self, mNrm, cNrm): + """ + Makes a cubic spline interpolation that contains the kink of the unconstrained + consumption function for this period. + + Parameters + ---------- + mNrm : np.array + Corresponding market resource points for interpolation. + cNrm : np.array + Consumption points for interpolation. + + Returns + ------- + cFuncUnc : CubicInterp + The unconstrained consumption function for this period. + """ + # Call the make_cubic_cFunc from ConsIndShockSolver. + cFuncNowUncKink = super().make_cubic_cFunc(mNrm, cNrm) + + # Change the coeffients at the kinked points. + cFuncNowUncKink.coeffs[self.i_kink + 1] = [ + cNrm[self.i_kink], + mNrm[self.i_kink + 1] - mNrm[self.i_kink], + 0, + 0, + ] + + return cFuncNowUncKink + + def add_stable_points(self, solution): + """ + TODO: + Placeholder method for a possible future implementation of stable + points in the kinked R model. For now it simply serves to override + ConsIndShock's method, which does not apply here given the multiple + interest rates. + + Discusson: + - The target and steady state should exist under the same conditions + as in ConsIndShock. + - The ConsIndShock code as it stands can not be directly applied + because it assumes that R is a constant, and in this model R depends + on the level of wealth. + - After allowing for wealth-depending interest rates, the existing + code might work without modification to add the stable points. If not, + it should be possible to find these values by checking within three + distinct intervals: + - From h_min to the lower kink. + - From the lower kink to the upper kink + - From the upper kink to infinity. + the stable points must be in one of these regions. + + """ + return solution + + def prepare_to_calc_EndOfPrdvP(self): + """ + Prepare to calculate end-of-period marginal value by creating an array + of market resources that the agent could have next period, considering + the grid of end-of-period assets and the distribution of shocks he might + experience next period. This differs from the baseline case because + different savings choices yield different interest rates. + + Parameters + ---------- + none + + Returns + ------- + aNrmNow : np.array + A 1D array of end-of-period assets; also stored as attribute of self. + """ + KinkBool = ( + self.Rboro > self.Rsave + ) # Boolean indicating that there is actually a kink. + # When Rboro == Rsave, this method acts just like it did in IndShock. + # When Rboro < Rsave, the solver would have terminated when it was called. + + # Make a grid of end-of-period assets, including *two* copies of a=0 + if KinkBool: + aNrmNow = np.sort( + np.hstack( + (np.asarray(self.aXtraGrid) + self.mNrmMinNow, np.array([0.0, 0.0])) + ) + ) + else: + aNrmNow = np.asarray(self.aXtraGrid) + self.mNrmMinNow + aXtraCount = aNrmNow.size + + # Make tiled versions of the assets grid and income shocks + ShkCount = self.TranShkValsNext.size + aNrm_temp = np.tile(aNrmNow, (ShkCount, 1)) + PermShkVals_temp = (np.tile(self.PermShkValsNext, (aXtraCount, 1))).transpose() + TranShkVals_temp = (np.tile(self.TranShkValsNext, (aXtraCount, 1))).transpose() + ShkPrbs_temp = (np.tile(self.ShkPrbsNext, (aXtraCount, 1))).transpose() + + # Make a 1D array of the interest factor at each asset gridpoint + Rfree_vec = self.Rsave * np.ones(aXtraCount) + if KinkBool: + self.i_kink = ( + np.sum(aNrmNow <= 0) - 1 + ) # Save the index of the kink point as an attribute + Rfree_vec[0: self.i_kink] = self.Rboro + self.Rfree = Rfree_vec + Rfree_temp = np.tile(Rfree_vec, (ShkCount, 1)) + + # Make an array of market resources that we could have next period, + # considering the grid of assets and the income shocks that could occur + mNrmNext = ( + Rfree_temp / (self.PermGroFac * PermShkVals_temp) * aNrm_temp + + TranShkVals_temp + ) + + # Recalculate the minimum MPC and human wealth using the interest factor on saving. + # This overwrites values from set_and_update_values, which were based on Rboro instead. + if KinkBool: + PatFacTop = ( + (self.Rsave * self.DiscFacEff) ** (1.0 / self.CRRA) + ) / self.Rsave + self.MPCminNow = 1.0 / (1.0 + PatFacTop / self.solution_next.MPCmin) + self.hNrmNow = ( + self.PermGroFac + / self.Rsave + * ( + np.dot( + self.ShkPrbsNext, self.TranShkValsNext * self.PermShkValsNext + ) + + self.solution_next.hNrm + ) + ) + + # Store some of the constructed arrays for later use and return the assets grid + self.PermShkVals_temp = PermShkVals_temp + self.ShkPrbs_temp = ShkPrbs_temp + self.mNrmNext = mNrmNext + self.aNrmNow = aNrmNow + return aNrmNow + + +# ============================================================================ +# == Classes for representing types of consumer agents (and things they do) == +# ============================================================================ + +# Make a dictionary to specify a perfect foresight consumer type +init_perfect_foresight = { + 'CRRA': 2.0, # Coefficient of relative risk aversion, + 'Rfree': 1.03, # Interest factor on assets + 'DiscFac': 0.96, # Intertemporal discount factor + 'LivPrb': [0.98], # Survival probability + 'PermGroFac': [1.01], # Permanent income growth factor + 'BoroCnstArt': None, # Artificial borrowing constraint + 'MaxKinks': 400, # Maximum number of grid points to allow in cFunc (should be large) + 'AgentCount': 10000, # Number of agents of this type (only matters for simulation) + 'aNrmInitMean': 0.0, # Mean of log initial assets (only matters for simulation) + 'aNrmInitStd': 1.0, # Standard deviation of log initial assets (only for simulation) + 'pLvlInitMean': 0.0, # Mean of log initial permanent income (only matters for simulation) + # Standard deviation of log initial permanent income (only matters for simulation) + 'pLvlInitStd': 0.0, + # Aggregate permanent income growth factor: portion of PermGroFac attributable to aggregate productivity growth (only matters for simulation) + 'PermGroFacAgg': 1.0, + 'T_age': None, # Age after which simulated agents are automatically killed + 'T_cycle': 1 # Number of periods in the cycle for this agent type +} + + +class PerfForesightConsumerType(AgentType): + """ + A perfect foresight consumer type who has no uncertainty other than mortality. + His problem is defined by a coefficient of relative risk aversion, intertemporal + discount factor, interest factor, an artificial borrowing constraint (maybe) + and time sequences of the permanent income growth rate and survival probability. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods should be solved. + """ + + # Define some universal values for all consumer types + cFunc_terminal_ = LinearInterp([0.0, 1.0], [0.0, 1.0]) # c=m in terminal period + vFunc_terminal_ = LinearInterp([0.0, 1.0], [0.0, 0.0]) # This is overwritten + solution_terminal_ = ConsumerSolution( + cFunc=cFunc_terminal_, + vFunc=vFunc_terminal_, + mNrmMin=0.0, + hNrm=0.0, + MPCmin=1.0, + MPCmax=1.0, + ) + time_vary_ = ["LivPrb", "PermGroFac"] + time_inv_ = ["CRRA", "Rfree", "DiscFac", "MaxKinks", "BoroCnstArt"] + state_vars = ['pLvl', 'PlvlAgg', 'bNrm', 'mNrm', "aNrm"] + shock_vars_ = [] + + def __init__(self, cycles=1, verbose=1, quiet=False, **kwds): + params = init_perfect_foresight.copy() + params.update(kwds) + kwds = params + + # Initialize a basic AgentType + AgentType.__init__( + self, + solution_terminal=deepcopy(self.solution_terminal_), + cycles=cycles, + pseudo_terminal=False, + **kwds + ) + + # Add consumer-type specific objects, copying to create independent versions + self.time_vary = deepcopy(self.time_vary_) + self.time_inv = deepcopy(self.time_inv_) + + self.shock_vars = deepcopy(self.shock_vars_) + self.verbose = verbose + self.quiet = quiet + self.solve_one_period = make_one_period_oo_solver(ConsPerfForesightSolver) + set_verbosity_level((4 - verbose) * 10) + + def pre_solve(self): + self.update_solution_terminal() # Solve the terminal period problem + + # Fill in BoroCnstArt and MaxKinks if they're not specified or are irrelevant. + if not hasattr(self, "BoroCnstArt"): # If no borrowing constraint specified... + self.BoroCnstArt = None # ...assume the user wanted none + if not hasattr(self, "MaxKinks"): + if self.cycles > 0: # If it's not an infinite horizon model... + self.MaxKinks = np.inf # ...there's no need to set MaxKinks + elif self.BoroCnstArt is None: # If there's no borrowing constraint... + self.MaxKinks = np.inf # ...there's no need to set MaxKinks + else: + raise ( + AttributeError( + "PerfForesightConsumerType requires the attribute MaxKinks to be specified when BoroCnstArt is not None and cycles == 0." + ) + ) + + def check_restrictions(self): + """ + A method to check that various restrictions are met for the model class. + """ + if self.DiscFac < 0: + raise Exception("DiscFac is below zero with value: " + str(self.DiscFac)) + + return + + def update_solution_terminal(self): + """ + Update the terminal period solution. This method should be run when a + new AgentType is created or when CRRA changes. + + Parameters + ---------- + none + + Returns + ------- + none + """ + self.solution_terminal.vFunc = ValueFuncCRRA(self.cFunc_terminal_, self.CRRA) + self.solution_terminal.vPfunc = MargValueFuncCRRA(self.cFunc_terminal_, self.CRRA) + self.solution_terminal.vPPfunc = MargMargValueFuncCRRA( + self.cFunc_terminal_, self.CRRA + ) + + def unpack_cFunc(self): + """ DEPRECATED: Use solution.unpack('cFunc') instead. + "Unpacks" the consumption functions into their own field for easier access. + After the model has been solved, the consumption functions reside in the + attribute cFunc of each element of ConsumerType.solution. This method + creates a (time varying) attribute cFunc that contains a list of consumption + functions. + Parameters + ---------- + none + Returns + ------- + none + """ + _log.critical( + "unpack_cFunc is deprecated and it will soon be removed, " + "please use unpack('cFunc') instead." + ) + self.unpack("cFunc") + + def initialize_sim(self): + self.PermShkAggNow = self.PermGroFacAgg # This never changes during simulation + self.state_now['PlvlAgg'] = 1.0 + AgentType.initialize_sim(self) + + def sim_birth(self, which_agents): + """ + Makes new consumers for the given indices. Initialized variables include aNrm and pLvl, as + well as time variables t_age and t_cycle. Normalized assets and permanent income levels + are drawn from lognormal distributions given by aNrmInitMean and aNrmInitStd (etc). + + Parameters + ---------- + which_agents : np.array(Bool) + Boolean array of size self.AgentCount indicating which agents should be "born". + + Returns + ------- + None + """ + # Get and store states for newly born agents + N = np.sum(which_agents) # Number of new consumers to make + self.state_now['aNrm'][which_agents] = Lognormal( + mu=self.aNrmInitMean, + sigma=self.aNrmInitStd, + seed=self.RNG.randint(0, 2 ** 31 - 1), + ).draw(N) + # why is a now variable set here? Because it's an aggregate. + pLvlInitMeanNow = self.pLvlInitMean + np.log( + self.state_now['PlvlAgg'] + ) # Account for newer cohorts having higher permanent income + self.state_now['pLvl'][which_agents] = Lognormal( + pLvlInitMeanNow, + self.pLvlInitStd, + seed=self.RNG.randint(0, 2 ** 31 - 1) + ).draw(N) + self.t_age[which_agents] = 0 # How many periods since each agent was born + self.t_cycle[ + which_agents + ] = 0 # Which period of the cycle each agent is currently in + return None + + def sim_death(self): + """ + Determines which agents die this period and must be replaced. Uses the sequence in LivPrb + to determine survival probabilities for each agent. + + Parameters + ---------- + None + + Returns + ------- + which_agents : np.array(bool) + Boolean array of size AgentCount indicating which agents die. + """ + # Determine who dies + DiePrb_by_t_cycle = 1.0 - np.asarray(self.LivPrb) + DiePrb = DiePrb_by_t_cycle[ + self.t_cycle - 1 + ] # Time has already advanced, so look back one + + # In finite-horizon problems the previous line gives newborns the + # survival probability of the last non-terminal period. This is okay, + # however, since they will be instantly replaced by new newborns if + # they die. + # See: https://github.com/econ-ark/HARK/pull/981 + + DeathShks = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw( + N=self.AgentCount + ) + which_agents = DeathShks < DiePrb + if self.T_age is not None: # Kill agents that have lived for too many periods + too_old = self.t_age >= self.T_age + which_agents = np.logical_or(which_agents, too_old) + return which_agents + + def get_shocks(self): + """ + Finds permanent and transitory income "shocks" for each agent this period. As this is a + perfect foresight model, there are no stochastic shocks: PermShkNow = PermGroFac for each + agent (according to their t_cycle) and TranShkNow = 1.0 for all agents. + + Parameters + ---------- + None + + Returns + ------- + None + """ + PermGroFac = np.array(self.PermGroFac) + self.shocks['PermShk'] = PermGroFac[ + self.t_cycle - 1 + ] # cycle time has already been advanced + self.shocks['TranShk'] = np.ones(self.AgentCount) + + def get_Rfree(self): + """ + Returns an array of size self.AgentCount with self.Rfree in every entry. + + Parameters + ---------- + None + + Returns + ------- + RfreeNow : np.array + Array of size self.AgentCount with risk free interest rate for each agent. + """ + RfreeNow = self.Rfree * np.ones(self.AgentCount) + return RfreeNow + + def transition(self): + pLvlPrev = self.state_prev['pLvl'] + aNrmPrev = self.state_prev['aNrm'] + RfreeNow = self.get_Rfree() + + # Calculate new states: normalized market resources and permanent income level + pLvlNow = pLvlPrev*self.shocks['PermShk'] # Updated permanent income level + # Updated aggregate permanent productivity level + PlvlAggNow = self.state_prev['PlvlAgg']*self.PermShkAggNow + # "Effective" interest factor on normalized assets + ReffNow = RfreeNow/self.shocks['PermShk'] + bNrmNow = ReffNow*aNrmPrev # Bank balances before labor income + mNrmNow = bNrmNow + self.shocks['TranShk'] # Market resources after income + + return pLvlNow, PlvlAggNow, bNrmNow, mNrmNow, None + + def get_controls(self): + """ + Calculates consumption for each consumer of this type using the consumption functions. + + Parameters + ---------- + None + + Returns + ------- + None + """ + cNrmNow = np.zeros(self.AgentCount) + np.nan + MPCnow = np.zeros(self.AgentCount) + np.nan + for t in range(self.T_cycle): + these = t == self.t_cycle + cNrmNow[these], MPCnow[these] = self.solution[t].cFunc.eval_with_derivative( + self.state_now['mNrm'][these] + ) + self.controls['cNrm'] = cNrmNow + + # MPCnow is not really a control + self.MPCnow = MPCnow + return None + + def get_poststates(self): + """ + Calculates end-of-period assets for each consumer of this type. + + Parameters + ---------- + None + + Returns + ------- + None + """ + # should this be "Now", or "Prev"?!? + self.state_now['aNrm'] = self.state_now['mNrm'] - self.controls['cNrm'] + # Useful in some cases to precalculate asset level + self.state_now['aLvl'] = self.state_now['aNrm'] * self.state_now['pLvl'] + + # moves now to prev + super().get_poststates() + + return None + + def check_condition(self, name, test, messages, verbose, verbose_messages=None): + """ + Checks one condition. + + Parameters + ---------- + name : string + Name for the condition. + + test : function(self -> boolean) + A function (of self) which tests the condition + + messages : dict{boolean : string} + A dictiomary with boolean keys containing values + for messages to print if the condition is + true or false. + + verbose_messages : dict{boolean : string} + (Optional) A dictiomary with boolean keys containing values + for messages to print if the condition is + true or false under verbose printing. + """ + self.conditions[name] = test(self) + set_verbosity_level((4 - verbose) * 10) + _log.info(messages[self.conditions[name]].format(self)) + if verbose_messages: + _log.debug(verbose_messages[self.conditions[name]].format(self)) + + def check_AIC(self, verbose=None): + """ + Evaluate and report on the Absolute Impatience Condition + """ + name = "AIC" + def test(agent): return agent.thorn < 1 + + messages = { + True: "The value of the Absolute Patience Factor (APF) for the supplied parameter values satisfies the Absolute Impatience Condition.", + False: "The given type violates the Absolute Impatience Condition with the supplied parameter values; the APF is {0.thorn}", + } + verbose_messages = { + True: " Because the APF < 1, the absolute amount of consumption is expected to fall over time.", + False: " Because the APF > 1, the absolute amount of consumption is expected to grow over time.", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_GICRaw(self, verbose=None): + """ + Evaluate and report on the Growth Impatience Condition for the Perfect Foresight model + """ + name = "GICRaw" + + self.GPFRaw = self.thorn / self.PermGroFac[0] + + def test(agent): return agent.GPFRaw < 1 + + messages = { + True: "The value of the Growth Patience Factor for the supplied parameter values satisfies the Perfect Foresight Growth Impatience Condition.", + False: "The value of the Growth Patience Factor for the supplied parameter values fails the Perfect Foresight Growth Impatience Condition; the GPFRaw is: {0.GPFRaw}", + } + + verbose_messages = { + True: " Therefore, for a perfect foresight consumer, the ratio of individual wealth to permanent income will fall indefinitely.", + False: " Therefore, for a perfect foresight consumer, the ratio of individual wealth to permanent income is expected to grow toward infinity.", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_RIC(self, verbose=None): + """ + Evaluate and report on the Return Impatience Condition + """ + + self.RPF = self.thorn / self.Rfree + + name = "RIC" + def test(agent): return self.RPF < 1 + + messages = { + True: "The value of the Return Patience Factor for the supplied parameter values satisfies the Return Impatience Condition.", + False: "The value of the Return Patience Factor for the supplied parameter values fails the Return Impatience Condition; the factor is {0.RPF}", + } + + verbose_messages = { + True: " Therefore, the limiting consumption function is not c(m)=0 for all m", + False: " Therefore, if the FHWC is satisfied, the limiting consumption function is c(m)=0 for all m.", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_FHWC(self, verbose=None): + """ + Evaluate and report on the Finite Human Wealth Condition + """ + + self.FHWF = self.PermGroFac[0] / self.Rfree + self.cNrmPDV = 1.0 / (1.0 - self.thorn / self.Rfree) + + name = "FHWC" + def test(agent): return self.FHWF < 1 + + messages = { + True: "The Finite Human wealth factor value for the supplied parameter values satisfies the Finite Human Wealth Condition.", + False: "The given type violates the Finite Human Wealth Condition; the Finite Human wealth factor value is {0.FHWF}", + } + + verbose_messages = { + True: " Therefore, the limiting consumption function is not c(m)=Infinity\nand human wealth normalized by permanent income is {0.hNrm}\nand the PDV of future consumption growth is {0.cNrmPDV}", + False: " Therefore, the limiting consumption function is c(m)=Infinity for all m unless the RIC is also violated. If both FHWC and RIC fail and the consumer faces a liquidity constraint, the limiting consumption function is nondegenerate but has a limiting slope of 0. (https://econ-ark.github.io/BufferStockTheory#PFGICRawHoldsFHWCFailsRICFailsDiscuss)", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose) + + def check_conditions(self, verbose=None): + """ + This method checks whether the instance's type satisfies the + Absolute Impatience Condition (AIC), + the Return Impatience Condition (RIC), + the Finite Human Wealth Condition (FHWC), the perfect foresight + model's Growth Impatience Condition (GICRaw) and + Perfect Foresight Finite Value of Autarky Condition (FVACPF). Depending on the configuration of parameter values, some + combination of these conditions must be satisfied in order for the problem to have + a nondegenerate solution. To check which conditions are required, in the verbose mode + a reference to the relevant theoretical literature is made. + + + Parameters + ---------- + verbose : boolean + Specifies different levels of verbosity of feedback. When False, it only reports whether the + instance's type fails to satisfy a particular condition. When True, it reports all results, i.e. + the factor values for all conditions. + + Returns + ------- + None + """ + self.conditions = {} + + self.violated = False + + # This method only checks for the conditions for infinite horizon models + # with a 1 period cycle. If these conditions are not met, we exit early. + if self.cycles != 0 or self.T_cycle > 1: + return + + self.thorn = (self.Rfree * self.DiscFac * self.LivPrb[0]) ** (1 / self.CRRA) + + verbose = self.verbose if verbose is None else verbose + self.check_AIC(verbose) + self.check_GICRaw(verbose) + self.check_RIC(verbose) + self.check_FHWC(verbose) + + if hasattr(self, "BoroCnstArt") and self.BoroCnstArt is not None: + self.violated = not self.conditions["RIC"] + else: + self.violated = not self.conditions["RIC"] or not self.conditions["FHWC"] + + +# Make a dictionary to specify an idiosyncratic income shocks consumer +init_idiosyncratic_shocks = dict( + init_perfect_foresight, + **{ + # assets above grid parameters + "aXtraMin": 0.001, # Minimum end-of-period "assets above minimum" value + "aXtraMax": 20, # Maximum end-of-period "assets above minimum" value + "aXtraNestFac": 3, # Exponential nesting factor when constructing "assets above minimum" grid + "aXtraCount": 48, # Number of points in the grid of "assets above minimum" + "aXtraExtra": [ + None + ], # Some other value of "assets above minimum" to add to the grid, not used + # Income process variables + "PermShkStd": [0.1], # Standard deviation of log permanent income shocks + "PermShkCount": 7, # Number of points in discrete approximation to permanent income shocks + "TranShkStd": [0.1], # Standard deviation of log transitory income shocks + "TranShkCount": 7, # Number of points in discrete approximation to transitory income shocks + "UnempPrb": 0.05, # Probability of unemployment while working + "UnempPrbRet": 0.005, # Probability of "unemployment" while retired + "IncUnemp": 0.3, # Unemployment benefits replacement rate + "IncUnempRet": 0.0, # "Unemployment" benefits when retired + "BoroCnstArt": 0.0, # Artificial borrowing constraint; imposed minimum level of end-of period assets + "tax_rate": 0.0, # Flat income tax rate + "T_retire": 0, # Period of retirement (0 --> no retirement) + "vFuncBool": False, # Whether to calculate the value function during solution + "CubicBool": False, # Use cubic spline interpolation when True, linear interpolation when False + } +) + + +class IndShockConsumerType(PerfForesightConsumerType): + """ + A consumer type with idiosyncratic shocks to permanent and transitory income. + His problem is defined by a sequence of income distributions, survival prob- + abilities, and permanent income growth rates, as well as time invariant values + for risk aversion, discount factor, the interest rate, the grid of end-of- + period assets, and an artificial borrowing constraint. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods should be solved. + """ + + time_inv_ = PerfForesightConsumerType.time_inv_ + [ + "BoroCnstArt", + "vFuncBool", + "CubicBool", + ] + time_inv_.remove( + "MaxKinks" + ) # This is in the PerfForesight model but not ConsIndShock + shock_vars_ = ['PermShk', 'TranShk'] + + def __init__(self, cycles=1, verbose=1, quiet=False, **kwds): + params = init_idiosyncratic_shocks.copy() + params.update(kwds) + + # Initialize a basic AgentType + PerfForesightConsumerType.__init__( + self, cycles=cycles, verbose=verbose, quiet=quiet, **params + ) + + # Add consumer-type specific objects, copying to create independent versions + if (not self.CubicBool) and (not self.vFuncBool): + solver = ConsIndShockSolverBasic + else: # Use the "advanced" solver if either is requested + solver = ConsIndShockSolver + self.solve_one_period = make_one_period_oo_solver(solver) + + self.update() # Make assets grid, income process, terminal solution + + def update_income_process(self): + """ + Updates this agent's income process based on his own attributes. + + Parameters + ---------- + none + + Returns: + ----------- + none + """ + ( + IncShkDstn, + PermShkDstn, + TranShkDstn, + ) = self.construct_lognormal_income_process_unemployment() + self.IncShkDstn = IncShkDstn + self.PermShkDstn = PermShkDstn + self.TranShkDstn = TranShkDstn + self.add_to_time_vary("IncShkDstn", "PermShkDstn", "TranShkDstn") + + def update_assets_grid(self): + """ + Updates this agent's end-of-period assets grid by constructing a multi- + exponentially spaced grid of aXtra values. + + Parameters + ---------- + none + + Returns + ------- + none + """ + aXtraGrid = construct_assets_grid(self) + self.aXtraGrid = aXtraGrid + self.add_to_time_inv("aXtraGrid") + + def update(self): + """ + Update the income process, the assets grid, and the terminal solution. + + Parameters + ---------- + None + + Returns + ------- + None + """ + self.update_income_process() + self.update_assets_grid() + self.update_solution_terminal() + + def reset_rng(self): + """ + Reset the RNG behavior of this type. This method is called automatically + by initialize_sim(), ensuring that each simulation run uses the same sequence + of random shocks; this is necessary for structural estimation to work. + This method extends AgentType.reset_rng() to also reset elements of IncShkDstn. + + Parameters + ---------- + None + + Returns + ------- + None + """ + PerfForesightConsumerType.reset_rng(self) + + # Reset IncShkDstn if it exists (it might not because reset_rng is called at init) + if hasattr(self, "IncShkDstn"): + for dstn in self.IncShkDstn: + dstn.reset() + + def get_shocks(self): + """ + Gets permanent and transitory income shocks for this period. Samples from IncShkDstn for + each period in the cycle. + + Parameters + ---------- + None + + Returns + ------- + None + """ + PermShkNow = np.zeros(self.AgentCount) # Initialize shock arrays + TranShkNow = np.zeros(self.AgentCount) + newborn = self.t_age == 0 + for t in range(self.T_cycle): + these = t == self.t_cycle + N = np.sum(these) + if N > 0: + IncShkDstnNow = self.IncShkDstn[ + t - 1 + ] # set current income distribution + PermGroFacNow = self.PermGroFac[t - 1] # and permanent growth factor + # Get random draws of income shocks from the discrete distribution + IncShks = IncShkDstnNow.draw(N) + + PermShkNow[these] = ( + IncShks[0, :] * PermGroFacNow + ) # permanent "shock" includes expected growth + TranShkNow[these] = IncShks[1, :] + + # That procedure used the *last* period in the sequence for newborns, but that's not right + # Redraw shocks for newborns, using the *first* period in the sequence. Approximation. + N = np.sum(newborn) + if N > 0: + these = newborn + IncShkDstnNow = self.IncShkDstn[0] # set current income distribution + PermGroFacNow = self.PermGroFac[0] # and permanent growth factor + + # Get random draws of income shocks from the discrete distribution + EventDraws = IncShkDstnNow.draw_events(N) + PermShkNow[these] = ( + IncShkDstnNow.X[0][EventDraws] * PermGroFacNow + ) # permanent "shock" includes expected growth + TranShkNow[these] = IncShkDstnNow.X[1][EventDraws] + # PermShkNow[newborn] = 1.0 + TranShkNow[newborn] = 1.0 + + # Store the shocks in self + self.EmpNow = np.ones(self.AgentCount, dtype=bool) + self.EmpNow[TranShkNow == self.IncUnemp] = False + self.shocks['PermShk'] = PermShkNow + self.shocks['TranShk'] = TranShkNow + + def calc_bounding_values(self): + """ + Calculate human wealth plus minimum and maximum MPC in an infinite + horizon model with only one period repeated indefinitely. Store results + as attributes of self. Human wealth is the present discounted value of + expected future income after receiving income this period, ignoring mort- + ality (because your income matters to you only if you are still alive). + The maximum MPC is the limit of the MPC as m --> mNrmMin. The + minimum MPC is the limit of the MPC as m --> infty. + + Parameters + ---------- + None + + Returns + ------- + None + """ + # Unpack the income distribution and get average and worst outcomes + PermShkValsNext = self.IncShkDstn[0][1] + TranShkValsNext = self.IncShkDstn[0][2] + ShkPrbsNext = self.IncShkDstn[0][0] + Ex_IncNext = np.dot(ShkPrbsNext, PermShkValsNext * TranShkValsNext) + PermShkMinNext = np.min(PermShkValsNext) + TranShkMinNext = np.min(TranShkValsNext) + WorstIncNext = PermShkMinNext * TranShkMinNext + WorstIncPrb = np.sum( + ShkPrbsNext[(PermShkValsNext * TranShkValsNext) == WorstIncNext] + ) + + # Calculate human wealth and the infinite horizon natural borrowing constraint + hNrm = (Ex_IncNext * self.PermGroFac[0] / self.Rfree) / ( + 1.0 - self.PermGroFac[0] / self.Rfree + ) + temp = self.PermGroFac[0] * PermShkMinNext / self.Rfree + BoroCnstNat = -TranShkMinNext * temp / (1.0 - temp) + + PatFac = (self.DiscFac * self.LivPrb[0] * self.Rfree) ** ( + 1.0 / self.CRRA + ) / self.Rfree + if BoroCnstNat < self.BoroCnstArt: + MPCmax = 1.0 # if natural borrowing constraint is overridden by artificial one, MPCmax is 1 + else: + MPCmax = 1.0 - WorstIncPrb ** (1.0 / self.CRRA) * PatFac + MPCmin = 1.0 - PatFac + + # Store the results as attributes of self + self.hNrm = hNrm + self.MPCmin = MPCmin + self.MPCmax = MPCmax + + def make_euler_error_func(self, mMax=100, approx_inc_dstn=True): + """ + Creates a "normalized Euler error" function for this instance, mapping + from market resources to "consumption error per dollar of consumption." + Stores result in attribute eulerErrorFunc as an interpolated function. + Has option to use approximate income distribution stored in self.IncShkDstn + or to use a (temporary) very dense approximation. + + Only works on (one period) infinite horizon models at this time, will + be generalized later. + + Parameters + ---------- + mMax : float + Maximum normalized market resources for the Euler error function. + approx_inc_dstn : Boolean + Indicator for whether to use the approximate discrete income distri- + bution stored in self.IncShkDstn[0], or to use a very accurate + discrete approximation instead. When True, uses approximation in + IncShkDstn; when False, makes and uses a very dense approximation. + + Returns + ------- + None + + Notes + ----- + This method is not used by any other code in the library. Rather, it is here + for expository and benchmarking purposes. + """ + # Get the income distribution (or make a very dense one) + if approx_inc_dstn: + IncShkDstn = self.IncShkDstn[0] + else: + TranShkDstn = MeanOneLogNormal(sigma=self.TranShkStd[0]).approx( + N=200, tail_N=50, tail_order=1.3, tail_bound=[0.05, 0.95] + ) + TranShkDstn = add_discrete_outcome_constant_mean( + TranShkDstn, self.UnempPrb, self.IncUnemp + ) + PermShkDstn = MeanOneLogNormal(sigma=self.PermShkStd[0]).approx( + N=200, tail_N=50, tail_order=1.3, tail_bound=[0.05, 0.95] + ) + IncShkDstn = combine_indep_dstns(PermShkDstn, TranShkDstn) + + # Make a grid of market resources + mNowMin = self.solution[0].mNrmMin + 10 ** ( + -15 + ) # add tiny bit to get around 0/0 problem + mNowMax = mMax + mNowGrid = np.linspace(mNowMin, mNowMax, 1000) + + # Get the consumption function this period and the marginal value function + # for next period. Note that this part assumes a one period cycle. + cFuncNow = self.solution[0].cFunc + vPfuncNext = self.solution[0].vPfunc + + # Calculate consumption this period at each gridpoint (and assets) + cNowGrid = cFuncNow(mNowGrid) + aNowGrid = mNowGrid - cNowGrid + + # Tile the grids for fast computation + ShkCount = IncShkDstn[0].size + aCount = aNowGrid.size + aNowGrid_tiled = np.tile(aNowGrid, (ShkCount, 1)) + PermShkVals_tiled = (np.tile(IncShkDstn[1], (aCount, 1))).transpose() + TranShkVals_tiled = (np.tile(IncShkDstn[2], (aCount, 1))).transpose() + ShkPrbs_tiled = (np.tile(IncShkDstn[0], (aCount, 1))).transpose() + + # Calculate marginal value next period for each gridpoint and each shock + mNextArray = ( + self.Rfree / (self.PermGroFac[0] * PermShkVals_tiled) * aNowGrid_tiled + + TranShkVals_tiled + ) + vPnextArray = vPfuncNext(mNextArray) + + # Calculate expected marginal value and implied optimal consumption + ExvPnextGrid = ( + self.DiscFac + * self.Rfree + * self.LivPrb[0] + * self.PermGroFac[0] ** (-self.CRRA) + * np.sum( + PermShkVals_tiled ** (-self.CRRA) * vPnextArray * ShkPrbs_tiled, axis=0 + ) + ) + cOptGrid = ExvPnextGrid ** ( + -1.0 / self.CRRA + ) # This is the 'Endogenous Gridpoints' step + + # Calculate Euler error and store an interpolated function + EulerErrorNrmGrid = (cNowGrid - cOptGrid) / cOptGrid + eulerErrorFunc = LinearInterp(mNowGrid, EulerErrorNrmGrid) + self.eulerErrorFunc = eulerErrorFunc + + def pre_solve(self): + # AgentType.pre_solve(self) + # Update all income process variables to match any attributes that might + # have been changed since `__init__` or `solve()` was last called. + # self.update_income_process() + self.update_solution_terminal() + if not self.quiet: + self.check_conditions(verbose=self.verbose) + + def check_GICNrm(self, verbose=None): + """ + Check Individual Growth Patience Factor. + """ + self.GPFNrm = self.thorn / ( + self.PermGroFac[0] * self.InvEx_PermShkInv + ) # [url]/#GICRawI + + name = "GICRaw" + def test(agent): return agent.GPFNrm <= 1 + + messages = { + True: "\nThe value of the Individual Growth Patience Factor for the supplied parameter values satisfies the Growth Impatience Condition; the value of the GPFNrm is: {0.GPFNrm}", + False: "\nThe given parameter values violate the Normalized Growth Impatience Condition; the GPFNrm is: {0.GPFNrm}", + } + + verbose_messages = { + True: " Therefore, a target level of the individual market resources ratio m exists (see {0.url}/#onetarget for more).\n", + False: " Therefore, a target ratio of individual market resources to individual permanent income does not exist. (see {0.url}/#onetarget for more).\n", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_GICAggLivPrb(self, verbose=None): + name = "GICAggLivPrb" + def test(agent): return agent.GPFAggLivPrb <= 1 + + messages = { + True: "\nThe value of the Mortality Adjusted Aggregate Growth Patience Factor for the supplied parameter values satisfies the Mortality Adjusted Aggregate Growth Imatience Condition; the value of the GPFAggLivPrb is: {0.GPFAggLivPrb}", + False: "\nThe given parameter values violate the Mortality Adjusted Aggregate Growth Imatience Condition; the GPFAggLivPrb is: {0.GPFAggLivPrb}", + } + + verbose_messages = { + # (see {0.url}/#WRIC for more).', + True: " Therefore, a target level of the ratio of aggregate market resources to aggregate permanent income exists.\n", + # (see {0.url}/#WRIC for more).' + False: " Therefore, a target ratio of aggregate resources to aggregate permanent income may not exist.\n", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_WRIC(self, verbose=None): + """ + Evaluate and report on the Weak Return Impatience Condition + [url]/#WRPF modified to incorporate LivPrb + """ + self.WRPF = ( + (self.UnempPrb ** (1 / self.CRRA)) + * (self.Rfree * self.DiscFac * self.LivPrb[0]) ** (1 / self.CRRA) + / self.Rfree + ) + + name = "WRIC" + def test(agent): return agent.WRPF <= 1 + + messages = { + True: "\nThe Weak Return Patience Factor value for the supplied parameter values satisfies the Weak Return Impatience Condition; the WRPF is {0.WRPF}.", + False: "\nThe Weak Return Patience Factor value for the supplied parameter values fails the Weak Return Impatience Condition; the WRPF is {0.WRPF} (see {0.url}/#WRIC for more).", + } + + verbose_messages = { + True: " Therefore, a nondegenerate solution exists if the FVAC is also satisfied. (see {0.url}/#WRIC for more) \n", + False: " Therefore, a nondegenerate solution is not available (see {0.url}/#WRIC for more). \n", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_FVAC(self, verbose=None): + """ + Evaluate and report on the Finite Value of Autarky Condition + Hyperlink to paper: [url]/#Autarky-Value + """ + EpShkuInv = calc_expectation( + self.PermShkDstn[0], + lambda x: x ** (1 - self.CRRA) + ) + + if self.CRRA != 1.0: + uInvEpShkuInv = EpShkuInv ** ( + 1 / (1 - self.CRRA) + ) # The term that gives a utility-consequence-adjusted utility growth + else: + uInvEpShkuInv = 1.0 + + self.uInvEpShkuInv = uInvEpShkuInv + + self.VAF = self.LivPrb[0] * self.DiscFac * self.uInvEpShkuInv + + name = "FVAC" + def test(agent): return agent.VAF <= 1 + + messages = { + True: "\nThe Value of Autarky Factor (VAF) for the supplied parameter values satisfies the Finite Value of Autarky Condition; the VAF is {0.VAF}", + False: "\nThe Value of Autarky Factor (VAF) for the supplied parameter values fails the Finite Value of Autarky Condition; the VAF is {0.VAF}", + } + + verbose_messages = { + True: " Therefore, a nondegenerate solution exists if the WRIC also holds; see {0.url}/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping\n", + False: " Therefore, a nondegenerate solution is not available (see {0.url}/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping\n", + } + verbose = self.verbose if verbose is None else verbose + self.check_condition(name, test, messages, verbose, verbose_messages) + + def check_conditions(self, verbose=None): + """ + This method checks whether the instance's type satisfies the Absolute Impatience Condition (AIC), Weak Return + Impatience Condition (WRIC), Finite Human Wealth Condition (FHWC) and Finite Value of + Autarky Condition (FVAC). When combinations of these conditions are satisfied, the + solution to the problem exhibits different characteristics. (For an exposition of the + conditions, see https://econ-ark.github.io/BufferStockTheory/) + + Parameters + ---------- + verbose : boolean + Specifies different levels of verbosity of feedback. When False, it only reports whether the + instance's type fails to satisfy a particular condition. When True, it reports all results, i.e. + the factor values for all conditions. + + Returns + ------- + None + """ + self.conditions = {} + + # PerfForesightConsumerType.check_conditions(self, verbose=False, verbose_reference=False) + self.violated = False + + if self.cycles != 0 or self.T_cycle > 1: + return + + # For theory, see hyperlink targets to expressions in + # url=https://econ-ark.github.io/BufferStockTheory + # For example, the hyperlink to the relevant section of the paper + self.url = "https://econ-ark.github.io/BufferStockTheory" + # would be referenced below as: + # [url]/#Uncertainty-Modified-Conditions + + self.Ex_PermShkInv = calc_expectation( + self.PermShkDstn[0], lambda x: 1 / x + ) + # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec) + + # [url]/#Pat, adjusted to include mortality + + self.InvEx_PermShkInv = ( + 1 / self.Ex_PermShkInv + ) # $\underline{\psi}$ in the paper (\bar{\isp} in private version) + self.PermGroFacAdj = self.PermGroFac[0] * self.InvEx_PermShkInv # [url]/#PGroAdj + + self.thorn = ((self.Rfree * self.DiscFac)) ** (1 / self.CRRA) + + # self.Ex_RNrm = self.Rfree*Ex_PermShkInv/(self.PermGroFac[0]*self.LivPrb[0]) + self.GPFRaw = self.thorn / (self.PermGroFac[0]) # [url]/#GPF + # Lower bound of aggregate wealth growth if all inheritances squandered + + self.GPFAggLivPrb = self.thorn * self.LivPrb[0] / self.PermGroFac[0] + + self.DiscFacGPFRawMax = ((self.PermGroFac[0]) ** (self.CRRA)) / ( + self.Rfree + ) # DiscFac at growth impatience knife edge + self.DiscFacGPFNrmMax = ( + (self.PermGroFac[0] * self.InvEx_PermShkInv) ** (self.CRRA) + ) / ( + self.Rfree + ) # DiscFac at growth impatience knife edge + self.DiscFacGPFAggLivPrbMax = ((self.PermGroFac[0]) ** (self.CRRA)) / ( + self.Rfree * self.LivPrb[0] + ) # DiscFac at growth impatience knife edge + verbose = self.verbose if verbose is None else verbose + + # self.check_GICRaw(verbose) + self.check_GICNrm(verbose) + self.check_GICAggLivPrb(verbose) + self.check_WRIC(verbose) + self.check_FVAC(verbose) + + self.violated = not self.conditions["WRIC"] or not self.conditions["FVAC"] + + if self.violated: + _log.warning( + '\n[!] For more information on the conditions, see Tables 3 and 4 in "Theoretical Foundations of Buffer Stock Saving" at ' + + self.url + + "/#Factors-Defined-And-Compared" + ) + + _log.warning("GPFRaw = %2.6f " % (self.GPFRaw)) + _log.warning("GPFNrm = %2.6f " % (self.GPFNrm)) + _log.warning("GPFAggLivPrb = %2.6f " % (self.GPFAggLivPrb)) + _log.warning("Thorn = APF = %2.6f " % (self.thorn)) + _log.warning("PermGroFacAdj = %2.6f " % (self.PermGroFacAdj)) + _log.warning("uInvEpShkuInv = %2.6f " % (self.uInvEpShkuInv)) + _log.warning("VAF = %2.6f " % (self.VAF)) + _log.warning("WRPF = %2.6f " % (self.WRPF)) + _log.warning("DiscFacGPFNrmMax = %2.6f " % (self.DiscFacGPFNrmMax)) + _log.warning("DiscFacGPFAggLivPrbMax = %2.6f " % (self.DiscFacGPFAggLivPrbMax)) + + def Ex_Mtp1_over_Ex_Ptp1(self, mNrm): + cNrm = self.solution[-1].cFunc(mNrm) + aNrm = mNrm - cNrm + Ex_Ptp1 = PermGroFac[0] + Ex_bLev_tp1 = aNrm * self.Rfree + Ex_Mtp1 = Ex_bLev_tp1 + return Ex_Mtp1 / Ex_Ptp1 + + def Ex_mtp1(self, mNrm): + cNrm = self.solution[-1].cFunc(mNrm) + aNrm = mNrm - cNrm + Ex_bNrm_tp1 = aNrm * self.Rfree * self.Ex_PermShkInv / self.PermGroFac[0] + Ex_Mtp1 = (Ex_bNrm_tp1 + 1) * Ex_Ptp1 # mean TranShk and PermShk are 1 + return Ex_Mtp1 / Ex_Ptp1 + + def calc_stable_points(self): + """ + If the problem is one that satisfies the conditions required for target ratios of different + variables to permanent income to exist, and has been solved to within the self-defined + tolerance, this method calculates the target values of market resources, consumption, + and assets. + + Parameters + ---------- + None + + Returns + ------- + None + """ + infinite_horizon = cycles_left == 0 + if not infinite_horizon: + _log.warning( + "The calc_stable_points method works only for infinite horizon models." + ) + return + + # = Functions for generating discrete income processes and + # simulated income shocks = + # ======================================================== + + def construct_lognormal_income_process_unemployment(self): + """ + Generates a list of discrete approximations to the income process for each + life period, from end of life to beginning of life. Permanent shocks are mean + one lognormally distributed with standard deviation PermShkStd[t] during the + working life, and degenerate at 1 in the retirement period. Transitory shocks + are mean one lognormally distributed with a point mass at IncUnemp with + probability UnempPrb while working; they are mean one with a point mass at + IncUnempRet with probability UnempPrbRet. Retirement occurs + after t=T_retire periods of working. + + Note 1: All time in this function runs forward, from t=0 to t=T + + Note 2: All parameters are passed as attributes of the input parameters. + + Parameters (passed as attributes of the input parameters) + ---------- + PermShkStd : [float] + List of standard deviations in log permanent income uncertainty during + the agent's life. + PermShkCount : int + The number of approximation points to be used in the discrete approxima- + tion to the permanent income shock distribution. + TranShkStd : [float] + List of standard deviations in log transitory income uncertainty during + the agent's life. + TranShkCount : int + The number of approximation points to be used in the discrete approxima- + tion to the permanent income shock distribution. + UnempPrb : float + The probability of becoming unemployed during the working period. + UnempPrbRet : float + The probability of not receiving typical retirement income when retired. + T_retire : int + The index value for the final working period in the agent's life. + If T_retire <= 0 then there is no retirement. + IncUnemp : float + Transitory income received when unemployed. + IncUnempRet : float + Transitory income received while "unemployed" when retired. + T_cycle : int + Total number of non-terminal periods in the consumer's sequence of periods. + + Returns + ------- + IncShkDstn : [distribution.Distribution] + A list with T_cycle elements, each of which is a + discrete approximation to the income process in a period. + PermShkDstn : [[distribution.Distributiony]] + A list with T_cycle elements, each of which + a discrete approximation to the permanent income shocks. + TranShkDstn : [[distribution.Distribution]] + A list with T_cycle elements, each of which + a discrete approximation to the transitory income shocks. + """ + # Unpack the parameters from the input + PermShkStd = self.PermShkStd + PermShkCount = self.PermShkCount + TranShkStd = self.TranShkStd + TranShkCount = self.TranShkCount + T_cycle = self.T_cycle + T_retire = self.T_retire + UnempPrb = self.UnempPrb + IncUnemp = self.IncUnemp + UnempPrbRet = self.UnempPrbRet + IncUnempRet = self.IncUnempRet + + IncShkDstn = [] # Discrete approximations to income process in each period + PermShkDstn = [] # Discrete approximations to permanent income shocks + TranShkDstn = [] # Discrete approximations to transitory income shocks + + # Fill out a simple discrete RV for retirement, with value 1.0 (mean of shocks) + # in normal times; value 0.0 in "unemployment" times with small prob. + if T_retire > 0: + if UnempPrbRet > 0: + PermShkValsRet = np.array( + [1.0, 1.0] + ) # Permanent income is deterministic in retirement (2 states for temp income shocks) + TranShkValsRet = np.array( + [ + IncUnempRet, + (1.0 - UnempPrbRet * IncUnempRet) / (1.0 - UnempPrbRet), + ] + ) + ShkPrbsRet = np.array([UnempPrbRet, 1.0 - UnempPrbRet]) + else: + PermShkValsRet = np.array([1.0]) + TranShkValsRet = np.array([1.0]) + ShkPrbsRet = np.array([1.0]) + IncShkDstnRet = DiscreteDistribution( + ShkPrbsRet, + [PermShkValsRet, TranShkValsRet], + seed=self.RNG.randint(0, 2 ** 31 - 1), + ) + + # Loop to fill in the list of IncShkDstn random variables. + for t in range(T_cycle): # Iterate over all periods, counting forward + + if T_retire > 0 and t >= T_retire: + # Then we are in the "retirement period" and add a retirement income object. + IncShkDstn.append(deepcopy(IncShkDstnRet)) + PermShkDstn.append([np.array([1.0]), np.array([1.0])]) + TranShkDstn.append([ShkPrbsRet, TranShkValsRet]) + else: + # We are in the "working life" periods. + TranShkDstn_t = MeanOneLogNormal(sigma=TranShkStd[t]).approx( + TranShkCount, tail_N=0 + ) + if UnempPrb > 0: + TranShkDstn_t = add_discrete_outcome_constant_mean( + TranShkDstn_t, p=UnempPrb, x=IncUnemp + ) + PermShkDstn_t = MeanOneLogNormal(sigma=PermShkStd[t]).approx( + PermShkCount, tail_N=0 + ) + + IncShkDstn.append( + combine_indep_dstns( + PermShkDstn_t, + TranShkDstn_t, + seed=self.RNG.randint(0, 2 ** 31 - 1), + ) + ) # mix the independent distributions + PermShkDstn.append(PermShkDstn_t) + TranShkDstn.append(TranShkDstn_t) + return IncShkDstn, PermShkDstn, TranShkDstn + + +# Make a dictionary to specify a "kinked R" idiosyncratic shock consumer +init_kinked_R = dict( + init_idiosyncratic_shocks, + **{ + "Rboro": 1.20, # Interest factor on assets when borrowing, a < 0 + "Rsave": 1.02, # Interest factor on assets when saving, a > 0 + "BoroCnstArt": None, # kinked R is a bit silly if borrowing not allowed + "CubicBool": True, # kinked R is now compatible with linear cFunc and cubic cFunc + "aXtraCount": 48, # ...so need lots of extra gridpoints to make up for it + } +) +del init_kinked_R["Rfree"] # get rid of constant interest factor + + +class KinkedRconsumerType(IndShockConsumerType): + """ + A consumer type that faces idiosyncratic shocks to income and has a different + interest factor on saving vs borrowing. Extends IndShockConsumerType, with + very small changes. Solver for this class is currently only compatible with + linear spline interpolation. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods should be solved. + """ + + time_inv_ = copy(IndShockConsumerType.time_inv_) + time_inv_.remove("Rfree") + time_inv_ += ["Rboro", "Rsave"] + + def __init__(self, cycles=1, **kwds): + params = init_kinked_R.copy() + params.update(kwds) + + # Initialize a basic AgentType + PerfForesightConsumerType.__init__(self, cycles=cycles, **params) + + # Add consumer-type specific objects, copying to create independent versions + self.solve_one_period = make_one_period_oo_solver(ConsKinkedRsolver) + self.update() # Make assets grid, income process, terminal solution + + def pre_solve(self): + # AgentType.pre_solve(self) + self.update_solution_terminal() + + def calc_bounding_values(self): + """ + Calculate human wealth plus minimum and maximum MPC in an infinite + horizon model with only one period repeated indefinitely. Store results + as attributes of self. Human wealth is the present discounted value of + expected future income after receiving income this period, ignoring mort- + ality. The maximum MPC is the limit of the MPC as m --> mNrmMin. The + minimum MPC is the limit of the MPC as m --> infty. This version deals + with the different interest rates on borrowing vs saving. + + Parameters + ---------- + None + + Returns + ------- + None + """ + # Unpack the income distribution and get average and worst outcomes + PermShkValsNext = self.IncShkDstn[0][1] + TranShkValsNext = self.IncShkDstn[0][2] + ShkPrbsNext = self.IncShkDstn[0][0] + Ex_IncNext = calc_expectation( + IncShkDstn, + lambda trans, perm: trans * perm + ) + PermShkMinNext = np.min(PermShkValsNext) + TranShkMinNext = np.min(TranShkValsNext) + WorstIncNext = PermShkMinNext * TranShkMinNext + WorstIncPrb = np.sum( + ShkPrbsNext[(PermShkValsNext * TranShkValsNext) == WorstIncNext] + ) + + # Calculate human wealth and the infinite horizon natural borrowing constraint + hNrm = (Ex_IncNext * self.PermGroFac[0] / self.Rsave) / ( + 1.0 - self.PermGroFac[0] / self.Rsave + ) + temp = self.PermGroFac[0] * PermShkMinNext / self.Rboro + BoroCnstNat = -TranShkMinNext * temp / (1.0 - temp) + + PatFacTop = (self.DiscFac * self.LivPrb[0] * self.Rsave) ** ( + 1.0 / self.CRRA + ) / self.Rsave + PatFacBot = (self.DiscFac * self.LivPrb[0] * self.Rboro) ** ( + 1.0 / self.CRRA + ) / self.Rboro + if BoroCnstNat < self.BoroCnstArt: + MPCmax = 1.0 # if natural borrowing constraint is overridden by artificial one, MPCmax is 1 + else: + MPCmax = 1.0 - WorstIncPrb ** (1.0 / self.CRRA) * PatFacBot + MPCmin = 1.0 - PatFacTop + + # Store the results as attributes of self + self.hNrm = hNrm + self.MPCmin = MPCmin + self.MPCmax = MPCmax + + def make_euler_error_func(self, mMax=100, approx_inc_dstn=True): + """ + Creates a "normalized Euler error" function for this instance, mapping + from market resources to "consumption error per dollar of consumption." + Stores result in attribute eulerErrorFunc as an interpolated function. + Has option to use approximate income distribution stored in self.IncShkDstn + or to use a (temporary) very dense approximation. + + SHOULD BE INHERITED FROM ConsIndShockModel + + Parameters + ---------- + mMax : float + Maximum normalized market resources for the Euler error function. + approx_inc_dstn : Boolean + Indicator for whether to use the approximate discrete income distri- + bution stored in self.IncShkDstn[0], or to use a very accurate + discrete approximation instead. When True, uses approximation in + IncShkDstn; when False, makes and uses a very dense approximation. + + Returns + ------- + None + + Notes + ----- + This method is not used by any other code in the library. Rather, it is here + for expository and benchmarking purposes. + """ + raise NotImplementedError() + + def get_Rfree(self): + """ + Returns an array of size self.AgentCount with self.Rboro or self.Rsave in each entry, based + on whether self.aNrmNow >< 0. + + Parameters + ---------- + None + + Returns + ------- + RfreeNow : np.array + Array of size self.AgentCount with risk free interest rate for each agent. + """ + RfreeNow = self.Rboro * np.ones(self.AgentCount) + RfreeNow[self.state_prev['aNrm'] > 0] = self.Rsave + return RfreeNow + + def check_conditions(self): + """ + This method checks whether the instance's type satisfies the Absolute Impatience Condition (AIC), + the Return Impatience Condition (RIC), the Growth Impatience Condition (GICRaw), the Normalized Growth Impatience Condition (GIC-Nrm), the Weak Return + Impatience Condition (WRIC), the Finite Human Wealth Condition (FHWC) and the Finite Value of + Autarky Condition (FVAC). To check which conditions are relevant to the model at hand, a + reference to the relevant theoretical literature is made. + + Parameters + ---------- + None + + Returns + ------- + None + """ + raise NotImplementedError() + + +def apply_flat_income_tax( + IncShkDstn, tax_rate, T_retire, unemployed_indices=None, transitory_index=2 +): + """ + Applies a flat income tax rate to all employed income states during the working + period of life (those before T_retire). Time runs forward in this function. + + Parameters + ---------- + IncShkDstn : [distribution.Distribution] + The discrete approximation to the income distribution in each time period. + tax_rate : float + A flat income tax rate to be applied to all employed income. + T_retire : int + The time index after which the agent retires. + unemployed_indices : [int] + Indices of transitory shocks that represent unemployment states (no tax). + transitory_index : int + The index of each element of IncShkDstn representing transitory shocks. + + Returns + ------- + IncShkDstn_new : [distribution.Distribution] + The updated income distributions, after applying the tax. + """ + unemployed_indices = ( + unemployed_indices if unemployed_indices is not None else list() + ) + IncShkDstn_new = deepcopy(IncShkDstn) + i = transitory_index + for t in range(len(IncShkDstn)): + if t < T_retire: + for j in range((IncShkDstn[t][i]).size): + if j not in unemployed_indices: + IncShkDstn_new[t][i][j] = IncShkDstn[t][i][j] * (1 - tax_rate) + return IncShkDstn_new + + +# ======================================================= +# ================ Other useful functions =============== +# ======================================================= + + +def construct_assets_grid(parameters): + """ + Constructs the base grid of post-decision states, representing end-of-period + assets above the absolute minimum. + + All parameters are passed as attributes of the single input parameters. The + input can be an instance of a ConsumerType, or a custom Parameters class. + + Parameters + ---------- + aXtraMin: float + Minimum value for the a-grid + aXtraMax: float + Maximum value for the a-grid + aXtraCount: int + Size of the a-grid + aXtraExtra: [float] + Extra values for the a-grid. + exp_nest: int + Level of nesting for the exponentially spaced grid + + Returns + ------- + aXtraGrid: np.ndarray + Base array of values for the post-decision-state grid. + """ + # Unpack the parameters + aXtraMin = parameters.aXtraMin + aXtraMax = parameters.aXtraMax + aXtraCount = parameters.aXtraCount + aXtraExtra = parameters.aXtraExtra + grid_type = "exp_mult" + exp_nest = parameters.aXtraNestFac + + # Set up post decision state grid: + aXtraGrid = None + if grid_type == "linear": + aXtraGrid = np.linspace(aXtraMin, aXtraMax, aXtraCount) + elif grid_type == "exp_mult": + aXtraGrid = make_grid_exp_mult( + ming=aXtraMin, maxg=aXtraMax, ng=aXtraCount, timestonest=exp_nest + ) + else: + raise Exception( + "grid_type not recognized in __init__." + + "Please ensure grid_type is 'linear' or 'exp_mult'" + ) + + # Add in additional points for the grid: + for a in aXtraExtra: + if a is not None: + if a not in aXtraGrid: + j = aXtraGrid.searchsorted(a) + aXtraGrid = np.insert(aXtraGrid, j, a) + + return aXtraGrid + + +# Make a dictionary to specify a lifecycle consumer with a finite horizon + +# Main calibration characteristics +birth_age = 25 +death_age = 90 +adjust_infl_to = 1992 +# Use income estimates from Cagetti (2003) for High-school graduates +education = "HS" +income_calib = Cagetti_income[education] + +# Income specification +income_params = parse_income_spec( + age_min=birth_age, + age_max=death_age, + adjust_infl_to=adjust_infl_to, + **income_calib, + SabelhausSong=True +) + +# Initial distribution of wealth and permanent income +dist_params = income_wealth_dists_from_scf( + base_year=adjust_infl_to, age=birth_age, education=education, wave=1995 +) + +# We need survival probabilities only up to death_age-1, because survival +# probability at death_age is 1. +liv_prb = parse_ssa_life_table( + female=False, cross_sec=True, year=2004, min_age=birth_age, max_age=death_age - 1 +) + +# Parameters related to the number of periods implied by the calibration +time_params = parse_time_params(age_birth=birth_age, age_death=death_age) + +# Update all the new parameters +init_lifecycle = copy(init_idiosyncratic_shocks) +init_lifecycle.update(time_params) +init_lifecycle.update(dist_params) +# Note the income specification overrides the pLvlInitMean from the SCF. +init_lifecycle.update(income_params) +init_lifecycle.update({"LivPrb": liv_prb}) + + +# Make a dictionary to specify an infinite consumer with a four period cycle +init_cyclical = copy(init_idiosyncratic_shocks) +init_cyclical['PermGroFac'] = [1.082251, 2.8, 0.3, 1.1] +init_cyclical['PermShkStd'] = [0.1, 0.1, 0.1, 0.1] +init_cyclical['TranShkStd'] = [0.1, 0.1, 0.1, 0.1] +init_cyclical['LivPrb'] = 4*[0.98] +init_cyclical['T_cycle'] = 4 diff --git a/HARK/ConsumptionSaving/ConsIndShockModel_AgentDicts.py b/HARK/ConsumptionSaving/ConsIndShockModel_AgentDicts.py new file mode 100644 index 000000000..a474d7356 --- /dev/null +++ b/HARK/ConsumptionSaving/ConsIndShockModel_AgentDicts.py @@ -0,0 +1,443 @@ +# -*- coding: utf-8 -*- +from copy import copy, deepcopy +from HARK.datasets.life_tables.us_ssa.SSATools import parse_ssa_life_table +from HARK.datasets.SCF.WealthIncomeDist.SCFDistTools \ + import income_wealth_dists_from_scf +from HARK.Calibration.Income.IncomeTools \ + import (parse_income_spec, parse_time_params, Cagetti_income) + +""" +Define parameters for various Consumer AgentTypes +""" + +init_perfect_foresight_plus = {} + +# The info below is optional at present but may become mandatory as the toolkit evolves +# 'Primitives' define the 'true' model that we think of ourselves as trying to solve +# (the limit as approximation error reaches zero) + +init_perfect_foresight_plus.update( + {'prmtv_par': ['CRRA', 'Rfree', 'DiscFac', 'LivPrb', 'PermGroFac', 'BoroCnstArt', 'PermGroFacAgg', 'T_cycle', 'cycles']}) +# Approximation parameters define the precision of the approximation +# Limiting values for approximation parameters: values such that, as all such parameters approach their limits, +# the approximation gets arbitrarily close to the 'true' model +init_perfect_foresight_plus.update( # In principle, kinks exist all the way to infinity + {'aprox_par': {'MaxKinks': '500'}}) +init_perfect_foresight_plus.update( # In principle, kinks exist all the way to infinity + {'aprox_lim': {'MaxKinks': float('inf')}}) + +# The simulation stge of the problem requires additional parameterization +init_perfect_foresight_plus.update( # The 'primitives' for the simulation + {'prmtv_sim': ['aNrmInitMean', 'aNrmInitStd', 'pLvlInitMean', 'pLvlInitStd']}) +init_perfect_foresight_plus.update({ # Approximation parameters for monte carlo sims + 'sim_mcrlo': ['AgentCount', 'T_age'] +}) +init_perfect_foresight_plus.update({ # Limiting values that define 'true' simulation + 'sim_mcrlo_lim': { + 'AgentCount': 'infinity', + 'T_age': 'infinity' + } +}) + +# Optional more detailed _fcts about various parameters +CRRA_fcts = { + 'about': 'Coefficient of Relative Risk Aversion'} +CRRA_fcts.update({'latexexpr': r'\providecommand{\CRRA}{\rho}\CRRA'}) +CRRA_fcts.update({'_unicode_': 'ρ'}) # \rho is Greek r: relative risk aversion rrr +CRRA_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('CRRA') +# init_perfect_foresight_plus['_fcts'].update({'CRRA': CRRA_fcts}) +init_perfect_foresight_plus.update({'CRRA_fcts': CRRA_fcts}) + +DiscFac_fcts = { + 'about': 'Pure time preference rate'} +DiscFac_fcts.update({'latexexpr': r'\providecommand{\DiscFac}{\beta}\DiscFac'}) +DiscFac_fcts.update({'_unicode_': 'β'}) +DiscFac_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('DiscFac') +# init_perfect_foresight_plus['_fcts'].update({'DiscFac': DiscFac_fcts}) +init_perfect_foresight_plus.update({'DiscFac_fcts': DiscFac_fcts}) + +LivPrb_fcts = { + 'about': 'Probability of survival from this period to next'} +LivPrb_fcts.update({'latexexpr': r'\providecommand{\LivPrb}{\Pi}\LivPrb'}) +LivPrb_fcts.update({'_unicode_': 'Π'}) # \Pi mnemonic: 'Probability of surival' +LivPrb_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('LivPrb') +# init_perfect_foresight_plus['_fcts'].update({'LivPrb': LivPrb_fcts}) +init_perfect_foresight_plus.update({'LivPrb_fcts': LivPrb_fcts}) + +Rfree_fcts = { + 'about': 'Risk free interest factor'} +Rfree_fcts.update({'latexexpr': r'\providecommand{\Rfree}{\mathsf{R}}\Rfree'}) +Rfree_fcts.update({'_unicode_': 'R'}) +Rfree_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('Rfree') +# init_perfect_foresight_plus['_fcts'].update({'Rfree': Rfree_fcts}) +init_perfect_foresight_plus.update({'Rfree_fcts': Rfree_fcts}) + +PermGroFac_fcts = { + 'about': 'Growth factor for permanent income'} +PermGroFac_fcts.update({'latexexpr': r'\providecommand{\PermGroFac}{\Gamma}\PermGroFac'}) +PermGroFac_fcts.update({'_unicode_': 'Γ'}) # \Gamma is Greek G for Growth +PermGroFac_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('PermGroFac') +# init_perfect_foresight_plus['_fcts'].update({'PermGroFac': PermGroFac_fcts}) +init_perfect_foresight_plus.update({'PermGroFac_fcts': PermGroFac_fcts}) + +PermGroFacAgg_fcts = { + 'about': 'Growth factor for aggregate permanent income'} +# PermGroFacAgg_fcts.update({'latexexpr': r'\providecommand{\PermGroFacAgg}{\Gamma}\PermGroFacAgg'}) +# PermGroFacAgg_fcts.update({'_unicode_': 'Γ'}) # \Gamma is Greek G for Growth +PermGroFacAgg_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('PermGroFacAgg') +# init_perfect_foresight_plus['_fcts'].update({'PermGroFacAgg': PermGroFacAgg_fcts}) +init_perfect_foresight_plus.update({'PermGroFacAgg_fcts': PermGroFacAgg_fcts}) + +BoroCnstArt_fcts = { + 'about': 'If not None, maximum future income borrowable (normalized by current permanent income)'} +BoroCnstArt_fcts.update({'latexexpr': r'\providecommand{\BoroCnstArt}{\underline{a}}\BoroCnstArt'}) +BoroCnstArt_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('BoroCnstArt') +# init_perfect_foresight_plus['_fcts'].update({'BoroCnstArt': BoroCnstArt_fcts}) +init_perfect_foresight_plus.update({'BoroCnstArt_fcts': BoroCnstArt_fcts}) + +MaxKinks_fcts = { + 'about': 'PF Constrained model solves to period T-MaxKinks,' + ' where the solution has exactly this many kink points'} +MaxKinks_fcts.update({'prmtv_par': 'False'}) +# init_perfect_foresight_plus['prmtv_par'].append('MaxKinks') +# init_perfect_foresight_plus['_fcts'].update({'MaxKinks': MaxKinks_fcts}) +init_perfect_foresight_plus.update({'MaxKinks_fcts': MaxKinks_fcts}) + +AgentCount_fcts = { + 'about': 'Number of agents to use in baseline Monte Carlo simulation'} +AgentCount_fcts.update( + {'latexexpr': r'\providecommand{\AgentCount}{N}\AgentCount'}) +AgentCount_fcts.update({'sim_mcrlo': 'True'}) +AgentCount_fcts.update({'sim_mcrlo_lim': 'infinity'}) +# init_perfect_foresight_plus['sim_mcrlo'].append('AgentCount') +# init_perfect_foresight_plus['_fcts'].update({'AgentCount': AgentCount_fcts}) +init_perfect_foresight_plus.update({'AgentCount_fcts': AgentCount_fcts}) + +aNrmInitMean_fcts = { + 'about': 'Mean initial population value of aNrm'} +aNrmInitMean_fcts.update({'sim_mcrlo': 'True'}) +aNrmInitMean_fcts.update({'sim_mcrlo_lim': 'infinity'}) +init_perfect_foresight_plus['sim_mcrlo'].append('aNrmInitMean') +# init_perfect_foresight_plus['_fcts'].update({'aNrmInitMean': aNrmInitMean_fcts}) +init_perfect_foresight_plus.update({'aNrmInitMean_fcts': aNrmInitMean_fcts}) + +aNrmInitStd_fcts = { + 'about': 'Std dev of initial population value of aNrm'} +aNrmInitStd_fcts.update({'sim_mcrlo': 'True'}) +init_perfect_foresight_plus['sim_mcrlo'].append('aNrmInitStd') +# init_perfect_foresight_plus['_fcts'].update({'aNrmInitStd': aNrmInitStd_fcts}) +init_perfect_foresight_plus.update({'aNrmInitStd_fcts': aNrmInitStd_fcts}) + +pLvlInitMean_fcts = { + 'about': 'Mean initial population value of log pLvl'} +pLvlInitMean_fcts.update({'sim_mcrlo': 'True'}) +init_perfect_foresight_plus['sim_mcrlo'].append('pLvlInitMean') +# init_perfect_foresight_plus['_fcts'].update({'pLvlInitMean': pLvlInitMean_fcts}) +init_perfect_foresight_plus.update({'pLvlInitMean_fcts': pLvlInitMean_fcts}) + +pLvlInitStd_fcts = { + 'about': 'Mean initial std dev of log ppLvl'} +pLvlInitStd_fcts.update({'sim_mcrlo': 'True'}) +init_perfect_foresight_plus['sim_mcrlo'].append('pLvlInitStd') +# init_perfect_foresight_plus['_fcts'].update({'pLvlInitStd': pLvlInitStd_fcts}) +init_perfect_foresight_plus.update({'pLvlInitStd_fcts': pLvlInitStd_fcts}) + +T_age_fcts = { + 'about': 'Age after which simulated agents are automatically killedl'} +T_age_fcts.update({'sim_mcrlo': 'False'}) +# init_perfect_foresight_plus['_fcts'].update({'T_age': T_age_fcts}) +init_perfect_foresight_plus.update({'T_age_fcts': T_age_fcts}) + +T_cycle_fcts = { + 'about': 'Number of periods in a "cycle" (like, a lifetime) for this agent type'} +# init_perfect_foresight_plus['_fcts'].update({'T_cycle': T_cycle_fcts}) +init_perfect_foresight_plus.update({'T_cycle_fcts': T_cycle_fcts}) + +cycles_fcts = { + 'about': 'Number of times the sequence of periods/stages should be solved'} +# init_perfect_foresight_plus['_fcts'].update({'cycle': cycles_fcts}) +init_perfect_foresight_plus.update({'cycles_fcts': cycles_fcts}) +cycles_fcts.update({'prmtv_par': 'True'}) +init_perfect_foresight_plus['prmtv_par'].append('cycles') + + +# Make a dictionary to specify a perfect foresight consumer type +init_perfect_foresight = { + 'CRRA': 2.0, # Coefficient of relative risk aversion, + 'Rfree': 1.03, # Interest factor on assets + 'DiscFac': 0.96, # Intertemporal discount factor + 'LivPrb': [0.98], # Survival probability + 'PermGroFac': [1.01], # Permanent income growth factor + 'BoroCnstArt': None, # Artificial borrowing constraint + 'T_cycle': 1, # Num of periods in a finite horizon cycle (like, a life cycle) + 'PermGroFacAgg': 1.0, # Aggregate income growth factor (multiplies individual) + 'MaxKinks': None, # Maximum number of grid points to allow in cFunc + 'AgentCount': 10000, # Number of agents of this type (only matters for simulation) + 'aNrmInitMean': 0.0, # Mean of log initial assets (only matters for simulation) + 'aNrmInitStd': 1.0, # Standard deviation of log initial assets (only for simulation) + 'pLvlInitMean': 0.0, # Mean of log initial permanent income (only matters for simulation) + # Standard deviation of log initial permanent income (only matters for simulation) + 'pLvlInitStd': 0.0, + # Aggregate permanent income growth factor: portion of PermGroFac attributable to aggregate productivity growth (only matters for simulation) + 'T_age': None, # Age after which simulated agents are automatically killed + # Optional extra _fcts about the model and its calibration + **init_perfect_foresight_plus +} + +# The info above is necessary and sufficient for defining the consumer +# The info below is supplemental +# Some of it is required for further purposes + +# Parameters required for a (future) matrix-based discretization of the problem +init_idiosyncratic_shocks_plus = {} +init_idiosyncratic_shocks_plus.update({ + 'matrx_par': { + 'mcrlo_aXtraCount': '100', + 'mcrlo_aXtraMin': 0.001, + 'mcrlo_aXtraMax': 20, + }}) +init_idiosyncratic_shocks_plus.update({ + 'matrx_lim': { + 'mcrlo_aXtraCount': float('inf'), + 'mcrlo_aXtraMin': float('inf'), + 'mcrlo_aXtraMax': float('inf') + }}) +init_idiosyncratic_shocks_plus['prmtv_par'] = [] +init_idiosyncratic_shocks_plus['aprox_lim'] = {} + +# add parameters that were not part of perfect foresight model +# Primitives +init_idiosyncratic_shocks_plus['prmtv_par'].append('permShkStd') +init_idiosyncratic_shocks_plus['prmtv_par'].append('tranShkStd') +init_idiosyncratic_shocks_plus['prmtv_par'].append('UnempPrb') +init_idiosyncratic_shocks_plus['prmtv_par'].append('UnempPrbRet') +init_idiosyncratic_shocks_plus['prmtv_par'].append('IncUnempRet') +init_idiosyncratic_shocks_plus['prmtv_par'].append('BoroCnstArt') +init_idiosyncratic_shocks_plus['prmtv_par'].append('tax_rate') +init_idiosyncratic_shocks_plus['prmtv_par'].append('T_retire') + +# Approximation parameters and their limits (if any) +# init_idiosyncratic_shocks_plus['aprox_par'].append('permShkCount') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'permShkCount': 'infinity'}) +# init_idiosyncratic_shocks_plus['aprox_par'].append('tranShkCount') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'tranShkCount': 'infinity'}) +# init_idiosyncratic_shocks_plus['aprox_par'].append('aXtraMin') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'aXtraMin': float('0.0')}) +# init_idiosyncratic_shocks_plus['aprox_par'].append('aXtraMax') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'aXtraMax': float('inf')}) +# init_idiosyncratic_shocks_plus['aprox_par'].append('aXtraNestFac') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'aXtraNestFac': None}) +# init_idiosyncratic_shocks_plus['aprox_par'].append('aXtraCount') +init_idiosyncratic_shocks_plus['aprox_lim'].update({'aXtraCount': None}) + +IncShkDstn_fcts = { + 'about': 'Income Shock Distribution: .X[0] and .X[1] retrieve shocks, .pmf retrieves probabilities'} +IncShkDstn_fcts.update({'py___code': r'construct_lognormal_income_process_unemployment'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'IncShkDstn': IncShkDstn_fcts}) +init_idiosyncratic_shocks_plus.update({'IncShkDstn_fcts': IncShkDstn_fcts}) + +permShkStd_fcts = { + 'about': 'Standard deviation for lognormal shock to permanent income'} +permShkStd_fcts.update({'latexexpr': r'\permShkStd'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'permShkStd': permShkStd_fcts}) +init_idiosyncratic_shocks_plus.update({'permShkStd_fcts': permShkStd_fcts}) + +tranShkStd_fcts = { + 'about': 'Standard deviation for lognormal shock to permanent income'} +tranShkStd_fcts.update({'latexexpr': r'\tranShkStd'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'tranShkStd': tranShkStd_fcts}) +init_idiosyncratic_shocks_plus.update({'tranShkStd_fcts': tranShkStd_fcts}) + +UnempPrb_fcts = { + 'about': 'Probability of unemployment while working'} +UnempPrb_fcts.update({'latexexpr': r'\UnempPrb'}) +UnempPrb_fcts.update({'_unicode_': '℘'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'UnempPrb': UnempPrb_fcts}) +init_idiosyncratic_shocks_plus.update({'UnempPrb_fcts': UnempPrb_fcts}) + +UnempPrbRet_fcts = { + 'about': '"unemployment" in retirement = big medical shock'} +UnempPrbRet_fcts.update({'latexexpr': r'\UnempPrbRet'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'UnempPrbRet': UnempPrbRet_fcts}) +init_idiosyncratic_shocks_plus.update({'UnempPrbRet_fcts': UnempPrbRet_fcts}) + +IncUnemp_fcts = { + 'about': 'Unemployment insurance replacement rate'} +IncUnemp_fcts.update({'latexexpr': r'\IncUnemp'}) +IncUnemp_fcts.update({'_unicode_': 'μ'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'IncUnemp': IncUnemp_fcts}) +init_idiosyncratic_shocks_plus.update({'IncUnemp_fcts': IncUnemp_fcts}) + +IncUnempRet_fcts = { + 'about': 'Size of medical shock (frac of perm inc)'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'IncUnempRet': IncUnempRet_fcts}) +init_idiosyncratic_shocks_plus.update({'IncUnempRet_fcts': IncUnempRet_fcts}) + +tax_rate_fcts = { + 'about': 'Flat income tax rate'} +tax_rate_fcts.update({ + 'about': 'Size of medical shock (frac of perm inc)'}) +# init_idiosyncratic_shocks_plus['_fcts'].update({'tax_rate': tax_rate_fcts}) +init_idiosyncratic_shocks_plus.update({'tax_rate_fcts': tax_rate_fcts}) + +T_retire_fcts = { + 'about': 'Period of retirement (0 --> no retirement)'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'T_retire': T_retire_fcts}) +init_idiosyncratic_shocks_plus.update({'T_retire_fcts': T_retire_fcts}) + +permShkCount_fcts = { + 'about': 'Num of pts in discrete approx to permanent income shock dstn'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'permShkCount': permShkCount_fcts}) +init_idiosyncratic_shocks_plus.update({'permShkCount_fcts': permShkCount_fcts}) + +tranShkCount_fcts = { + 'about': 'Num of pts in discrete approx to transitory income shock dstn'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'tranShkCount': tranShkCount_fcts}) +init_idiosyncratic_shocks_plus.update({'tranShkCount_fcts': tranShkCount_fcts}) + +aXtraMin_fcts = { + 'about': 'Minimum end-of-period "assets above minimum" value'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraMin': aXtraMin_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraMin_fcts': aXtraMin_fcts}) + +aXtraMax_fcts = { + 'about': 'Maximum end-of-period "assets above minimum" value'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraMax': aXtraMax_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraMax_fcts': aXtraMax_fcts}) + +aXtraNestFac_fcts = { + 'about': 'Exponential nesting factor when constructing "assets above minimum" grid'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraNestFac': aXtraNestFac_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraNestFac_fcts': aXtraNestFac_fcts}) + +aXtraCount_fcts = { + 'about': 'Number of points in the grid of "assets above minimum"'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraMax': aXtraCount_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraMax_fcts': aXtraCount_fcts}) + +aXtraCount_fcts = { + 'about': 'Number of points to include in grid of assets above minimum possible'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraCount': aXtraCount_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraCount_fcts': aXtraCount_fcts}) + +aXtraExtra_fcts = { + 'about': 'List of other values of "assets above minimum" to add to the grid (e.g., 10000)'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraExtra': aXtraExtra_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraExtra_fcts': aXtraExtra_fcts}) + +aXtraGrid_fcts = { + 'about': 'Grid of values to add to minimum possible value to obtain actual end-of-period asset grid'} +# init_idiosyncratic_shocks_plus['_fcts'].update({'aXtraGrid': aXtraGrid_fcts}) +init_idiosyncratic_shocks_plus.update({'aXtraGrid_fcts': aXtraGrid_fcts}) + +vFuncBool_fcts = { + 'about': 'Whether to calculate the value function during solution' +} +# init_idiosyncratic_shocks_plus['_fcts'].update({'vFuncBool': vFuncBool_fcts}) +init_idiosyncratic_shocks_plus.update({'vFuncBool_fcts': vFuncBool_fcts}) + +CubicBool_fcts = { + 'about': 'Use cubic spline interpolation when True, linear interpolation when False' +} +# init_idiosyncratic_shocks_plus['_fcts'].update({'CubicBool': CubicBool_fcts}) +init_idiosyncratic_shocks_plus.update({'CubicBool_fcts': CubicBool_fcts}) + +# Make a dictionary to specify an idiosyncratic income shocks consumer +init_idiosyncratic_shocks = dict( + init_perfect_foresight, + **{ + # Income process variables + "permShkStd": [0.1], # Standard deviation of log permanent income shocks + "tranShkStd": [0.1], # Standard deviation of log transitory income shocks + "UnempPrb": 0.05, # Probability of unemployment while working + "UnempPrbRet": 0.005, # Probability of "unemployment" while retired + "IncUnemp": 0.3, # Unemployment benefits replacement rate + "IncUnempRet": 0.0, # "Unemployment" benefits when retired + "BoroCnstArt": 0.0, # Artificial borrowing constraint; imposed minimum level of end-of period assets + "tax_rate": 0.0, # Flat income tax rate + "T_retire": 0, # Period of retirement (0 --> no retirement) + # Parameters governing construction of income process + "permShkCount": 7, # Number of points in discrete approximation to permanent income shocks + "tranShkCount": 7, # Number of points in discrete approximation to transitory income shocks + # parameters governing construction of grid of assets above min value + "aXtraMin": 0.001, # Minimum end-of-period "assets above minimum" value + "aXtraMax": 20, # Maximum end-of-period "assets above minimum" value + "aXtraNestFac": 3, # Exponential nesting factor when constructing "assets above minimum" grid + "aXtraCount": 48, # Number of points in the grid of "assets above minimum" + # list other values of "assets above minimum" to add to the grid (e.g., 10000) + "aXtraExtra": [None], + "vFuncBool": False, # Whether to calculate the value function during solution + "CubicBool": False, # Use cubic spline interpolation when True, linear interpolation when False + **init_idiosyncratic_shocks_plus + } +) + +init_idiosycratic_shocks_no_Rfree = deepcopy(init_idiosyncratic_shocks) +del init_idiosycratic_shocks_no_Rfree["Rfree"] # get rid of constant interest factor + +# Make a dictionary to specify a "kinked R" idiosyncratic shock consumer +init_kinked_R = dict( + init_idiosycratic_shocks_no_Rfree, + **{ + "Rboro": 1.20, # Interest factor on assets when borrowing, a < 0 + "Rsave": 1.02, # Interest factor on assets when saving, a > 0 + "BoroCnstArt": None, # kinked R is a bit silly if borrowing not allowed + "CubicBool": True, # kinked R is now compatible with linear cFunc and cubic cFunc + "aXtraCount": 48, # ...so need lots of extra gridpoints to make up for it + } +) + +# Main calibration characteristics +birth_age = 25 +death_age = 90 +adjust_infl_to = 1992 +# Use income estimates from Cagetti (2003) for High-school graduates +education = "HS" +income_calib = Cagetti_income[education] + +# Income specification +income_params = parse_income_spec( + age_min=birth_age, + age_max=death_age, + adjust_infl_to=adjust_infl_to, + **income_calib, + SabelhausSong=True +) + +# Initial distribution of wealth and permanent income +dist_params = income_wealth_dists_from_scf( + base_year=adjust_infl_to, age=birth_age, education=education, wave=1995 +) + +# We need survival probabilities only up to death_age-1, because survival +# probability at death_age is 1. +liv_prb = parse_ssa_life_table( + female=False, cross_sec=True, year=2004, min_age=birth_age, max_age=death_age + - 1) + +# Parameters related to the number of periods implied by the calibration +time_params = parse_time_params(age_birth=birth_age, age_death=death_age) + +# Update all the new parameters +init_lifecycle = deepcopy(init_idiosyncratic_shocks) +init_lifecycle.update(time_params) +init_lifecycle.update(dist_params) +# Note the income specification overrides the pLvlInitMean from the SCF. +init_lifecycle.update(income_params) +init_lifecycle.update({"LivPrb": liv_prb}) + + +# Make a dictionary to specify an infinite consumer with a four period cycle +init_cyclical = copy(init_idiosyncratic_shocks_plus) +init_cyclical['PermGroFac'] = [1.082251, 2.8, 0.3, 1.1] +init_cyclical['permShkStd'] = [0.1, 0.1, 0.1, 0.1] +init_cyclical['tranShkStd'] = [0.1, 0.1, 0.1, 0.1] +init_cyclical['LivPrb'] = 4*[0.98] +init_cyclical['T_cycle'] = 4 diff --git a/HARK/ConsumptionSaving/ConsIndShockModel_AgentSolve.py b/HARK/ConsumptionSaving/ConsIndShockModel_AgentSolve.py new file mode 100755 index 000000000..74f1d47ee --- /dev/null +++ b/HARK/ConsumptionSaving/ConsIndShockModel_AgentSolve.py @@ -0,0 +1,2385 @@ +# -*- coding: utf-8 -*- +import logging +from builtins import (str, breakpoint) +from copy import deepcopy +from types import SimpleNamespace + +import numpy as np +from numpy import dot as E_dot # easier to type +from numpy.testing import assert_approx_equal +from scipy.optimize import newton as find_zero_newton + +from HARK.ConsumptionSaving.ConsIndShockModelOld \ + import ConsumerSolution as ConsumerSolutionOlder +from HARK.ConsumptionSaving.ConsIndShockModel_Both import ( + define_t_reward, def_utility_CRRA, def_value_funcs, def_value_CRRA, + define_transition +) +from HARK.core import (_log, core_check_condition, MetricObject) +from HARK.distribution import calc_expectation \ + as expect_funcs_across_shocks_given_states +from HARK.interpolation import (CubicInterp, LowerEnvelope, LinearInterp) + + +class agent_stage_solution(MetricObject): + """ + Framework for solution of a single stage of a decision problem. + + A "stage" of a problem is the smallest unit into which it is useful + to break down the problem. Often this will correspond to a time period, + but sometimes a stage may correspond to subcomponents of a problem + which are conceived of as being solved simultaneously but which are + computationally useful to solve sequentially. + + Provides a foundational structure that all models will build on. It must + be specialized and elaborated to solve any particular problem. + + Parameters + ---------- + solution_follows : agent_stage_solution + + Returns + ------- + solution_current : agent_stage_solution + + Elements of the current solution crnt contain, but are not limited to: + Pars : The parameters used in solving this stage of the model + Bilt : Objects constructed and retained from the solution process + Modl : Equations of the model, in the form of the python code + that instantiates the computational solution + + This is broken down into: + + States : predetermined variables at the time of decisions + Controls : variables under control of the decisionmaker + Reward : current payoff as function of states and controls + Transitions : evolution of states + Choices : conditions that determine the agent's choices + + The minimal required element of a solution_current object is + [vFunc] : value function + Bellman value function the agent expects to experience for + behaving according to the dynamically optimal plan over + the remainder of the horizon. + + Solution objects will usually also contain a 'decision rule' (for + example a consumption function), although this is not a requirement. + + Other components of a solution object are: + + stge_kind : dict + Dictionary with info about this solution stage + One required entry keeps track of the nature of the stage: + {'iter_status':'not initialized'}: Before model is set up + {'iter_status':'finished'}: Stopping requirements are satisfied + If such requirements are satisfied, {'tolerance':tolerance} + should exist recording what convergence tolerance was satisfied + {'iter_status':'iterator'}: Status during iteration + solution[0].distance_last records the last distance + {'iter_status':'terminal_partial'}:Bare-bones terminal period/stage + Does not contain all the info needed to begin solution + Solver will augment and replace it with 'iterator' stage + Other uses include keeping track of the nature of the next stage + completed_cycles : integer + The number of cycles of the model solved before this call + solveMethod : str, optional + The name of the solution method to use, e.g. 'EGM' + solverType : str, optional + The name of the type of solver ('HARK', 'Dolo') + eventTiming : str, optional + Clarifies timing of events whose timing might otherwise be ambiguous + messaging_level : int, optional + Controls the amount of information returned to user. Varies by model. + """ + + def __init__(self, *args, + stge_kind=None, + parameters_solver=None, + completed_cycles=0, + **kwds): + if stge_kind is None: + stge_kind = {'iter_status': 'not initialized'} + self.E_Next_ = Nexspectations() # Next given this period/stage choices + self.Ante_E_ = Prospectations() # Before this stage shocks/choices + self.Pars = Parameters() + self.Bilt = Built() + self.Bilt.completed_cycles = completed_cycles + self.Bilt.stge_kind = stge_kind + self.Bilt.parameters_solver = parameters_solver + self.Modl = Modelements() + self.Modl.Transitions = {} + + def define_transitions_possible(self): + # Below: Transition types in their canonical possible order + + # These equations should be used by both solution and simulation code + + # We use an OrderedDict so that the Monte Carlo simulation machinery + # will know the order in which they should be executed + # (even though the Spyder variable explorer seems, confusingly, to be + # unable to show an OrderedDict in its intrinsic order) + + # The name of each equation corresponds to a variable that will be made + # and could be preserved in the simulation (or not) + + # Each status will end up transiting only to one subsequent status + # ("status" = set of state variables with associated decision problem) + # There are multiple possibilities because models may skip many steps + + # Steps can be skipped when the model is one in which nothing happens + # in that step, or what happens is so simple that it can be directly + # captured in a transition equation + + # For example, with no end of stage shocks, you could go directly from + # the "chosen" (after choice) status to the "next_BOP" status + + # Equations that define transitions that affect agent's state + transitions_possible = { # BOP: Beginnning of Problem + 'BOP_to_choice': {}, + 'choice_to_chosen': {}, # or + 'choice_to_next_BOP': {}, + 'chosen_to_EOP': {}, # or + 'chosen_to_next_BOP': {}, # or + 'chosen_to_next_choice': {}, + 'EOP_to_next_BOP': {}, # or + 'EOP_to_next_choice': {}, # EOP: End of Problem/Period + } + + return transitions_possible + + def describe_model_and_calibration(self, messaging_level, quietly): + pass + + +class Built(SimpleNamespace): + """Objects built by solvers during course of solution.""" + + pass + + +class Parameters(SimpleNamespace): + """Parameters (as passed, and exposed). But not modified.""" + + pass + + +class Nexspectations(SimpleNamespace): + """Expectations about future period after current decisions.""" + + pass + + +class Prospectations(SimpleNamespace): + """Expectations prior to the realization of current period shocks.""" + + pass + + +class ValueFunctions(SimpleNamespace): + """Expectations across realization of stochastic shocks.""" + + pass + + +class Modelements(SimpleNamespace): + """Elements of the model in python/HARK code.""" + + pass + + +__all__ = [ + "ConsumerSolutionOlder", + "ConsumerSolution", + "ConsumerSolutionOneNrmStateCRRA", + "ConsPerfForesightSolver", + "ConsIndShockSetup", + "ConsIndShockSolverBasic", + "ConsIndShockSolver", + "ConsIndShockSetup", +] + + +# ConsumerSolution does nothing except add agent_stage_solution +# content to original ConsumerSolutionOlder, and set distance_criteria to cFunc + +class ConsumerSolution(ConsumerSolutionOlder, agent_stage_solution): + __doc__ = ConsumerSolutionOlder.__doc__ + __doc__ += """ + In addition, it inherits the attributes of agent_stage_solution. + """ + # CDC 20210426: + # vPfunc is unbounded so seems a bad choice for distance; here we change + # to cFunc but doing so will require recalibrating some of our tests + # distance_criteria = ["vPfunc"] # Bad b/c vP(0)=inf; should use cFunc + # distance_criteria = ["vFunc.dm"] # Bad b/c vP(0)=inf; should use cFunc + # distance_criteria = ["mNrmTrg"] # mNrmTrg better choice if GICNrm holds + distance_criteria = ["cFunc"] # cFunc if the GIC fails + + def __init__(self, *args, + # TODO: New items below should be in default ConsumerSolution + stge_kind=None, + completed_cycles=0, + parameters_solver=None, + **kwds): + ConsumerSolutionOlder.__init__(self, **kwds) + agent_stage_solution.__init__(self, *args, **kwds) + if stge_kind is None: + stge_kind = dict(iter_status='not initialized') + + +# noinspection PyTypeChecker +class ConsumerSolutionOneNrmStateCRRA(ConsumerSolution): + """ + ConsumerSolution with CRRA utility and geometric discounting. + + Specializes the generic ConsumerSolution object to the case with: + * Constant Relative Risk Aversion (CRRA) utility + * Geometric Discounting of Time Separable Utility + * Normalizing Growth Factors for "Permanent Income" + - At the individual and aggregate levels + * A (potentially nonzero) Probability of Mortality + + and a standard budget constraint involving capital income with a riskfree + rate of return, and noncapital income that grows by a permanent factor + (which is used to normalize the problem). + + The model is specified in such a way that it can accommodate either the + perfect foresight case or the case where noncapital income is subject + to transitory and permanent shocks, and can accommodate an artificial + borrowing constraint specified as a proportion of permanent noncapital + income. + + The class can test for various restrictions on the parameter values of the + model. A suite of minimal restrictions (like, the time preference factor + must be nonnegative) is always evaluated. A set of conditions that + determine infinite horizon charactieristics of the solution can be + evaluated using the `check_conditions` method. (Further information about + the conditions can be found in the documentation for that method.) For + convenience, we repeat below the documentation for the parent + ConsumerSolution of this class, all of which applies here. + + Parameters + ---------- + DiscFac : float + Intertemporal discount factor for future utility. + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the next period. + CRRA : float + Coefficient of relative risk aversion. + Rfree : float + Risk free interest factor on end-of-period assets. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + """ + __doc__ += ConsumerSolution.__doc__ + + def __init__(self, *args, + CRRA=2., DiscFac=0.96, LivPrb=1.0, Rfree=1.03, PermGroFac=1.0, + **kwds): + ConsumerSolution.__init__(self, *args, **kwds) + + self.Pars.DiscFac = DiscFac + self.Pars.LivPrb = LivPrb + self.Pars.CRRA = CRRA + self.Pars.Rfree = Rfree + self.Pars.PermGroFac = PermGroFac + + # These have been moved to Bilt to declutter whiteboard: + del self.hNrm + del self.vPfunc + del self.vPPfunc + del self.MPCmax + del self.MPCmin + + self.Bilt.transitions_possible = self.define_transitions_possible() + + def define_transitions_possible(self): + """ + Construct dictionary containing the possible transition equations. + + Returns + ------- + possible_transitions : dict + Names and definitions of the transitions possible within this + solution object or as an exit from it to the beginning of the next + object. + + """ + # Working backwards from End of Problem + + # Later we can select among the allowed transitions + # First, for model with shocks at Beginning of Problem/Period (BOP): + chosen_to_next_BOP = \ + {'kNrm': 'kNrm = aNrm'} # k_{t+1} = a_{t} + + choice_to_chosen = \ + {'aNrm': 'aNrm = mNrm - cNrm'} # a_{t} = m_{t} - c_{t} + + BOP_to_choice = { + 'RNrm': 'RNrm = Rfree / (PermGroFac * permShk)', + 'bNrm': 'bNrm = kNrm * RNrm', + 'yNrm': 'yNrm = tranShk', + 'mNrm': 'mNrm = bNrm + yNrm'} + + # Now, for model with shocks at End of Problem/Period (EOP) + + chosen_to_next_choice = \ + {'kNrm': 'kNrm = aNrm', + 'RNrm': 'RNrm = Rfree / (PermGroFac * permShk)', + 'bNrm': 'bNrm = kNrm * RNrm', # b_{t} = k_{t} RNrm_{t} + 'yNrm': 'yNrm = tranShk', # y_{t} = \tranShk_{t} + 'mNrm': 'mNrm = bNrm + yNrm'} + + # choice_to_chosen need not be redefined b/c same as defined above + + possible_transitions = \ + {'chosen_to_next_BOP': chosen_to_next_BOP, + 'chosen_to_next_choice': chosen_to_next_choice, + 'choice_to_chosen': choice_to_chosen, + 'BOP_to_choice': BOP_to_choice + } + + return possible_transitions + + def describe_model_and_calibration(self, messaging_level=logging.INFO, + quietly=False): + """ + Log a brief description of the model and its calibration. + + Parameters + ---------- + self : agent_stage_solution + + Solution to the problem described by information for the current + stage found in Bilt and the succeeding stage. + + quietly : boolean, optional + + If true, suppresses all output + + Returns + ------- + None + """ + + crnt = self + Pars, Modl = crnt.Pars, crnt.Modl + Tran = Modl.Transitions + + if not quietly and messaging_level < logging.WARNING: + msg = '\n(quietly=False and messaging_level < logging.WARNING, ' \ + + 'so some model information is provided below):\n' + msg = msg + '\nThe model has the following parameter values:\n' + _log.setLevel(messaging_level) + _log.info(msg) + for key in Pars.__dict__.keys(): + _log.info('\t' + key + ': ' + str(Pars.__dict__[key])) + + msg = "\nThe model's transition equations are:" + _log.info(msg) + for key in Tran.keys(): + _log.info('\n' + key + ' step:') + for eqn_name in Tran[key]['raw_text']: + _log.info('\t' + str(Tran[key]['raw_text'][eqn_name])) + + def check_conditions(self, messaging_level=logging.DEBUG, quietly=False): + """ + Check whether parameters satisfy some possibly interesting conditions. + + ================================================================ + Acronym Condition + ================================================================ + AIC Absolute Impatience Condition + RIC Return Impatience Condition + GIC Growth Impatience Condition + GICLiv GIC adjusting for constant probability of mortality + GICNrm GIC adjusted for uncertainty in permanent income + FHWC Finite Human Wealth Condition + WRIC Weak Return Impatience Condition + FVAC Finite Value of Autarky Condition + ================================================================ + + Depending on the configuration of parameter values, some combination of + these conditions must be satisfied in order for the problem to have + a nondegenerate solution. To check which conditions are required, + in the verbose mode, a reference to the relevant theoretical literature + is made. + + Parameters + ---------- + self : agent_stage_solution + + Solution to the problem described by information for the current + stage found in Bilt and the succeeding stage. + + messaging_level : int, optional + + Controls verbosity of messages. logging.DEBUG is most verbose, + logging.INFO is less verbose, logging.WARNING indicates possible + problems, logging.CRITICAL indicates it is degenerate. + + quietly : boolean, optional + + If true, performs calculations but prints no results + + Returns + ------- + None + """ + crnt = self # A current solution object + + Bilt, Pars = crnt.Bilt, crnt.Pars + + Bilt.conditions = {} # Keep track of truth of conditions + Bilt.degenerate = False # True: solution is degenerate + + self.describe_model_and_calibration(messaging_level, quietly) + if not quietly: + _log.info('\n\nBecause messaging_level is >= logging.INFO, ' + + 'infinite horizon conditions are reported below:\n') + crnt.check_AIC(crnt, messaging_level, quietly) + crnt.check_FHWC(crnt, messaging_level, quietly) + crnt.check_RIC(crnt, messaging_level, quietly) + crnt.check_GICRaw(crnt, messaging_level, quietly) + crnt.check_GICNrm(crnt, messaging_level, quietly) + crnt.check_GICLiv(crnt, messaging_level, quietly) + crnt.check_WRIC(crnt, messaging_level, quietly) + crnt.check_FVAC(crnt, messaging_level, quietly) + + # degenerate flag is True if the model has no nondegenerate solution + if hasattr(Bilt, "BoroCnstArt") and Pars.BoroCnstArt is not None: + if Bilt.FHWC: + Bilt.degenerate = not Bilt.RIC # h finite & patient => c(m)=0 + # If BoroCnstArt exists but RIC fails, limiting soln is c(m)=0 + else: # No BoroCnst; not degenerate if neither c(m)=0 or \infty + if Bilt.FHWC: + Bilt.degenerate = not Bilt.RIC # Finite h requires finite Pat + else: + Bilt.degenerate = Bilt.RIC # infinite h requires impatience + + if Bilt.degenerate: + _log.critical("Under the given parameter values, " + + "the model is degenerate.") + + def check_AIC(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Absolute Impatience Condition.""" + name = "AIC" + + def test(soln): return soln.Bilt.APF < 1 + + messages = { + True: f"\nThe Absolute Patience Factor, APF={soln.Bilt.APF:.5f} satisfies the Absolute Impatience Condition (AIC), APF < 1:\n " + + soln.Bilt.AIC_fcts['urlhandle'], + False: f"\nThe Absolute Patience Factor, APF={soln.Bilt.APF:.5f} violates the Absolute Impatience Condition (AIC), APF < 1:\n " + + soln.Bilt.AIC_fcts['urlhandle'] + } + verbose_messages = { + True: "\n Because the APF < 1, the absolute amount of consumption is expected to fall over time. \n", + False: "\n Because the APF > 1, the absolute amount of consumption is expected to grow over time. \n", + } + + soln.Bilt.AIC = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "APF", soln, quietly) + + # noinspection PyTypeChecker + def check_FVAC(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Finite Value of Autarky Condition.""" + name = "FVAC" + + def test(soln): return soln.Bilt.FVAF < 1 + + messages = { + True: f"\nThe Finite Value of Autarky Factor, FVAF={soln.Bilt.FVAF:.5f} satisfies the Finite Value of Autarky Condition, FVAF < 1:\n " + + soln.Bilt.FVAC_fcts['urlhandle'], + False: f"\nThe Finite Value of Autarky Factor, FVAF={soln.Bilt.FVAF:.5f} violates the Finite Value of Autarky Condition, FVAF:\n " + + soln.Bilt.FVAC_fcts['urlhandle'] + } + verbose_messages = { + True: "\n Therefore, a nondegenerate solution exists if the RIC also holds. (" + soln.Bilt.FVAC_fcts[ + 'urlhandle'] + ")\n", + False: "\n Therefore, a nondegenerate solution exits if the RIC holds, but will not exist if the RIC fails unless the FHWC also fails.\n", + } + + # This is bad enough to report as a warning + if messaging_level == logging.WARNING and quietly is False \ + and soln.Bilt.FVAF > 1: + _log.warning(messages['False']+verbose_messages['False']) + + soln.Bilt.FVAC = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "FVAF", soln, quietly) + + def check_GICRaw(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Growth Impatience Condition.""" + name = "GICRaw" + + def test(soln): return soln.Bilt.GPFRaw < 1 + + messages = { + True: f"\nThe Growth Patience Factor, GPF={soln.Bilt.GPFRaw:.5f} satisfies the Growth Impatience Condition (GIC), GPF < 1:\n " + + soln.Bilt.GICRaw_fcts['urlhandle'], + False: f"\nThe Growth Patience Factor, GPF={soln.Bilt.GPFRaw:.5f} violates the Growth Impatience Condition (GIC), GPF < 1:\n " + + soln.Bilt.GICRaw_fcts['urlhandle'], + } + verbose_messages = { + True: "\n Therefore, for a perfect foresight consumer, the ratio of individual wealth to permanent income is expected to fall indefinitely. \n", + False: "\n Therefore, for a perfect foresight consumer whose parameters satisfy the FHWC, the ratio of individual wealth to permanent income is expected to rise toward infinity. \n" + } + soln.Bilt.GICRaw = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "GPFRaw", soln, quietly) + + # Give them a warning if the model does not satisfy the GIC, + # even if they asked to solve quietly, unless messaging_level is CRITICAL + if quietly is True: # Otherwise they will get the info anyway + if soln.Bilt.GPFRaw > 1: + if messaging_level <= logging.CRITICAL: + _log.warning(messages[False]+verbose_messages[False]) + + def check_GICLiv(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on Mortality Adjusted GIC.""" + name = "GICLiv" + + def test(soln): return soln.Bilt.GPFLiv < 1 + + messages = { + True: f"\nThe Mortality Adjusted Aggregate Growth Patience Factor, GPFLiv={soln.Bilt.GPFLiv:.5f} satisfies the Mortality Adjusted Aggregate Growth Impatience Condition (GICLiv):\n " + + soln.Bilt.GPFLiv_fcts['urlhandle'], + False: f"\nThe Mortality Adjusted Aggregate Growth Patience Factor, GPFLiv={soln.Bilt.GPFLiv:.5f} violates the Mortality Adjusted Aggregate Growth Impatience Condition (GICLiv):\n " + + soln.Bilt.GPFLiv_fcts['urlhandle'], + } + verbose_messages = { + True: "\n Therefore, a target level of the ratio of aggregate market resources to aggregate permanent income exists.\n" + + soln.Bilt.GPFLiv_fcts['urlhandle'] + "\n", + False: "\n Therefore, a target ratio of aggregate resources to aggregate permanent income may not exist. \n" + + soln.Bilt.GPFLiv_fcts['urlhandle'] + "\n", + } + soln.Bilt.GICLiv = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "GPFLiv", soln, quietly) + + # This is important enough to warn them even if quietly == True; unless messaging_level = CRITICAL + if (soln.Bilt.GICLiv == np.False_) and (quietly is True) and (messaging_level < logging.CRITICAL): + _log.warning(messages[False]+verbose_messages[False]) + + def check_RIC(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Return Impatience Condition.""" + name = "RIC" + + def test(soln): return soln.Bilt.RPF < 1 + + messages = { + True: f"\nThe Return Patience Factor, RPF={soln.Bilt.RPF:.5f} satisfies the Return Impatience Condition (RIC), RPF < 1:\n " + + soln.Bilt.RPF_fcts['urlhandle'], + False: f"\nThe Return Patience Factor, RPF={soln.Bilt.RPF:.5f} violates the Return Impatience Condition (RIC), RPF < 1:\n " + + soln.Bilt.RPF_fcts['urlhandle'], + } + verbose_messages = { + True: "\n Therefore, the limiting consumption function is not c(m)=0 for all m\n", + False: "\n Therefore, if the FHWC is satisfied, the limiting consumption function is c(m)=0 for all m.\n", + } + soln.Bilt.RIC = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "RPF", soln, quietly) + + def check_FHWC(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Finite Human Wealth Condition.""" + name = "FHWC" + + def test(soln): return soln.Bilt.FHWF < 1 + + messages = { + True: f"\nThe Finite Human Wealth Factor, FHWF={soln.Bilt.FHWF:.5f} satisfies the Finite Human Wealth Condition (FHWC), FHWF < 1:\n " + + soln.Bilt.FHWC_fcts['urlhandle'], + False: f"\nThe Finite Human Wealth Factor, FHWF={soln.Bilt.FHWF:.5f} violates the Finite Human Wealth Condition (FHWC), FHWF < 1:\n " + + soln.Bilt.FHWC_fcts['urlhandle'], + } + verbose_messages = { + True: f"\n Therefore, the limiting consumption function is not c(m)=Infinity.\n Human wealth normalized by permanent income is {soln.Bilt.hNrmInf:.5f}.\n", + False: "\n Therefore, the limiting consumption function is c(m)=Infinity for all m unless the RIC is also violated.\n If both FHWC and RIC fail and the consumer faces a liquidity constraint, the limiting consumption function is nondegenerate but has a limiting slope of 0. (" + + soln.Bilt.FHWC_fcts['urlhandle'] + ")\n", + } + soln.Bilt.FHWC = core_check_condition(name, test, messages, messaging_level, + verbose_messages, "FHWF", soln, quietly) + + if (messaging_level < logging.CRITICAL) and (soln.Bilt.FHWC == np.False_): + _log.info(messages[False]+verbose_messages[False]) + + def check_GICNrm(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Check Normalized Growth Patience Factor.""" + if not hasattr(soln.Pars, 'IncShkDstn'): + return # GICNrm is same as GIC for PF consumer + + name = "GICNrm" + + def test(soln): return soln.Bilt.GPFNrm <= 1 + + messages = { + True: f"\nThe Normalized Growth Patience Factor GPFNrm, GPFNrm={soln.Bilt.GPFNrm:.5f} satisfies the Normalized Growth Impatience Condition (GICNrm), GPFNrm < 1:\n " + + soln.Bilt.GICNrm_fcts['urlhandle'], + False: f"\nThe Normalized Growth Patience Factor GPFNrm, GPFNrm={soln.Bilt.GPFNrm:.5f} violates the Normalized Growth Impatience Condition (GICNrm), GPFNrm < 1:\n " + + soln.Bilt.GICNrm_fcts['urlhandle'], + } + verbose_messages = { + True: "\n Therefore, a target level of the individual market resources ratio m exists.", + False: "\n Therefore, a target ratio of individual market resources to individual permanent income does not exist. \n" + } + + soln.Bilt.GICNrm = \ + core_check_condition(name, test, messages, messaging_level, + verbose_messages, "GPFNrm", soln, quietly) + + # Warn them their model does not satisfy the GICNrm even if they asked + # for the "quietly" solution -- unless they said "only CRITICAL" + + if (messaging_level < logging.CRITICAL) and (soln.Bilt.GICNrm == np.False_): + _log.info(messages[False]+verbose_messages[False]) + + def check_WRIC(self, soln, messaging_level=logging.DEBUG, quietly=False): + """Evaluate and report on the Weak Return Impatience Condition.""" + if not hasattr(soln, 'IncShkDstn'): + return # WRIC is same as RIC for PF consumer + + name = "WRIC" + + def test(soln): return soln.Bilt.WRPF <= 1 + + messages = { + True: f"\nThe Weak Return Patience Factor, WRPF={soln.Bilt.WRPF:.5f} satisfies the Weak Return Impatience Condition, WRPF < 1:\n " + + soln.Bilt.WRIC_fcts['urlhandle'], + False: f"\nThe Weak Return Patience Factor, WRPF={soln.Bilt.WRPF:.5f} violates the Weak Return Impatience Condition, WRPF < 1:\n " + + soln.Bilt.WRIC_fcts['urlhandle'], + } + + verbose_messages = { + True: "\n Therefore, a nondegenerate solution exists if the FVAC is also satisfied. (" + + soln.Bilt.WRIC_fcts['urlhandle'] + ")\n", + False: "\n Therefore, a nondegenerate solution is not available (" + soln.Bilt.WRIC_fcts[ + 'urlhandle'] + ")\n", + } + soln.Bilt.WRIC = core_check_condition( + name, test, messages, messaging_level, verbose_messages, "WRPF", soln, quietly) + + def mNrmTrg_find(self): + """ + Find value of m at which individual consumer expects m not to change. + + This will exist if the GICNrm holds. + + https://econ-ark.github.io/BufferStockTheory#UniqueStablePoints + + Returns + ------- + The target value mNrmTrg. + """ + m_init_guess = self.Bilt.mNrmMin + self.E_Next_.IncNrmNxt + try: # Find value where argument is zero + self.Bilt.mNrmTrg = find_zero_newton( + self.E_Next_.m_tp1_minus_m_t, + m_init_guess) + except: + self.Bilt.mNrmTrg = None + + return self.Bilt.mNrmTrg + + def mNrmStE_find(self): + """ + Find pseudo Steady-State Equilibrium (normalized) market resources m. + + This is the m at which the consumer + expects level of market resources M to grow at same rate as the level + of permanent income P. + + This will exist if the GIC holds. + + https://econ-ark.github.io/BufferStockTheory#UniqueStablePoints + + Parameters + ---------- + self : ConsumerSolution + Solution to this period's problem, which must have attribute cFunc. + + Returns + ------- + self : ConsumerSolution + Same solution that was passed, but now with attribute mNrmStE. + """ + # Minimum market resources plus E[next income] is okay starting guess + + m_init_guess = self.Bilt.mNrmMin + self.E_Next_.IncNrmNxt + + try: + self.Bilt.mNrmStE = find_zero_newton( + self.E_Next_.permGroShk_tp1_times_m_tp1_Over_m_t_minus_PGro, m_init_guess) + except: + self.Bilt.mNrmStE = None + + # Add mNrmStE to the solution and return it + return self.Bilt.mNrmStE + + +# Until this point, our objects have been "solution" not "solver" objects. To +# a "solution" object, "solver" objects add the tools that can generate a +# solution of that kind. Eventually we aim to have a clear delineation between +# models objects, solution objects, and solvers, so that a model can be +# specified independent of a solution method, a solution can be specified +# independent of a model or solution method, and a solution method can be +# specified that can solve many different models. + +# As a first step in that direction, solver classes do not __init__ themselves +# with the __init__ method of their "parent" solution class. Instead, they +# expect to receive as an argument an instance of a solution object called +# solution_next, and they will construct a solution_current object that begins +# empty and onto which the information describing the model and its solution +# are added step by step. + + +class ConsPerfForesightSolver(ConsumerSolutionOneNrmStateCRRA): + """ + Solve (one period of) perfect foresight CRRA utility consumer problem. + + Augments ConsumerSolutionOneNrmStateCRRA_PF solution object with methods + able to solve a perfect foresight model with those characteristics, + allowing for a bequest motive and either a natural or an artificial + borrowing constraint. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one-period problem. + DiscFac : float + Intertemporal discount factor for future utility. + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the next period. + CRRA : float + Coefficient of relative risk aversion. + Rfree : float + Risk free interest factor on end-of-period assets. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt : float or None + Artificial borrowing constraint, as a multiple of permanent income. + Can be None, indicating no artificial constraint. + MaxKinks : int, optional + Maximum number of kink points to allow in the consumption function; + additional points will be thrown out. Only relevant in infinite + horizon model with artificial borrowing constraint. + """ + + # CDC 20200426: MaxKinks adds a lot of complexity to no evident purpose + # because everything it accomplishes could be done solving a finite horizon + # model (including tests of convergence conditions, which can be invoked + # manually if a user wants them). + def __init__(self, solution_next, DiscFac=0.96, LivPrb=1.0, CRRA=2.0, + Rfree=1.0, PermGroFac=1.0, BoroCnstArt=None, + MaxKinks=None, solverType='HARK', solveMethod='EGM', + eventTiming='EOP', horizon='infinite', *args, + **kwds): + + folw = self.solution_follows = solution_next # abbreviation + + # Do NOT __init__ as a ConsumerSolutionOneNrmStateCRRA object + # even though that is the parent class + # Because this is a SOLVER (which, admittedly, present, can only + # handle that class). But in principle, this is a solver, not a + # solution + + # In principle, a solution need not know its solver + crnt = self.solution_current = \ + ConsumerSolutionOneNrmStateCRRA( + self, DiscFac, LivPrb, CRRA, Rfree, PermGroFac, eventTiming) + + # Get solver parameters and store for later use + # omitting things that are not needed + + Pars = crnt.Pars + Pars.__dict__.update( + {k: v for k, v in {**kwds, **locals()}.items() + if k not in {'self', 'solution_next', 'kwds', 'solution_follows', + 'folw', 'crnt', 'Pars'}}) + + # 'terminal' solution should replace pseudo_terminal: + if hasattr(folw.Bilt, 'stge_kind') and \ + folw.Bilt.stge_kind['iter_status'] == 'terminal_partial': + crnt.Bilt = deepcopy(folw.Bilt) + + # links for docs; urls are used when "fcts" are added + self._url_doc_for_solver_get() + + return + + def _url_doc_for_solver_get(self): + # Generate a url that will locate the documentation + self.class_name = self.__class__.__name__ + self.solution_current.Bilt.url_ref = self.url_ref = \ + "https://econ-ark.github.io/BufferStockTheory" + self.solution_current.Bilt.urlroot = self.urlroot = \ + self.url_ref + '/#' + self.solution_current.Bilt.url_doc = self.url_doc = \ + "https://hark.readthedocs.io/en/latest/search.html?q=" + \ + self.class_name + "&check_keywords=yes&area=default#" + + def from_chosen_states_make_continuation_E_Next_(self, crnt): + """ + Construct expectations of useful objects from post-choice status. + + Parameters + ---------- + crnt : agent_stage_solution + The solution to the problem without the expectations info. + + Returns + ------- + crnt : agent_stage_solution + The given solution, with the relevant namespaces updated to + contain the constructed info. + """ + self.build_facts_infhor() + crnt = self.build_facts_recursive() + + # Reduce cluttered formulae with local aliases + E_Next_, tp1 = crnt.E_Next_, self.solution_follows + Bilt, Pars = crnt.Bilt, crnt.Pars + Rfree, PermGroFac, DiscLiv = Pars.Rfree, Pars.PermGroFac, Bilt.DiscLiv + + CRRA = tp1.vFunc.CRRA + + # Omit first and last pts; they define extrapo below and above kinks + Bilt.mNrm_kinks_tp1 = mNrm_kinks_tp1 = tp1.cFunc.x_list[:-1][1:] + Bilt.cNrm_kinks_tp1 = cNrm_kinks_tp1 = tp1.cFunc.y_list[:-1][1:] + Bilt.vNrm_kinks_tp1 = vNrm_kinks_tp1 = tp1.vFunc(mNrm_kinks_tp1) + + # Calculate end-of-this-period aNrm vals that would reach those mNrm's + # There are no shocks in the PF model, so tranShkMin = tranShk = 1.0 + bNrm_kinks_tp1 = (mNrm_kinks_tp1 - tp1.Bilt.tranShkMin) + aNrm_kinks = bNrm_kinks_tp1 * (PermGroFac / Rfree) + + crnt.Bilt.aNrmGrid = aNrm_kinks + + # Level and first derivative of expected value from aNrmGrid points + v_0 = DiscLiv * \ + PermGroFac ** (1 - CRRA) * vNrm_kinks_tp1 + v_1 = DiscLiv * \ + PermGroFac ** (0 - CRRA) * tp1.Bilt.u.dc(cNrm_kinks_tp1) * Rfree + + c_0 = cNrm_kinks_tp1 + + E_Next_.given_shocks = np.array([v_0, v_1, c_0]) + + # Make positions of precomputed objects easy to reference + E_Next_.v0_pos, E_Next_.v1_pos = 0, 1 + E_Next_.c0_pos = 3 + + return crnt + + def make_cFunc_PF(self): + """ + Make (piecewise linear) consumption function for this period. + + See PerfForesightConsumerType.ipynb notebook for derivations. + """ + # Reduce cluttered formulae with local aliases + crnt, tp1 = self.solution_current, self.solution_follows + Bilt, Pars, E_Next_ = crnt.Bilt, crnt.Pars, crnt.E_Next_ + Rfree, PermGroFac, MPCmin = Pars.Rfree, Pars.PermGroFac, Bilt.MPCmin + + BoroCnstArt, DiscLiv, BoroCnstNat = \ + Pars.BoroCnstArt, Bilt.DiscLiv, Bilt.BoroCnstNat + + u, u.Nvrs, u.dc.Nvrs = Bilt.u, Bilt.u.Nvrs, Bilt.u.dc.Nvrs + CRRA_tp1 = tp1.Bilt.vFunc.CRRA + + # define yNrm_tp1 to make formulas below easier to read + yNrm_tp1 = tp1.Bilt.tranShkMin # in PF model tranShk[Min,Max] = 1.0 + + if BoroCnstArt is None: + BoroCnstArt = -np.inf + + # Whichever constraint is tighter is the relevant one + BoroCnst = max(BoroCnstArt, BoroCnstNat) + + # Translate t+1 constraints into their consequences for t + # Endogenous Gridpoints steps: + # c today yielding u' equal to discounted u' from each kink in t+1 + cNrm_kinks = crnt.Bilt.u.dc.Nvrs(E_Next_.given_shocks[E_Next_.v1_pos]) + mNrm_kinks = Bilt.aNrmGrid + cNrm_kinks # Corresponding m + + # Corresponding value and inverse value + vNrm_kinks = E_Next_.given_shocks[E_Next_.v0_pos] + vInv_kinks = u.Nvrs(vNrm_kinks) + + # vAdd used later to add some new points; should add zero to existing + vAdd_kinks = mNrm_kinks - mNrm_kinks # makes zero array of useful size + + mNrmMin_tp1 = yNrm_tp1 + BoroCnst * (Rfree / PermGroFac) + + # by t_E_ here we mean "discounted back to period t" + t_E_v_tp1_at_mNrmMin_tp1 = \ + (DiscLiv * PermGroFac ** (1 - CRRA_tp1) * tp1.vFunc(mNrmMin_tp1)) + + t_E_v1_tp1_at_mNrmMin_tp1 = \ + (((Rfree * DiscLiv) * (PermGroFac ** (-CRRA_tp1)) + ) * tp1.vFunc.dm(mNrmMin_tp1)) + + # h is the 'horizon': h_t(m_t) is the number of periods it will take + # before you hit the constraint, after which you remain constrained + + # The maximum h in a finite horizon model + # is the remaining number of periods of life: h = T - t + + # If the consumer is sufficiently impatient, there will be levels of + # m from which the optimal plan will be to run down existing wealth + # over some horizon less than T - t, and for the remainder of the + # horizon to set consumption equal to income + + # In a given period t, it will be optimal to spend all resources + # whenever the marginal utility of doing so exceeds the marginal + # utility yielded by receiving the minimum possible income next + # period: u'(m_t) > (discounted) u'(c(y_{t+1})) + + # "cusp" is name for where current period constraint stops binding + cNrm_cusp = u.dc.Nvrs(t_E_v1_tp1_at_mNrmMin_tp1) + vNrm_cusp = Bilt.u(cNrm_cusp) + t_E_v_tp1_at_mNrmMin_tp1 + vAdd_cusp = t_E_v_tp1_at_mNrmMin_tp1 + vInv_cusp = u.Nvrs(vNrm_cusp) + mNrm_cusp = cNrm_cusp + BoroCnst + + # cusp today vs today's implications of future constraints + if mNrm_cusp >= mNrm_kinks[-1]: # tighter than the tightest existing + mNrm_kinks = np.array([mNrm_cusp]) # looser kinka are irrelevant + cNrm_kinks = np.array([cNrm_cusp]) # forget about them all + vNrm_kinks = np.array([vNrm_cusp]) + vInv_kinks = np.array([vInv_cusp]) + vAdd_kinks = np.array([vAdd_cusp]) + else: # keep today's implications of future kinks that matter today + first_reachable = np.where(mNrm_kinks >= mNrm_cusp)[0][-1] + if first_reachable < mNrm_kinks.size - 1: # Keep binding pts + mNrm_kinks = mNrm_kinks[first_reachable:-1] + cNrm_kinks = cNrm_kinks[first_reachable:-1] + vInv_kinks = vInv_kinks[first_reachable:-1] + vAdd_kinks = vAdd_kinks[first_reachable:-1] + # Add the new kink introduced by today's constraint + mNrm_kinks = np.insert(mNrm_kinks, 0, mNrm_cusp) + cNrm_kinks = np.insert(cNrm_kinks, 0, cNrm_cusp) + vNrm_kinks = np.insert(vNrm_kinks, 0, vNrm_cusp) + + # Add a point to construct cFunc, vFunc as PF solution beyond last kink + mNrmGrid_unconst = np.append(mNrm_kinks, mNrm_kinks[-1] + 1) # m + 1 + cNrmGrid_unconst = np.append(cNrm_kinks, cNrm_kinks[-1] + 1*MPCmin) + mNrmGrid = np.append([BoroCnst], mNrmGrid_unconst) + cNrmGrid = np.append(0., cNrmGrid_unconst) + + self.cFunc = self.solution_current.cFunc = Bilt.cFunc = \ + LinearInterp(mNrmGrid, cNrmGrid) + + def def_value(self): + """ + Build value function and store results in Modl.value. + + Returns + ------- + soln : solution object with value functions attached + + """ + return def_value_CRRA(self.solution_current, + self.solution_current.Pars.CRRA) + + def build_facts_infhor(self): + """ + Calculate facts useful for characterizing infinite horizon models. + + Returns + ------- + solution : ConsumerSolution + The given solution, with the relevant namespaces updated to + contain the constructed info. + """ + crnt = self.solution_current # current + Bilt, Pars, E_Next_ = crnt.Bilt, crnt.Pars, crnt.E_Next_ + + urlroot = Bilt.urlroot + Bilt.DiscLiv = Pars.DiscFac * Pars.LivPrb + # givens are not changed by calculations below; Bilt and E_Next_ are + givens = {**Pars.__dict__} + + APF_fcts = { + 'about': 'Absolute Patience Factor' + } + py___code = '((Rfree * DiscLiv) ** (1.0 / CRRA))' + Bilt.APF = APF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + APF_fcts.update({'latexexpr': r'\APF'}) + APF_fcts.update({'_unicode_': r'Þ'}) + APF_fcts.update({'urlhandle': urlroot + 'APF'}) + APF_fcts.update({'py___code': py___code}) + APF_fcts.update({'value_now': APF}) + Bilt.APF_fcts = APF_fcts + + AIC_fcts = { + 'about': 'Absolute Impatience Condition' + } + AIC_fcts.update({'latexexpr': r'\AIC'}) + AIC_fcts.update({'urlhandle': urlroot + 'AIC'}) + AIC_fcts.update({'py___code': 'test: APF < 1'}) + Bilt.AIC_fcts = AIC_fcts + + RPF_fcts = { + 'about': 'Return Patience Factor' + } + py___code = 'APF / Rfree' + Bilt.RPF = RPF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + RPF_fcts.update({'latexexpr': r'\RPF'}) + RPF_fcts.update({'_unicode_': r'Þ_R'}) + RPF_fcts.update({'urlhandle': urlroot + 'RPF'}) + RPF_fcts.update({'py___code': py___code}) + RPF_fcts.update({'value_now': RPF}) + Bilt.RPF_fcts = RPF_fcts + + RIC_fcts = { + 'about': 'Growth Impatience Condition' + } + RIC_fcts.update({'latexexpr': r'\RIC'}) + RIC_fcts.update({'urlhandle': urlroot + 'RIC'}) + RIC_fcts.update({'py___code': 'test: RPF < 1'}) + Bilt.RIC_fcts = RIC_fcts + + GPFRaw_fcts = { + 'about': 'Growth Patience Factor' + } + py___code = 'APF / PermGroFac' + Bilt.GPFRaw = GPFRaw = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + GPFRaw_fcts.update({'latexexpr': r'\GPFRaw'}) + GPFRaw_fcts.update({'_unicode_': r'Þ_Γ'}) + GPFRaw_fcts.update({'urlhandle': urlroot + 'GPFRaw'}) + GPFRaw_fcts.update({'py___code': py___code}) + GPFRaw_fcts.update({'value_now': GPFRaw}) + Bilt.GPFRaw_fcts = GPFRaw_fcts + + GICRaw_fcts = { + 'about': 'Growth Impatience Condition' + } + GICRaw_fcts.update({'latexexpr': r'\GICRaw'}) + GICRaw_fcts.update({'urlhandle': urlroot + 'GICRaw'}) + GICRaw_fcts.update({'py___code': 'test: GPFRaw < 1'}) + Bilt.GICRaw_fcts = GICRaw_fcts + + GPFLiv_fcts = { + 'about': 'Mortality-Adjusted Growth Patience Factor' + } + py___code = 'APF * LivPrb / PermGroFac' + Bilt.GPFLiv = GPFLiv = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + GPFLiv_fcts.update({'latexexpr': r'\GPFLiv'}) + GPFLiv_fcts.update({'urlhandle': urlroot + 'GPFLiv'}) + GPFLiv_fcts.update({'py___code': py___code}) + GPFLiv_fcts.update({'value_now': GPFLiv}) + Bilt.GPFLiv_fcts = GPFLiv_fcts + + GICLiv_fcts = { + 'about': 'Growth Impatience Condition' + } + GICLiv_fcts.update({'latexexpr': r'\GICLiv'}) + GICLiv_fcts.update({'urlhandle': urlroot + 'GICLiv'}) + GICLiv_fcts.update({'py___code': 'test: GPFLiv < 1'}) + Bilt.GICLiv_fcts = GICLiv_fcts + + RNrm_PF_fcts = { + 'about': 'Growth-Normalized PF Return Factor' + } + py___code = 'Rfree/PermGroFac' + E_Next_.RNrm_PF = RNrm_PF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + RNrm_PF_fcts.update({'latexexpr': r'\PFRNrm'}) + RNrm_PF_fcts.update({'_unicode_': r'R/Γ'}) + RNrm_PF_fcts.update({'py___code': py___code}) + RNrm_PF_fcts.update({'value_now': RNrm_PF}) + E_Next_.RNrm_PF_fcts = RNrm_PF_fcts + + Inv_RNrm_PF_fcts = { + 'about': 'Inv of Growth-Normalized PF Return Factor' + } + py___code = '1 / RNrm_PF' + E_Next_.Inv_RNrm_PF = Inv_RNrm_PF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + Inv_RNrm_PF_fcts.update({'latexexpr': r'\InvPFRNrm'}) + Inv_RNrm_PF_fcts.update({'_unicode_': r'Γ/R'}) + Inv_RNrm_PF_fcts.update({'py___code': py___code}) + Inv_RNrm_PF_fcts.update({'value_now': Inv_RNrm_PF}) + E_Next_.Inv_RNrm_PF_fcts = \ + Inv_RNrm_PF_fcts + + FHWF_fcts = { + 'about': 'Finite Human Wealth Factor' + } + py___code = 'PermGroFac / Rfree' + Bilt.FHWF = FHWF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + FHWF_fcts.update({'latexexpr': r'\FHWF'}) + FHWF_fcts.update({'_unicode_': r'R/Γ'}) + FHWF_fcts.update({'urlhandle': urlroot + 'FHWF'}) + FHWF_fcts.update({'py___code': py___code}) + FHWF_fcts.update({'value_now': FHWF}) + Bilt.FHWF_fcts = \ + FHWF_fcts + + FHWC_fcts = { + 'about': 'Finite Human Wealth Condition' + } + FHWC_fcts.update({'latexexpr': r'\FHWC'}) + FHWC_fcts.update({'urlhandle': urlroot + 'FHWC'}) + FHWC_fcts.update({'py___code': 'test: FHWF < 1'}) + Bilt.FHWC_fcts = FHWC_fcts + + hNrmInf_fcts = { + 'about': 'Human wealth for inf hor' + } + py___code = '1/(1-FHWF) if (FHWF < 1) else float("inf")' + Bilt.hNrmInf = hNrmInf = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + hNrmInf_fcts = dict({'latexexpr': r'1/(1-\FHWF)'}) + hNrmInf_fcts.update({'value_now': hNrmInf}) + hNrmInf_fcts.update({'py___code': py___code}) + Bilt.hNrmInf_fcts = hNrmInf_fcts + + DiscGPFRawCusp_fcts = { + 'about': 'DiscFac s.t. GPFRaw = 1' + } + py___code = '( PermGroFac **CRRA)/(Rfree)' + Bilt.DiscGPFRawCusp = DiscGPFRawCusp = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + DiscGPFRawCusp_fcts.update({'latexexpr': + r'\PermGroFac^{\CRRA}/\Rfree'}) + DiscGPFRawCusp_fcts.update({'value_now': DiscGPFRawCusp}) + DiscGPFRawCusp_fcts.update({'py___code': py___code}) + Bilt.DiscGPFRawCusp_fcts = \ + DiscGPFRawCusp_fcts + + DiscGPFLivCusp_fcts = { + 'about': 'DiscFac s.t. GPFLiv = 1' + } + py___code = '( PermGroFac **CRRA)/(Rfree*LivPrb)' + Bilt.DiscGPFLivCusp = DiscGPFLivCusp = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + DiscGPFLivCusp_fcts.update({'latexexpr': + r'\PermGroFac^{\CRRA}/(\Rfree\LivPrb)'}) + DiscGPFLivCusp_fcts.update({'value_now': DiscGPFLivCusp}) + DiscGPFLivCusp_fcts.update({'py___code': py___code}) + Bilt.DiscGPFLivCusp_fcts = DiscGPFLivCusp_fcts + + FVAF_fcts = { # overwritten by version with uncertainty + 'about': 'Finite Value of Autarky Factor' + } + py___code = 'LivPrb * DiscLiv' + Bilt.FVAF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + FVAF_fcts.update({'latexexpr': r'\FVAFPF'}) + FVAF_fcts.update({'urlhandle': urlroot + 'FVAFPF'}) + FVAF_fcts.update({'py___code': py___code}) + Bilt.FVAF_fcts = FVAF_fcts + + FVAC_fcts = { # overwritten by version with uncertainty + 'about': 'Finite Value of Autarky Condition - Perfect Foresight' + } + FVAC_fcts.update({'latexexpr': r'\FVACPF'}) + FVAC_fcts.update({'urlhandle': urlroot + 'FVACPF'}) + FVAC_fcts.update({'py___code': 'test: FVAFPF < 1'}) + Bilt.FVAC_fcts = FVAC_fcts + + E_Next_.IncNrmNxt_fcts = { # Overwritten by version with uncertainty + 'about': 'Expected income next period' + } + py___code = '1.0' + E_Next_.IncNrmNxt = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + E_Next_.IncNrmNxt_fcts.update({'py___code': py___code}) + E_Next_.IncNrmNxt_fcts.update({'value_now': E_Next_.IncNrmNxt}) + crnt.E_Next_.IncNrmNxt_fcts = E_Next_.IncNrmNxt_fcts + + RNrm_PF_fcts = { + 'about': 'Expected Growth-Normalized Return' + } + py___code = 'Rfree / PermGroFac' + E_Next_.RNrm_PF = RNrm_PF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + RNrm_PF_fcts.update({'latexexpr': r'\PFRNrm'}) + RNrm_PF_fcts.update({'_unicode_': r'R/Γ'}) + RNrm_PF_fcts.update({'urlhandle': urlroot + 'PFRNrm'}) + RNrm_PF_fcts.update({'py___code': py___code}) + RNrm_PF_fcts.update({'value_now': RNrm_PF}) + E_Next_.RNrm_PF_fcts = RNrm_PF_fcts + + RNrm_PF_fcts = { + 'about': 'Expected Growth-Normalized Return' + } + py___code = 'Rfree / PermGroFac' + E_Next_.RNrm_PF = RNrm_PF = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + RNrm_PF_fcts.update({'latexexpr': r'\PFRNrm'}) + RNrm_PF_fcts.update({'_unicode_': r'R/Γ'}) + RNrm_PF_fcts.update({'urlhandle': urlroot + 'PFRNrm'}) + RNrm_PF_fcts.update({'py___code': py___code}) + RNrm_PF_fcts.update({'value_now': RNrm_PF}) + E_Next_.RNrm_PF_fcts = RNrm_PF_fcts + + DiscLiv_fcts = { + 'about': 'Mortality-Inclusive Discounting' + } + py___code = 'DiscFac * LivPrb' + Bilt.DiscLiv = DiscLiv = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + DiscLiv_fcts.update({'latexexpr': r'\PFRNrm'}) + DiscLiv_fcts.update({'_unicode_': r'R/Γ'}) + DiscLiv_fcts.update({'urlhandle': urlroot + 'PFRNrm'}) + DiscLiv_fcts.update({'py___code': py___code}) + DiscLiv_fcts.update({'value_now': DiscLiv}) + Bilt.DiscLiv_fcts = DiscLiv_fcts + + def build_facts_recursive(self): + """ + For t, calculate results that depend on the last period solved (t+1). + + Returns + ------- + None. + + """ + crnt = self.solution_current + tp1 = self.solution_follows.Bilt # tp1 means t+1 + Bilt, Pars, E_Next_ = crnt.Bilt, crnt.Pars, crnt.E_Next_ + + givens = {**Pars.__dict__, **locals()} + urlroot = Bilt.urlroot + Bilt.DiscLiv = Pars.DiscFac * Pars.LivPrb + + hNrm_fcts = { + 'about': 'Human Wealth ' + } + py___code = '((PermGroFac / Rfree) * (1.0 + tp1.hNrm))' + if crnt.stge_kind['iter_status'] == 'terminal_partial': # kludge: + py___code = '0.0' # hNrm = 0.0 for last period + Bilt.hNrm = hNrm = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + hNrm_fcts.update({'latexexpr': r'\hNrm'}) + hNrm_fcts.update({'_unicode_': r'R/Γ'}) + hNrm_fcts.update({'urlhandle': urlroot + 'hNrm'}) + hNrm_fcts.update({'py___code': py___code}) + hNrm_fcts.update({'value_now': hNrm}) + Bilt.hNrm_fcts = hNrm_fcts + + BoroCnstNat_fcts = { + 'about': 'Natural Borrowing Constraint' + } + py___code = '(tp1.mNrmMin - tranShkMin)*(PermGroFac/Rfree)*permShkMin' + if crnt.stge_kind['iter_status'] == 'terminal_partial': # kludge + py___code = 'hNrm' # Presumably zero + Bilt.BoroCnstNat = BoroCnstNat = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + BoroCnstNat_fcts.update({'latexexpr': r'\BoroCnstNat'}) + BoroCnstNat_fcts.update({'_unicode_': r''}) + BoroCnstNat_fcts.update({'urlhandle': urlroot + 'BoroCnstNat'}) + BoroCnstNat_fcts.update({'py___code': py___code}) + BoroCnstNat_fcts.update({'value_now': BoroCnstNat}) + Bilt.BoroCnstNat_fcts = BoroCnstNat_fcts + + BoroCnst_fcts = { + 'about': 'Effective Borrowing Constraint' + } + py___code = 'BoroCnstNat if (BoroCnstArt == None) else ' + \ + '(BoroCnstArt if BoroCnstNat < BoroCnstArt else BoroCnstNat)' + Bilt.BoroCnst = BoroCnst = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + BoroCnst_fcts.update({'latexexpr': r'\BoroCnst'}) + BoroCnst_fcts.update({'_unicode_': r''}) + BoroCnst_fcts.update({'urlhandle': urlroot + 'BoroCnst'}) + BoroCnst_fcts.update({'py___code': py___code}) + BoroCnst_fcts.update({'value_now': BoroCnst}) + Bilt.BoroCnst_fcts = BoroCnst_fcts + + # MPCmax is not a meaningful object in the PF model so is not created + # there so create it here + MPCmax_fcts = { + 'about': 'Maximal MPC in current period as m -> mNrmMin' + } + py___code = '1.0 / (1.0 + (RPF / tp1.MPCmax))' + if crnt.stge_kind['iter_status'] == 'terminal_partial': # kludge: + crnt.tp1.MPCmax = float('inf') # => MPCmax = 1 for last per + Bilt.MPCmax = eval( + py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + MPCmax_fcts.update({'latexexpr': r''}) + MPCmax_fcts.update({'urlhandle': urlroot + 'MPCmax'}) + MPCmax_fcts.update({'py___code': py___code}) + MPCmax_fcts.update({'value_now': Bilt.MPCmax}) + Bilt.MPCmax_fcts = MPCmax_fcts + + mNrmMin_fcts = { + 'about': 'Min m is the max you can borrow' + } + py___code = 'BoroCnst' + Bilt.mNrmMin = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + mNrmMin_fcts.update({'latexexpr': r'\mNrmMin'}) + mNrmMin_fcts.update({'py___code': py___code}) + Bilt.mNrmMin_fcts = mNrmMin_fcts + + MPCmin_fcts = { + 'about': 'Minimal MPC in current period as m -> infty' + } + py___code = '1.0 / (1.0 + (RPF / tp1.MPCmin))' + if crnt.stge_kind['iter_status'] == 'terminal_partial': # kludge: + py__code = '1.0' + Bilt.MPCmin = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + MPCmin_fcts.update({'latexexpr': r''}) + MPCmin_fcts.update({'urlhandle': urlroot + 'MPCmin'}) + MPCmin_fcts.update({'py___code': py___code}) + MPCmin_fcts.update({'value_now': Bilt.MPCmin}) + Bilt.MPCmin_fcts = MPCmin_fcts + + MPCmax_fcts = { + 'about': 'Maximal MPC in current period as m -> mNrmMin' + } + py___code = '1.0 / (1.0 + (RPF / tp1.MPCmax))' + if crnt.stge_kind['iter_status'] == 'terminal_partial': # kludge: + Bilt.tp1.MPCmax = float('inf') # => MPCmax = 1 for final period + Bilt.MPCmax = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + MPCmax_fcts.update({'latexexpr': r''}) + MPCmax_fcts.update({'urlhandle': urlroot + 'MPCmax'}) + MPCmax_fcts.update({'py___code': py___code}) + MPCmax_fcts.update({'value_now': Bilt.MPCmax}) + Bilt.MPCmax_fcts = MPCmax_fcts + + cFuncLimitIntercept_fcts = { + 'about': + 'Vertical intercept of perfect foresight consumption function'} + py___code = 'MPCmin * hNrm' + Bilt.cFuncLimitIntercept = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + cFuncLimitIntercept_fcts.update({'py___code': py___code}) + cFuncLimitIntercept_fcts.update({'latexexpr': r'\MPC \hNrm'}) + crnt.Bilt.cFuncLimitIntercept_fcts = cFuncLimitIntercept_fcts + + cFuncLimitSlope_fcts = { + 'about': 'Slope of limiting consumption function'} + py___code = 'MPCmin' + cFuncLimitSlope_fcts.update({'py___code': 'MPCmin'}) + Bilt.cFuncLimitSlope = \ + eval(py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + cFuncLimitSlope_fcts.update({'py___code': py___code}) + cFuncLimitSlope_fcts = dict({'latexexpr': r'\MPCmin'}) + cFuncLimitSlope_fcts.update({'urlhandle': r'\MPC'}) + crnt.Bilt.cFuncLimitSlope_fcts = cFuncLimitSlope_fcts + + # That's the end of things that are identical for PF and non-PF models + # Models with uncertainty will supplement the above calculations + + return crnt + + def solve_prepared_stage_divert(self): + """ + Allow alternative solution method in special cases. + + Returns + ------- + divert : boolean + If False (usually), continue normal solution + If True, produce alternative solution and store on self.solution_current + """ + # bare-bones default terminal solution does not have all the facts + # we need, because it is generic (for any u func) so add the facts + crnt, folw = self.solution_current, self.solution_follows + if folw.Bilt.stge_kind['iter_status'] != 'terminal_partial': + return False # Continue with normal solution procedures + else: + # Populate it with the proper properties + crnt = define_t_reward(crnt, def_utility_CRRA) # Bellman reward + define_transition(crnt, 'chosen_to_next_choice') + define_transition(crnt, 'choice_to_chosen') + crnt.cFunc = crnt.Bilt.cFunc # make cFunc accessible + crnt = def_value_CRRA(crnt, crnt.Pars.CRRA) # make v using cFunc + self.build_facts_infhor() + crnt.Bilt.stge_kind['iter_status'] = 'iterator' # now it's legit + return True # if pseudo_terminal=True, enhanced replaces original + + def solve_prepared_stage(self): # inside ConsPerfForesightSolver + """ + Solve one stage/period of the consumption-saving problem. + + Parameters + ---------- + None (all are already in self) + + Returns + ------- + solution : ConsumerSolution + The solution to this period/stage's problem + """ + if self.solve_prepared_stage_divert(): # Allow bypass of normal soln + return self.solution_current # created by solve_prepared_stage_divert + + crnt = self.solution_current + + define_transition(crnt, 'chosen_to_next_choice') + + self.from_chosen_states_make_continuation_E_Next_(crnt) + + define_t_reward(crnt, def_utility_CRRA) # Bellman reward: utility + + self.make_t_decision_rules_and_value_functions() + + return crnt + + # alias for core.py which calls .solve method + solve = solve_prepared_stage + + def make_t_decision_rules_and_value_functions(self): + """ + Add decision rules and value funcs to current solution object. + + Returns + ------- + agent_stage_solution : agent_stage_solution + Augmented with decision rules and value functions + + """ + self.make_cFunc_PF() + return def_value_funcs(self.solution_current, self.solution_current.Pars.CRRA) + + def solver_prep_solution_for_an_iteration(self): # PF + """Prepare current stage for processing by the one-stage solver.""" + crnt = self.solution_current + + Bilt, Pars = crnt.Bilt, crnt.Pars + + # Catch degenerate case of zero-variance income distributions + # Otherwise "test cases" that try the degenerate dstns will fail + if hasattr(Bilt, "tranShkVals") and hasattr(Bilt, "permShkVals"): + if ((Bilt.tranShkMin == 1.0) and (Bilt.permShkMin == 1.0)): + crnt.E_Next_.Inv_permShk = 1.0 + crnt.E_Next_.uInv_permShk = 1.0 + else: # Missing trans or permShkVals; assume it's PF model + Bilt.tranShkMin = Bilt.permShkMin = 1.0 + + # Nothing needs to be done for terminal_partial + if hasattr(Bilt, 'stge_kind'): + if 'iter_status' in Bilt.stge_kind: + if (Bilt.stge_kind['iter_status'] == 'terminal_partial'): + # solution_terminal is handmade, do not remake + return + + Bilt.stge_kind = \ + crnt.stge_kind = {'iter_status': 'iterator', + 'slvr_type': self.__class__.__name__} + + return + + # Disambiguate "prepare_to_solve" from similar method names elsewhere + # (preserve "prepare_to_solve" as alias because core.py calls it) + prepare_to_solve = solver_prep_solution_for_an_iteration + + +############################################################################## + +class ConsIndShockSetup(ConsPerfForesightSolver): + """ + Solve one period of CRRA problem with transitory and permanent shocks. + + This is a superclass for solvers of one period consumption problems with + constant relative risk aversion utility and permanent and transitory shocks + to labor income, containing code shared among alternative specific solvers. + + N.B.: Because this is a one-time-period solver, objects that (in the full + problem) are lists because they are allowed to vary at different periods + (like, income growth at different ages), are scalars here because the value + that is appropriate for the current period is the one that will be passed. + + Parameters + ---------- + solution_next : ConsumerSolution + The solution to next period's one period problem. + IncShkDstn : distribution.Distribution + A discrete approximation to the income process between the period + being solved and the one immediately following + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the succeeding period. + DiscFac : float + Intertemporal discount factor for future utility. + CRRA : float + Coefficient of relative risk aversion. + Rfree : float + Risk free interest factor on end-of-period assets. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt: float or None + Borrowing constraint for the minimum allowable assets to end the + period with. If it is less than the natural borrowing constraint, + then it is irrelevant; BoroCnstArt=None indicates no artificial bor- + rowing constraint. + aXtraGrid: np.array + Array of "extra" end-of-period asset values-- assets above the + absolute minimum acceptable level. + CubicBool: boolean + An indicator for whether the solver should use cubic or linear inter- + polation. + solveMethod : str, optional + Solution method to use + eventTiming : str, optional + Stochastic shocks or deterministic evolutions of the problem (aside + from state variable transitions) can occur between choice stages. The + informaton about these events needs to be attached to the appropriate + solution stage, and executed at appropriate point. This option allows + changing interpretation of an existing variable, e.g. income shocks, + between the allowed timings. + 'EOP' is 'End of problem/period' + 'BOP' is 'Beginning of problem/period' + 'Both' there are things to do both before and after decision stage + """ + + shock_vars = ['tranShkDstn', 'permShkDstn'] # Unemp shock=min(transShkVal) + + # TODO: CDC 20210416: Params shared with PF are in different order. Fix + # noinspection PyTypeChecker + def __init__( + self, solution_next, IncShkDstn, LivPrb, DiscFac, CRRA, Rfree, + PermGroFac, BoroCnstArt, aXtraGrid, vFuncBool, CubicBool, + permShkDstn, tranShkDstn, + solveMethod='EGM', + eventTiming='EOP', + horizon='infinite', + **kwds): + # First execute PF solver init + # We must reorder params by hand in case someone tries positional solve + ConsPerfForesightSolver.__init__(self, solution_next, DiscFac=DiscFac, + LivPrb=LivPrb, CRRA=CRRA, + Rfree=Rfree, PermGroFac=PermGroFac, + BoroCnstArt=BoroCnstArt, + IncShkDstn=IncShkDstn, + permShkDstn=permShkDstn, + tranShkDstn=tranShkDstn, + solveMethod=solveMethod, + eventTiming=eventTiming, + horizon=horizon, + **kwds) + + # ConsPerfForesightSolver.__init__ makes self.solution_current + crnt = self.solution_current + + # Things we have built, exogenous parameters, and model structures: + Bilt, Modl = crnt.Bilt, crnt.Modl + + Modl.eventTiming = eventTiming + Modl.horizon = horizon + + Bilt.aXtraGrid = aXtraGrid + self.CubicBool = CubicBool + + # In which column is each object stored in IncShkDstn? + Bilt.permPos = IncShkDstn.parameters['ShkPosn']['perm'] + Bilt.tranPos = IncShkDstn.parameters['ShkPosn']['tran'] + + # Bcst are "broadcasted" values: serial list of every permutation + # Makes it fast to take expectations using E_dot + Bilt.permShkValsBcst = permShkValsBcst = IncShkDstn.X[Bilt.permPos] + Bilt.tranShkValsBcst = tranShkValsBcst = IncShkDstn.X[Bilt.tranPos] + + Bilt.ShkPrbs = ShkPrbs = IncShkDstn.pmf + + Bilt.permShkPrbs = permShkPrbs = permShkDstn.pmf + Bilt.permShkVals = permShkVals = permShkDstn.X + # Confirm that perm shocks have expectation near one + assert_approx_equal(E_dot(permShkPrbs, permShkVals), 1.0) + + Bilt.tranShkPrbs = tranShkPrbs = tranShkDstn.pmf + Bilt.tranShkVals = tranShkVals = tranShkDstn.X + # Confirm that tran shocks have expectation near one + assert_approx_equal(E_dot(tranShkPrbs, tranShkVals), 1.0) + + Bilt.permShkMin = permShkMin = np.min(permShkVals) + Bilt.tranShkMin = tranShkMin = np.min(tranShkVals) + + Bilt.permShkMax = permShkMax = np.max(permShkVals) + Bilt.tranShkMax = tranShkMax = np.max(tranShkVals) + + Bilt.UnempPrb = Bilt.tranShkPrbs[0] + + Bilt.inc_min_Prb = np.sum( # All cases where perm and tran Shk are Min + ShkPrbs[ \ + permShkValsBcst * tranShkValsBcst == permShkMin * tranShkMin + ] + ) + + Bilt.inc_max_Prb = np.sum( # All cases where perm and tran Shk are Min + ShkPrbs[ \ + permShkValsBcst * tranShkValsBcst == permShkMax * tranShkMax + ] + ) + Bilt.inc_max_Val = permShkMax * tranShkMax + + def build_facts_infhor(self): + """ + Calculate expectations and facts for models with uncertainty. + + For versions with uncertainty in transitory and/or permanent shocks, + adds to the solution a set of results useful for calculating + various diagnostic conditions about the problem, and stable + points (if they exist). + + Returns + ------- + solution : ConsumerSolution + Same solution that was provided, augmented with the factors + + """ + super().build_facts_infhor() # Make the facts built by the PF model + + crnt = self.solution_current + + Bilt, Pars, E_Next_ = crnt.Bilt, crnt.Pars, crnt.E_Next_ + + # The 'givens' do not change as facts are constructed + givens = {**Pars.__dict__, **crnt.__dict__} + + Bilt.E_dot = E_dot # add dot product expectations operator to envt + + urlroot = Bilt.urlroot + + # Many other _fcts will have been inherited from the perfect foresight + + # Here we need compute only those objects whose value changes from PF + # (or does not exist in PF case) + + E_Next_.IncNrmNxt_fcts = { + 'about': 'Expected income next period' + } + py___code = 'E_dot(ShkPrbs, tranShkValsBcst * permShkValsBcst)' + E_Next_.IncNrmNxt = E_Next_.IncNrmNxt = eval( + py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + E_Next_.IncNrmNxt_fcts.update({'latexexpr': r'ExIncNrmNxt'}) + E_Next_.IncNrmNxt_fcts.update({'_unicode_': r'E[tranShk permShk]=1.0'}) + E_Next_.IncNrmNxt_fcts.update({'urlhandle': urlroot + 'ExIncNrmNxt'}) + E_Next_.IncNrmNxt_fcts.update({'py___code': py___code}) + E_Next_.IncNrmNxt_fcts.update({'value_now': E_Next_.IncNrmNxt}) + crnt.E_Next_.IncNrmNxt_fcts = E_Next_.IncNrmNxt_fcts + + E_Next_.Inv_permShk_fcts = { + 'about': 'Expected Inverse of Permanent Shock' + } + py___code = 'E_dot(1/permShkVals, permShkPrbs)' + E_Next_.Inv_permShk = E_Next_.Inv_permShk = eval( + py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + E_Next_.Inv_permShk_fcts.update({'latexexpr': r'\ExInvpermShk'}) + E_Next_.Inv_permShk_fcts.update({'urlhandle': + urlroot + 'ExInvpermShk'}) + E_Next_.Inv_permShk_fcts.update({'py___code': py___code}) + E_Next_.Inv_permShk_fcts.update({'value_now': E_Next_.Inv_permShk}) + crnt.E_Next_.Inv_permShk_fcts = E_Next_.Inv_permShk_fcts + + E_Next_.RNrm_fcts = { + 'about': 'Expected Stochastic-Growth-Normalized Return' + } + py___code = 'RNrm_PF * E_Next_.Inv_permShk' + E_Next_.RNrm = eval( + py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + E_Next_.RNrm_fcts.update({'latexexpr': r'\ExRNrm'}) + E_Next_.RNrm_fcts.update({'_unicode_': r'E[R/Γψ]'}) + E_Next_.RNrm_fcts.update({'urlhandle': urlroot + 'ExRNrm'}) + E_Next_.RNrm_fcts.update({'py___code': py___code}) + E_Next_.RNrm_fcts.update({'value_now': E_Next_.RNrm}) + E_Next_.RNrm_fcts = E_Next_.RNrm_fcts + + E_Next_.uInv_permShk_fcts = { + 'about': 'Expected Utility for Consuming Permanent Shock' + } + py___code = 'E_dot(permShkValsBcst**(1-CRRA), ShkPrbs)' + E_Next_.uInv_permShk = E_Next_.uInv_permShk = eval( + py___code, {}, {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + E_Next_.uInv_permShk_fcts.update({'latexexpr': r'\ExuInvpermShk'}) + E_Next_.uInv_permShk_fcts.update({'urlhandle': r'ExuInvpermShk'}) + E_Next_.uInv_permShk_fcts.update({'py___code': py___code}) + E_Next_.uInv_permShk_fcts.update({'value_now': E_Next_.uInv_permShk}) + E_Next_.uInv_permShk_fcts = E_Next_.uInv_permShk_fcts + + GPFNrm_fcts = { + 'about': 'Normalized Expected Growth Patience Factor' + } + py___code = 'GPFRaw * E_Next_.Inv_permShk' + Bilt.GPFNrm = eval(py___code, {}, + {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + GPFNrm_fcts.update({'latexexpr': r'\GPFNrm'}) + GPFNrm_fcts.update({'_unicode_': r'Þ_Γ'}) + GPFNrm_fcts.update({'urlhandle': urlroot + 'GPFNrm'}) + GPFNrm_fcts.update({'py___code': py___code}) + Bilt.GPFNrm_fcts = GPFNrm_fcts + + GICNrm_fcts = { + 'about': 'Stochastic Growth Normalized Impatience Condition' + } + GICNrm_fcts.update({'latexexpr': r'\GICNrm'}) + GICNrm_fcts.update({'urlhandle': urlroot + 'GICNrm'}) + GICNrm_fcts.update({'py___code': 'test: GPFNrm < 1'}) + Bilt.GICNrm_fcts = GICNrm_fcts + + FVAC_fcts = { # overwrites PF version + 'about': 'Finite Value of Autarky Condition' + } + + FVAF_fcts = { # overwrites PF version FVAFPF + 'about': 'Finite Value of Autarky Factor' + } + py___code = 'LivPrb * DiscLiv' + Bilt.FVAF = eval(py___code, {}, + {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + FVAF_fcts.update({'latexexpr': r'\FVAF'}) + FVAF_fcts.update({'urlhandle': urlroot + 'FVAF'}) + FVAF_fcts.update({'py___code': py___code}) + Bilt.FVAF_fcts = FVAF_fcts + + FVAC_fcts = { # overwrites PF version + 'about': 'Finite Value of Autarky Condition' + } + FVAC_fcts.update({'latexexpr': r'\FVAC'}) + FVAC_fcts.update({'urlhandle': urlroot + 'FVAC'}) + FVAC_fcts.update({'py___code': 'test: FVAF < 1'}) + Bilt.FVAC_fcts = FVAC_fcts + + WRPF_fcts = { + 'about': 'Weak Return Patience Factor' + } + py___code = '(UnempPrb ** (1 / CRRA)) * RPF' + Bilt.WRPF = WRPF = \ + eval(py___code, {}, + {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + WRPF_fcts.update({'latexexpr': r'\WRPF'}) + WRPF_fcts.update({'_unicode_': r'℘^(1/\rho) RPF'}) + WRPF_fcts.update({'urlhandle': urlroot + 'WRPF'}) + WRPF_fcts.update({'value_now': WRPF}) + WRPF_fcts.update({'py___code': py___code}) + Bilt.WRPF_fcts = WRPF_fcts + + WRIC_fcts = { + 'about': 'Weak Return Impatience Condition' + } + WRIC_fcts.update({'latexexpr': r'\WRIC'}) + WRIC_fcts.update({'urlhandle': urlroot + 'WRIC'}) + WRIC_fcts.update({'py___code': 'test: WRPF < 1'}) + Bilt.WRIC_fcts = WRIC_fcts + + DiscGPFNrmCusp_fcts = { + 'about': 'DiscFac s.t. GPFNrm = 1' + } + py___code = '((PermGroFac/E_Next_.Inv_permShk)**(CRRA))/Rfree' + Bilt.DiscGPFNrmCusp = DiscGPFNrmCusp = \ + eval(py___code, {}, + {**E_Next_.__dict__, **Bilt.__dict__, **givens}) + DiscGPFNrmCusp_fcts.update({'latexexpr': ''}) + DiscGPFNrmCusp_fcts.update({'value_now': DiscGPFNrmCusp}) + DiscGPFNrmCusp_fcts.update({'py___code': py___code}) + Bilt.DiscGPFNrmCusp_fcts = DiscGPFNrmCusp_fcts + + def build_facts_recursive(self): + """ + Calculate recursive facts for current period from next. + + Returns + ------- + crnt : agent_stage_solution + + """ + super().build_facts_recursive() + + # All the recursive facts are required for PF model so already exist + # But various lambda functions are interesting when uncertainty exists + + crnt = self.solution_current + Bilt = crnt.Bilt + Pars = crnt.Pars + E_Next_ = crnt.E_Next_ + + # To use these it is necessary to have created an alias to + # the relevant namespace on the solution object, e.g. + # E_Next_ = [soln].E_Next_ + # Bilt = [soln].Bilt + # Pars = [soln].Pars + + # Given m, value of c where E[m_{t+1}]=m_{t} + # E_Next_.c_where_m_tp1_minus_m_t_eq_0 = ( + # lambda m_t: + # m_t * (1 - 1 / E_Next_.RNrm) + (1 / E_Next_.RNrm) + # ) + # E_Next_.c_where_permGroShk_times_m_tp1_minus_m_t_eq_0 = ( + # lambda m_t: + # m_t * (1 - E_Next_.Inv_RNrm_PF) + E_Next_.Inv_RNrm_PF + # ) + # E[c_{t+1} pLev_{t+1}/pLev_{t}] as a fn of a_{t} + E_Next_.cLev_tp1_Over_pLev_t_from_a_t = ( + lambda a_t: + E_dot(Pars.PermGroFac * + Bilt.permShkValsBcst * + Bilt.cFunc((E_Next_.RNrm_PF / Bilt.permShkValsBcst) * a_t + + Bilt.tranShkValsBcst), + Bilt.ShkPrbs) + ) + E_Next_.c_where_E_Next_m_tp1_minus_m_t_eq_0 = \ + lambda m_t: \ + m_t * (1 - 1/E_Next_.RNrm) + (1 / E_Next_.RNrm) + + E_Next_.c_where_E_Next_permGroShk_times_m_tp1_minus_m_t_eq_0 = \ + lambda m_t: \ + (m_t * (1 - 1 / E_Next_.RNrm_PF)) + (1 / E_Next_.RNrm_PF) + # mNrmTrg solves E_Next_.RNrm*(m - c(m)) + E[inc_next] - m = 0 + + E_Next_.m_tp1_minus_m_t = ( + lambda m_t: + (E_Next_.RNrm * (m_t - Bilt.cFunc(m_t)) + E_Next_.IncNrmNxt)-m_t + ) + E_Next_.m_tp1_Over_m_t = ( + lambda m_t: + (E_Next_.RNrm * (m_t - Bilt.cFunc(m_t)) + E_Next_.IncNrmNxt)/m_t + ) + E_Next_.mLev_tp1_Over_mLev_t = ( + lambda m_t: + (Pars.Rfree * (m_t - Bilt.cFunc(m_t)) + + Pars.PermGroFac * E_Next_.IncNrmNxt)/m_t + ) + # Define separately for float ('num') and listlike ('lst'), then combine + E_Next_.cLev_tp1_Over_pLev_t_from_num_a_t = ( + lambda a_t: + E_dot( + Bilt.permShkValsBcst * Pars.PermGroFac * Bilt.cFunc( + (E_Next_.RNrm_PF / Bilt.permShkValsBcst) * + a_t + Bilt.tranShkValsBcst + ), + Bilt.ShkPrbs) + ) + E_Next_.cLev_tp1_Over_pLev_t_from_lst_a_t = ( + lambda a_lst: list(map( + E_Next_.cLev_tp1_Over_pLev_t_from_num_a_t, a_lst + )) + ) + E_Next_.cLev_tp1_Over_pLev_t_from_a_t = ( + lambda a_t: + E_Next_.cLev_tp1_Over_pLev_t_from_lst_a_t(a_t) + if (type(a_t) == list or type(a_t) == np.ndarray) else + E_Next_.cLev_tp1_Over_pLev_t_from_num_a_t(a_t) + ) + E_Next_.mLev_tp1_Over_pLev_t_from_num_a_t = ( + lambda a_t: + Pars.Rfree * a_t + Pars.PermGroFac + ) + E_Next_.mLev_tp1_Over_pLev_t_from_lst_a_t = ( + lambda a_lst: list(map( + E_Next_.mLev_tp1_Over_pLev_t_from_num_a_t, a_lst + )) + ) + E_Next_.mLev_tp1_Over_pLev_t_from_a_t = ( + lambda a_t: + E_Next_.mLev_tp1_Over_pLev_t_from_lst_a_t(a_t) + if (type(a_t) == list or type(a_t) == np.ndarray) else + E_Next_.mLev_tp1_Over_pLev_t_from_num_a_t(a_t) + ) + E_Next_.cLev_tp1_Over_pLev_t_from_lst_m_t = ( + lambda m_t: + E_Next_.cLev_tp1_Over_pLev_t_from_lst_a_t(m_t - + Bilt.cFunc(m_t)) + ) + E_Next_.permGroShk_tp1_times_m_tp1_Over_m_t = ( + lambda m_t: + (Pars.Rfree*(m_t - Bilt.cFunc(m_t)) + Pars.PermGroFac * E_Next_.IncNrmNxt)/m_t + ) + E_Next_.permGroShk_tp1_times_m_tp1_Over_m_t_minus_PGro = ( + lambda m_t: + E_Next_.permGroShk_tp1_times_m_tp1_Over_m_t(m_t) - Pars.PermGroFac + ) + E_Next_.m_tp1_from_a_t = ( + lambda a_t: + E_Next_.RNrm * a_t + E_Next_.IncNrmNxt + ) + E_Next_.cLev_tp1_Over_pLev_t_from_num_m_t = ( + lambda m_t: + E_Next_.cLev_tp1_Over_pLev_t_from_num_a_t(m_t - + Bilt.cFunc(m_t)) + ) + E_Next_.cLev_tp1_Over_cLev_t_from_m_t = ( + lambda m_t: + E_Next_.cLev_tp1_Over_pLev_t_from_lst_m_t(m_t) / Bilt.cFunc(m_t) + if (type(m_t) == list or type(m_t) == np.ndarray) else + E_Next_.cLev_tp1_Over_pLev_t_from_num_m_t(m_t) / Bilt.cFunc(m_t) + ) + # E_Next_.mLev_tp1_Over_mLev_t_from_m_t = ( + # lambda m_t: + # E_Next_.mLev_tp1_Over_pLev_t_from_lst_m_t(m_t) / m_t + # if (type(m_t) == list or type(m_t) == np.ndarray) else + # E_Next_.mLev_tp1_Over_pLev_t_from_num_m_t(m_t) / m_t + # ) + self.solution_current = crnt + + return crnt + + +class ConsIndShockSolverBasic(ConsIndShockSetup): + """ + Solves a single period of a standard consumption-saving problem. + + Uses linear interpolation and missing the ability to calculate the value + function. ConsIndShockSolver inherits from this class and adds the ability + to perform cubic interpolation and to calculate the value function. + + Note that this class does not have its own initializing method. It initial- + izes the same problem in the same way as ConsIndShockSetup, from which it + inherits. + """ + + def make_chosen_state_grid(self): + """ + Make grid of potential values of state variable(s) after choice(s). + + Returns + ------- + aNrmGrid : np.array + A 1D array of end-of-period assets; also is made attribute of Bilt. + """ + # We define aNrmGrid all the way from BoroCnstNat up to max(aXtraGrid) + # even if BoroCnstNat Rsave`). + +""" + +__all__ = [ + "AgentTypePlus", + "consumer_terminal_nobequest_onestate", + "PerfForesightConsumerType", + "IndShockConsumerType", + "KinkedRconsumerType", + "onestate_bequest_warmglow_homothetic" +] + +# TODO: CDC 20210129: After being vetted, the elements of "Plus" that add to +# the base type from core.py should be merged into that base type. We can leave +# the "Plus" type empty in order to preserve an easy workflow that permits +# future proposals for improvements to the core AgentType. + + +class AgentTypePlus(AgentType): + """ + Augment AgentType with features that should be incorporated into AgentType. + """ + __doc__ += AgentType.__doc__ + __doc__ += """ + Notes + ----- + The code defines a number of optional elements that are used to + to enhance clarity or to allow future functionality. These include: + + prmtv_par : dictionary + List of 'prmtv' parameters that are necessary and sufficient to + define a unique solution with infinite computational power + + aprox_lim : dictionary + Approximation parameters, including a limiting value. + As all aprox parameters approach their limits simultaneously, + the numerical solution should converge to the 'true' solution + that would be obtained with infinite computational power + + """ + + # Mandatory lists; they must be overwritten as appropriate + time_vary = [] + time_inv = [] + state_vars = [] + + # https://elfi-y.medium.com/super-inherit-your-python-class-196369e3377a + def __init__(self, *args, + **kwds): # Inherit from basic AgentType + AgentType.__init__(self, *args, **kwds) + + # The base MetricObject class automatically constructs a list + # of parameters but for some reason it does not get some + # of the parameters {'cycles','seed','tolerance'} needed + # to reproduce results exactly + # TODO: CDC 20210525: Fix this in MetricObject to reduce clutter here + self.add_to_given_params = {'time_vary', 'time_inv', 'state_vars', + 'cycles', 'seed', 'tolerance'} + self.update_parameters_for_this_agent_subclass() + + def agent_store_model_params(self, prmtv_par, aprox_lim): + # When anything cached here changes, solution must be recomputed + prmtv_par_vals = {} + for par in prmtv_par: + if hasattr(self, par): + prmtv_par_vals[par] = getattr(self, par) + + aprox_par_vals = {} + for key in aprox_lim: + if hasattr(self, key): + aprox_par_vals[key] = getattr(self, key) + + # Merge to get all aprox and prmtv params and make a copy + self.solve_par_vals = \ + deepcopy({**prmtv_par_vals, **aprox_par_vals}) + + # Put on solution_terminal so it can get on non-term solution + self.solution_terminal.Bilt.solve_par_vals = self.solve_par_vals + + def update_parameters_for_this_agent_subclass(self): + # add_it: (below) + # class(Model) adds parameters explicitly passed; but parameters should also + # include anything else (even default values not explicitly passed) required + # to reproduce exactly ALL results of the model + + for add_it in self.add_to_given_params: + self.parameters.update({add_it: getattr(self, add_it)}) + + def agent_update_if_params_have_changed_since_last_solve(self): + """ + Update any characteristics of the agent that need to be recomputed + as a result of changes in parameters since the last time the solver was invoked. + + Parameters + ---------- + None + + Returns + ------- + None (adds `solve_par_vals_now` dict to self) + + """ + + # Get current parameter values + solve_par_vals_now = {} + if hasattr(self, 'solve_par_vals'): + for par in self.solve_par_vals: + solve_par_vals_now[par] = getattr(self, par) + # Check whether any of them has changed + if not (solve_par_vals_now == self.solve_par_vals): + breakpoint() + if not self.quietly: + _log.info('Some parameter has changed since last update.') + self._agent_force_prepare_info_needed_to_begin_solving() + + def _agent_force_prepare_info_needed_to_begin_solving(self): + # There are no universally required pre_solve objects + pass + + # pre_solve is the old name, preserved as an alias because + # core.py uses it. New name is MUCH clearer + pre_solve = agent_update_if_params_have_changed_since_last_solve + + # Universal method to either warn that something went wrong + # or to mark the solution as having completed. Should not + # be overwritten by subclasses; instead, agent-specific + # post-solve actions are accomplished by agent_post_post_solve + def post_solve(self): + if not hasattr(self, 'solution'): + _log.critical('No solution was returned.') + return + else: + if not type(self.solution) == list: + _log.critical('Solution is not a list.') + return + soln = self.solution[0] + if not hasattr(soln.Bilt, 'stge_kind'): + _log.warning('Solution does not have attribute stge_kind') + return + else: # breakpoint() + self.agent_post_post_solve() + + # Disambiguation: former "[solver].post_solve"; post_solve is now alias + # it's too hard to remember whether "post_solve" is a method of + # the solver or of the agent. The answer is the agent; hence the rename + agent_post_solve = post_solve_agent = post_solve + + # User-provided handmade solution_terminal is likely to be bare-bones + # Below is a placeholder for anything that user might want to do + # programmatially to enhance it + def finish_setup_of_default_solution_terminal(self): + """ + Add to terminal solution info specific to this agent type. + + Add to `solution_terminal` characteristics of the agent required + for solution of the particular type which are not automatically + created as part of the definition of the generic `solution_terminal.` + """ + pass + + def agent_post_post_solve(self): + """Do anything specific to this AgentType required after solution.""" + # overwrite this with anything required to be customized for post_solve + # of a particular agent type. + # For example, computing stable points for inf hor buffer stock + # Overwritten in PerfForesightConsumerSolution, carrying over + # to IndShockConsumerType + pass + + # If they did not provide their own solution_startfrom, use default + if not hasattr(self, 'solution_startfrom'): + # enrich generic consumer_terminal_nobequest_onestate terminal func + # with info specifically needed to solve this particular model + self.solution_terminal.Bilt = \ + self.finish_setup_of_default_solution_terminal() + # make url that will locate the documentation + self._url_doc_for_this_agent_type_get() + # any user-provided solution should already be enriched + + +# TODO: CDC: 20210529 consumer_terminal_nobequest_onestate should be changed to +# consumer_onestate and we should define a set of allowed bequest +# choices including at least: +# - nobequest +# - warm_glow +# - capitalist_spirit +# - warm_glow with bequests as a luxury in Stone-Geary form +# - implies that bequests are left only if lifetime income high enough +# - dynasty (Barrovian) + +class consumer_terminal_nobequest_onestate(AgentTypePlus): + """ + Define one-state no-bequest terminal consumption function. + + Minimal requirements for a consumer with one state variable, m: + * m combines assets from prior history with current income + * it is referred to as `market resources` throughout the docs + + This class must be inherited by some subclass + that fleshes out the rest of the characteristics of the agent, e.g. the + PerfForesightConsumerType or MertonSamuelsonConsumerType or something. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods/stages should be solved. + + solution_startfrom : ConsumerSolution, optional + A prespecified solution for the endpoint of the consumer + problem. If no value is supplied, the terminal solution defaults + to the case in which the consumer spends all available resources, + obtaining no residual utility from any unspent m. + """ + + def __init__( + self, solution_startfrom=None, cycles=1, pseudo_terminal=False, + **kwds): + + AgentTypePlus.__init__( + self, solution_terminal=solution_startfrom, # handmade or default + cycles=cycles, pseudo_terminal=False, + **kwds) + + # The below config of the 'afterlife' is constructed so that when + # the standard lifetime transition rules are applied, the nobequest + # terminal solution defined below is generated. + # This should work if stge_kind['iter_status']="iterator" + # The afterlife is inoperative if the terminal period is labeled with + # stge_kind['iter_status']="terminal_partial" (because in that case + # the "terminal_partial" final solution is used to construct the + # augmented "terminal" solution) + + # no value in afterlife: + def vFunc(m): return 0. + # TODO: Globally (throughout codebase) replace vPfunc with vFunc.dm + # TODO: Globally (throughout codebase) replace vPPfunc with vFunc.dm.dm + vFunc.dm = vPfunc = vFunc + vFunc.dm.dm = vPPfunc = vFunc + + def cFunc(m): return float('inf') # With CRRA utility, c=inf gives v=0 + cFunc.derivativeX = lambda m: float('inf') + + solution_afterlife_nobequest_ = ConsumerSolutionOneNrmStateCRRA( + vFunc=vFunc, + cFunc=cFunc, + stge_kind={ + 'iter_status': 'afterlife', + 'term_type': 'nobequest'}, + completed_cycles=-1 + ) + Bilt = solution_afterlife_nobequest_.Bilt + Bilt.cFunc, Bilt.vFunc, Bilt.mNrmMin, Bilt.hNrm, Bilt.MPCmin,\ + Bilt.MPCmax = cFunc, vFunc, 0.0, -1.0, float('inf'), float('inf') + + # This is the solution that would be constructed by applying + # our normal iteration tools to solution_afterlife_nobequest_ + + cFunc_terminal_nobequest_ = LinearInterp([0.0, 1.0, 2.0], + [0.0, 1.0, 2.0], + [0.0, 1.0, 2.0]) + + cFunc = cFunc_terminal_nobequest_ + + CRRA = 2.0 + def u(c): CRRAutility(c, CRRA) + + solution_nobequest_ = \ + ConsumerSolutionOneNrmStateCRRA( # Omit vFunc b/c u not yet def + cFunc=cFunc_terminal_nobequest_, + stge_kind={ + 'iter_status': 'terminal_partial', # must be replaced + 'term_type': 'nobequest' + }) + + Bilt = solution_nobequest_.Bilt + + Bilt.cFunc, Bilt.vFunc, Bilt.mNrmMin, Bilt.hNrm, Bilt.MPCmin,\ + Bilt.MPCmax = cFunc, vFunc, 0.0, 0.0, 1.0, 1.0 + + solution_nobequest_.solution_next = solution_afterlife_nobequest_ + # solution_terminal_ is defined for legacy/compatability reasons + # Otherwise would be better to just explicitly use solution_nobequest_ + self.solution_terminal_ = solution_terminal_ = solution_nobequest_ + # Deepcopy: We will be modifying features of solution_terminal, + # so make a deepcopy so that if multiple agents get created, we + # always use the unaltered "master" solution_terminal_ + self.solution_terminal = deepcopy(solution_terminal_) + + +class onestate_bequest_warmglow_homothetic(ConsumerSolutionOneNrmStateCRRA): + """ + Homothetic Stone-Geary bequest utility function with bequests as a luxury. + + Must be inherited by a subclass + that fleshes out the rest of the characteristics of the agent, e.g. the + PerfForesightConsumerType or MertonSamuelsonConsumerType or something. + + The bequest utility function is assumed to be of the Stone-Geary form + and to have a scale reflecting the number of periods worth of consumption + that it is equivalent to in the limit. (In the limit as wealth approaches + infinity, if this parameter were equal to the number of periods of life + and the pure time preference factor were 1, the consumer would split their + lifetime resources equally between the bequest and their lifetime + consumption). + + Parameters + ---------- + cycles : int + Number of times the sequence of periods/stages should be solved. + + solution_startfrom : ConsumerSolution, optional + A prespecified solution for the endpoint of the consumer + problem. If no value is supplied, the terminal solution defaults + to the case in which the consumer spends all available resources, + obtaining no residual utility from any unspent m. + + stone_geary : float + This parameter is added to the argument of the bequest utility function + in order to make bequests a luxury good + + equiv_life_periods : float + Limiting number of periods-worth of consumption that the bequest is + equivalent to + """ + + def __init__( + self, solution_startfrom=None, cycles=1, pseudo_terminal=False, + stone_geary=1.0, + equiv_life_periods=1.0, + CRRA=2, + **kwds): + + ConsumerSolutionOneNrmStateCRRA.__init__(self, + cycles=cycles, + pseudo_terminal=False, + CRRA=CRRA, + **kwds) + + Bilt = self.Bilt # alias + + if (equiv_life_periods == 0.0): + msg = 'With bequest parameter equiv_life_periods = 0, ' +\ + 'the model exhibits no bequest motive.' + + nobequest_agent = consumer_terminal_nobequest_onestate( + ) + self.solution_terminal = nobequest_agent.solution_terminal + + # Only reason to use the bequest type here instead of nobequest + # is to get the infrastructure for solving the PF liquidity + # constrained problem. That is below. + + # Add infrastructure for piecewise linear PF solution + Bilt.mNrm_cusp = 0.0 # here 'cusp' => cannot die in debt + Bilt.vNrm_cusp = -float('inf') # yields neg inf value + Bilt.vInv_cusp = 0.0 + Bilt.mNrm_kinks = [Bilt.mNrm_cusp] + Bilt.vNrm_kinks = [Bilt.vNrm_cusp] + Bilt.MPC_kinks = [1.0] + Bilt.hNrm = 0.0 + _log.info(msg) + return + + if (stone_geary == 0.0): + msg = 'With stone_geary parameter of zero, the bequest motive ' +\ + 'is equivlent to equiv_life_periods worth of consumption.' + _log.info(msg) + + # The entire bequest enters the utility function + bequest_entering_utility = LinearInterp( + [0., 1.], [0., 1.] + ) + + sab = solution_afterlife_bequest_ = ConsumerSolutionOneNrmStateCRRA( + cFunc=bequest_entering_utility, + u=u_stone_geary, uP=uP_stone_geary, uPP=uPP_stone_geary, + vFunc=u_stone_geary, vPfunc=uP_stone_geary, + vPPfunc=uPP_stone_geary, + stge_kind={ + 'iter_status': 'afterlife', + 'term_type': 'bequest_warmglow_homothetic'}, + completed_cycles=-1 + ) + ρ = sab.Bilt.CRRA = CRRA + η = sab.Bilt.stone_geary = stone_geary + ℶ = sab.Bilt.equiv_life_periods = equiv_life_periods # Hebrew bet + + if (equiv_life_periods == 0.0): + Bilt.vNrm_cusp = -float('inf') # then 'cusp' => cannot die in debt + else: + bequest_size = 0.0 + Bilt.vNrm_cusp = CRRAutility(Bilt.mNrm_cusp, CRRA) +\ + ℶ * u_stone_geary(bequest_size, CRRA, stone_geary) + + Bilt.mNrm_kinks = [Bilt.mNrm_cusp] # zero if no bequest motive + Bilt.vInv_uncons = [self.Bilt.uinv(Bilt.vNrm_cusp)] + Bilt.vInv_constr = [self.Bilt.uinv(Bilt.u(0.))] + # See PerfForesightConsumerType for MPC derivation + if ℶ == 0.0: + Bilt.MPC_constr = [1/(1+0.0)] + else: + Bilt.MPC_constr = [1/(1+(ℶ**(-1/ρ)))] + + def cFunc(self, m): + MPC_constr = self.Bilt.MPC_constr + mNrm_kinks = self.Bilt.mNrm_kinks + constr_0 = np.heaviside(m-mNrm_kinks[0], 0.) # 0 if constrnd, else 1 + c_constr = (1-constr_0)*m # m if m < kink + c_uncons = constr_0*(c_constr+MPC_constr[0]*(m-mNrm_kinks[0])) + return c_constr+c_uncons + +# It should be possible to swap other bequest motive choices, but this +# has not really been tested (20210718) + + +class PerfForesightConsumerType(consumer_terminal_nobequest_onestate): + """ + Consumer with perfect foresight except for potential mortality risk. + + A perfect foresight consumer who has no uncertainty other than + mortality risk. Time-separable utility maximization problem is + defined by a coefficient of relative risk aversion, geometric + discount factor, interest factor, an artificial borrowing constraint + (maybe) and time sequences of permanent income growth rate and survival. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods/stages should be solved. + """ + + time_vary_ = ["LivPrb", # Age-varying death rates can match mortality data + "PermGroFac"] # Age-varying income growth to match lifecycle + time_inv_ = ["CRRA", "Rfree", "DiscFac", "MaxKinks", "BoroCnstArt", + "solveMethod", "eventTiming", "solverType", + "horizon" + ] + state_vars = ['pLvl', # Initial idiosyncratic permanent income + 'PlvlAgg', # Aggregate permanent income + 'bNrm', # Bank balances beginning of period (pLvl normed) + 'mNrm', # Market resources (b + income) (pLvl normed) + "aNrm"] # Assets after all actions (pLvl normed) + shock_vars_ = [] + + def __init__(self, + cycles=0, # Default to finite horiz + quietly=False, # if True, do print anything conditions + solution_startfrom=None, # Default: no interim solution + solver=ConsPerfForesightSolver, + solveMethod='EGM', + eventTiming='EOP', + solverType='HARK', + horizon='infinite', + messaging_level=logging.INFO, + **kwds + ): + + params = init_perfect_foresight.copy() # Get defaults + params.update(kwds) # Replace defaults with passed vals if diff + + consumer_terminal_nobequest_onestate.__init__( + self, solution_startfrom=None, cycles=cycles, + pseudo_terminal=False, ** params) + + # Solver and method are: + # - required to solve + # - not necessarily set in any ancestral class + self.solver = solver + self.solveMethod = solveMethod + self.eventTiming = eventTiming + self.solverType = solverType + self.horizon = horizon + self.messaging_level = messaging_level + self.quietly = quietly + + # Things to keep track of for this and child models + self.check_restrictions() # Make sure it's a minimally valid model + self.time_vary = deepcopy(self.time_vary_) + self.time_inv = deepcopy(self.time_inv_) + self.cycles = deepcopy(self.cycles) + + self.update_parameters_for_this_agent_subclass() # store new info + + # If they did not provide their own solution_startfrom, use default + if not hasattr(self, 'solution_startfrom'): + # enrich generic consumer_terminal_nobequest_onestate terminal func + # with info specifically needed to solve this particular model + self.solution_terminal.Bilt = \ + self.finish_setup_of_default_solution_terminal() + # make url that will locate the documentation + self._url_doc_for_this_agent_type_get() + # any user-provided solution should already be enriched + + # The foregoing is executed by all classes that inherit from PF model + # The code below the following "if" is excuted only in the PF case + + self.income_risks_exist = \ + ('permShkStd' in params) or \ + ('tranShkStd' in params) or \ + (('UnempPrb' in params) and (params['UnempPrb'] != 0)) or \ + (('UnempPrbRet' in params) and (params['UnempPrbRet'] != 0)) + + if self.income_risks_exist: # We got here from a model with risks + return # Models with risks have different prep + + self._agent_force_prepare_info_needed_to_begin_solving() + + # Store initial params; later used to test if anything changed + self.agent_store_model_params(params['prmtv_par'], + params['aprox_lim']) + + # Attach one-period(/stage) solver to AgentType + self.solve_one_period = \ + make_one_period_oo_solver( + solver, + solveMethod=solveMethod, + eventTiming=eventTiming + ) # allows user-specified alt + + self.make_solution_for_final_period() # Populate instance.solution[0] + + def add_stable_points_to_solution(self, soln): + """ + If they exist, add any stable points to the model solution object. + + Parameters + ---------- + soln : agent_stage_solution + The solution whose stable points are to be calculated + """ + + # Users can effectively solve approx to inf hor PF model by specifying + # the "horizon" (number of periods to be solved). In that special case + # the "conditions" are relevant because we are thinking of it as an + # inf hor model, so allow that case to slip through the cracks + if soln.Pars.horizon != 'infinite': + if soln.Pars.BoroCnstArt is None: + return + else: # finite horizon borrowing constrained model + if self.income_risks_exist: + return # infinite horizon conditions unimportant + + soln.check_conditions(messaging_level=self.messaging_level, quietly=self.quietly) + + if not soln.Bilt.GICRaw: # no mNrmStE + soln.Bilt.mNrmStE = soln.mNrmStE = float('nan') + else: # mNrmStE exists; compute it and check mNrmTrg + soln.Bilt.mNrmStE = soln.mNrmStE_find() + if not self.income_risks_exist: # If a PF model, nothing more to do + soln.Bilt.mNrmTrg = soln.mNrmStE_find() + return + else: + if not soln.Bilt.GICNrm: + soln.Bilt.mNrmTrg = float('nan') + else: # GICNrm exists; calculate it + soln.Bilt.mNrmTrg = soln.mNrmTrg_find() + return + + # CDC 20210511: The old version of ConsIndShockModel mixed calibration and results + # between the agent, the solver, and the solution. The new version puts all results + # on the solution. This requires a final stage solution to exist from the get-go. + # The method below tricks the solver into putting a properly enhanced version of + # solution_terminal into the solution[0] position where it needs to be, leaving + # the agent in a state where invoking the ".solve()" method as before will + # accomplish the same things it did before, but from the new starting setup + + def make_solution_for_final_period(self): + # but want to add extra info required for backward induction + quietly, messaging_level = self.quietly, self.messaging_level + cycles_orig = deepcopy(self.cycles) + tolerance_orig = deepcopy(self.tolerance) + self.tolerance = float('inf') # Any distance satisfies this tolerance + + if self.cycles > 0: # Then it's a finite horizon problem + self.cycles = 0 # solve only one period (leaving MaxKinks be) + self.solve(quietly=quietly, messaging_level=logging.CRITICAL+1) # do not spout nonsense + else: # tolerance of inf means that "solve" will stop after setup ... + self.solve(quietly=quietly, messaging_level=messaging_level) + + self.tolerance = tolerance_orig # which leaves us ready to solve + self.cycles = cycles_orig # with the original convergence criteria + self.solution[0].Bilt.stge_kind['iter_status'] = 'iterator' + self.solution_current = self.solution[0] # current soln is now newly made one + + def agent_post_post_solve(self): # Overwrites version from AgentTypePlus + """For infinite horizon models, add stable points (if they exist).""" + if self.cycles == 0: # if it's an infinite horizon model + if self.messaging_level <= logging.CRITICAL: + self.add_stable_points_to_solution(self.solution[0]) + else: # finite horizon model + self.describe_model_and_calibration( + messaging_level=self.messaging_level, + quietly=self.quietly) + + def check_restrictions(self): + """ + Check that various restrictions are met for the model class. + """ + min0Bounded = { # Things that must be >= 0 + 'tranShkStd', 'permShkStd', 'UnempPrb', 'IncUnemp', 'UnempPrbRet', + 'IncUnempRet'} + + gt0Bounded = { # Things that must be >0 + 'DiscFac', 'Rfree', 'PermGroFac', 'LivPrb'} + + max1Bounded = { # Things that must be <= 1 + 'LivPrb'} + + gt1Bounded = { # Things that must be > 1 + 'CRRA'} + + for var in min0Bounded: + if var in self.__dict__['parameters']: + if self.__dict__['parameters'][var] is not None: + # If a list (because time_var), use extremum of list + if type(self.__dict__['parameters'][var]) == list: + varMin = np.min(self.__dict__['parameters'][var]) + else: + varMin = self.__dict__['parameters'][var] + if varMin < 0: + raise Exception(var+" is negative with value: " + str(varMin)) + for var in gt0Bounded: + if self.__dict__['parameters'][var] is not None: + if var in self.__dict__['parameters']: + if type(self.__dict__['parameters'][var]) == list: + varMin = np.min(self.__dict__['parameters'][var]) + else: + varMin = self.__dict__['parameters'][var] + if varMin <= 0.0: + raise Exception(var+" is nonpositive with value: " + str(varMin)) + + for var in max1Bounded: + if self.__dict__['parameters'][var] is not None: + if var in self.__dict__['parameters']: + if type(self.__dict__['parameters'][var]) == list: + varMax = np.max(self.__dict__['parameters'][var]) + else: + varMax = self.__dict__['parameters'][var] + if varMax > 1.0: + raise Exception(var+" is greater than 1 with value: " + str(varMax)) + + for var in gt1Bounded: + if self.__dict__['parameters'][var] is not None: + if var in self.__dict__['parameters']: + if type(self.__dict__['parameters'][var]) == list: + varMin = np.min(self.__dict__['parameters'][var]) + else: + varMin = self.__dict__['parameters'][var] + if varMin <= 1.0: + if var == 'CRRA' and self.__dict__['parameters'][var] == 1.0: + _log.info('For log utility, use CRRA very close to 1, like 1.00001') + raise Exception( + var+" is less than or equal to 1.0 with value: " + + str(varMax)) + return + + def describe_model_and_calibration(self, messaging_level=logging.INFO, + quietly=False): + + if not hasattr(self, 'solution'): # A solution must have been computed + _log.info('Making final soln because model info stored there') + self.make_solution_for_final_period() + + solution_current = self.solution[0] + solution_current.describe_model_and_calibration(messaging_level, + quietly) + + def check_conditions(self, messaging_level=logging.INFO, quietly=False): + + if not hasattr(self, 'solution'): # A solution must have been computed + _log.info('Make final soln because conditions are computed there') + self.make_solution_for_final_period() + + solution_current = self.solution[0] + solution_current.check_conditions(messaging_level=logging.INFO, + quietly=False) + + def finish_setup_of_default_solution_terminal(self): + """ + Add to `solution_terminal` characteristics of the agent required + for solution of the particular type which are not automatically + created as part of the definition of the generic `solution_terminal.` + """ + # If no solution exists for the agent, + # core.py uses solution_terminal as solution_next + + solution_terminal = self.solution_terminal + + # Natural borrowing constraint: Cannot die in debt + # Measured after income = tranShk*permShk/permShk received + if not hasattr(solution_terminal.Bilt, 'hNrm'): + _log.warning('warning: hNrm should be set in solution_terminal.') + _log.warning('assuming solution_terminal.hNrm = 0.') + solution_terminal.Bilt.hNrm = 0. + solution_terminal.Bilt.BoroCnstNat = -solution_terminal.Bilt.hNrm + + # Define BoroCnstArt if not yet defined + if not hasattr(self.parameters, 'BoroCnstArt'): + solution_terminal.Bilt.BoroCnstArt = None + else: + solution_terminal.Bilt.BoroCnstArt = self.parameters.BoroCnstArt + + solution_terminal.Bilt.stge_kind = {'iter_status': 'terminal_partial'} + + # Solution options + if hasattr(self, 'vFuncBool'): + solution_terminal.Bilt.vFuncBool = self.parameters['vFuncBool'] + else: # default to true + solution_terminal.Bilt.vFuncBool = True + + if hasattr(self, 'CubicBool'): + solution_terminal.Bilt.CubicBool = self.parameters['CubicBool'] + else: # default to false (linear) + solution_terminal.Bilt.CubicBool = False + + solution_terminal.Bilt.parameters = self.parameters + CRRA = self.CRRA +# breakpoint() +# solution_terminal.Bilt = def_utility(solution_terminal.Bilt, CRRA) + + solution_terminal = def_utility_CRRA(solution_terminal, CRRA) +# solution_terminal.Bilt = def_value_funcs(solution_terminal.Bilt, CRRA) + solution_terminal = def_value_funcs(solution_terminal, CRRA) + + return solution_terminal.Bilt + + check_conditions_solver = solver_check_conditions = check_conditions + + def _url_doc_for_this_agent_type_get(self): + # Generate a url that will locate the documentation + self.class_name = self.__class__.__name__ + self.url_ref = "https://econ-ark.github.io/BufferStockTheory" + self.urlroot = self.url_ref+'/#' + self.url_doc = "https://hark.readthedocs.io/en/latest/search.html?q=" +\ + self.class_name+"&check_keywords=yes&area=default#" + + # Prepare PF agent for solution of entire problem + # Overwrites default version from AgentTypePlus + # Overwritten by version in ConsIndShockSolver + def _agent_force_prepare_info_needed_to_begin_solving(self): + # This will be reached by IndShockConsumerTypes when they execute + # PerfForesightConsumerType.__init__ but will subsequently be + # overridden by the _agent_force_prepare_info_needed_to_begin_solving + # method attached to the IndShockConsumerType class + + if (type(self) == PerfForesightConsumerType): + if self.cycles > 0: # finite horizon, not solving terminal period + if hasattr(self, 'BoroCnstArt'): + if isinstance(self.BoroCnstArt, float): # 0.0 means no borrowing + if self.MaxKinks: # If they did specify MaxKinks + if self.MaxKinks > self.cycles: + msg = 'You have requested a number of constraints ' +\ + 'greater than the number of cycles. ' +\ + 'Reducing to MaxKinks = cycles' + self.MaxKinks = self.cycles + _log.critical(msg) + else: # They specified a BoroCnstArt but no MaxKinks + self.MaxKinks = self.cycles + else: # BoroCnstArt is not defined + if not hasattr(self, "MaxKinks"): + self.MaxKinks = self.cycles + else: + if self.MaxKinks: + # What does it mean to have specified MaxKinks + # but no BoroCnstArt? + raise( + AttributeError( + "Kinks are caused by constraints. \n" + + "Cannot specify MaxKinks without constraints!\n" + + " Aborting." + )) + else: + self.MaxKinks = self.cycles + + pre_solve = _agent_force_prepare_info_needed_to_begin_solving + + def initialize_sim(self): + self.mcrlovars = SimpleNamespace() + self.mcrlovars.permShkAgg = self.permShkAgg = self.PermGroFacAgg # Never changes during sim + # CDC 20210428 it would be good if we could separate the sim from the sol variables like this + self.mcrlovars.state_now['PlvlAgg'] = self.state_now['PlvlAgg'] = 1.0 + AgentType.initialize_sim(self) + + def birth(self, which_agents): + """ + Makes new consumers for the given indices. Initialized variables include aNrm and pLvl, as + well as time variables t_age and t_cycle. Normalized assets and permanent income levels + are drawn from lognormal distributions given by aNrmInitMean and aNrmInitStd (etc). + + Parameters + ---------- + which_agents : np.array(Bool) + Boolean array of size self.AgentCount indicating which agents should be "born". + + Returns + ------- + None + """ + # Get and store states for newly born agents + N = np.sum(which_agents) # Number of new consumers to make + self.mcrlovars.state_now['aNrm'][which_agents] = self.state_now['aNrm'][which_agents] = Lognormal( + mu=self.aNrmInitMean, + sigma=self.aNrmInitStd, + seed=self.RNG.randint(0, 2 ** 31 - 1), + ).draw(N) + # why is a now variable set here? Because it's an aggregate. + pLvlInitMean = self.pLvlInitMean + np.log( + self.state_now['PlvlAgg'] + ) # Account for newer cohorts having higher permanent income + self.mcrlovars.state_now['pLvl'][which_agents] = \ + self.state_now['pLvl'][which_agents] = Lognormal( + pLvlInitMean, + self.pLvlInitStd, + seed=self.RNG.randint(0, 2 ** 31 - 1) + ).draw(N) + # How many periods since each agent was born + self.mcrlovars.t_age[which_agents] = self.t_age[which_agents] = 0 + self.mcrlovars.t_cycle[which_agents] = \ + self.t_cycle[ + which_agents + ] = 0 # Which period of the cycle each agent is currently in + return None + + mcrlo_birth = birth_mcrlo = birth + + def death(self): + """ + Determine which agents die this period and must be replaced. + + Uses the sequence in LivPrb + to determine survival probabilities for each agent. + + Parameters + ---------- + None + + Returns + ------- + which_agents : np.array(bool) + Boolean array of size AgentCount indicating which agents die. + """ + # Determine who dies + DiePrb_by_t_cycle = 1.0 - np.asarray(self.LivPrb) + DiePrb = DiePrb_by_t_cycle[ + self.t_cycle - 1 + ] # Time has already advanced, so look back one + DeathShks = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw( + N=self.AgentCount + ) + which_agents = DeathShks < DiePrb + if self.T_age is not None: # Kill agents that have lived for too many periods + too_old = self.t_age >= self.T_age + which_agents = np.logical_or(which_agents, too_old) + return which_agents + + mcrlo_death = death_mcrlo = death + + def get_shocks(self): + """ + Finds permanent and transitory income "shocks" for each agent this period. When this is a + perfect foresight model, there are no stochastic shocks: permShk = PermGroFac for each + agent (according to their t_cycle) and tranShk = 1.0 for all agents. + + Parameters + ---------- + None + + Returns + ------- + None + """ + PermGroFac = np.array(self.PermGroFac) + self.shocks['permShk'] = PermGroFac[ + self.t_cycle - 1 + ] # cycle time has already been advanced + self.shocks['tranShk'] = np.ones(self.AgentCount) + + get_shocks_mcrlo = mcrlo_get_shocks = get_shocks + + def get_Rfree(self): # -> mcrlo_get_Rfree. + # CDC: We should have a generic mcrlo_get_all_params + """ + Returns an array of size self.AgentCount with self.Rfree in every entry. + + Parameters + ---------- + None + + Returns + ------- + Rfree : np.array + Array of size self.AgentCount with risk free interest rate for each agent. + """ + Rfree = self.Rfree * np.ones(self.AgentCount) + return Rfree + + mcrlo_get_Rfree = get_Rfree_mcrlo = get_Rfree + + def transition(self): # -> mcrlo_trnsitn + pLvlPrev = self.state_prev['pLvl'] + aNrmPrev = self.state_prev['aNrm'] + Rfree = self.get_Rfree() + + # Calculate new states: normalized market resources and permanent income level + pLvl = pLvlPrev*self.shocks['permShk'] # Updated permanent income level + # Updated aggregate permanent productivity level + PlvlAgg = self.state_prev['PlvlAgg']*self.permShkAgg + # "Effective" interest factor on normalized assets + RNrm = Rfree/self.shocks['permShk'] + bNrm = RNrm*aNrmPrev # Bank balances before labor income + mNrm = bNrm + self.shocks['tranShk'] # Market resources after income + + return pLvl, PlvlAgg, bNrm, mNrm, None + + transition_mcrlo = mcrlo_transition = transition + + def get_controls(self): # -> mcrlo_get_ctrls + """ + Calculates consumption for each consumer of this type using the consumption functions. + + Parameters + ---------- + None + + Returns + ------- + None + """ + cNrm = np.zeros(self.AgentCount) + np.nan + MPCnow = np.zeros(self.AgentCount) + np.nan + for t in range(self.T_cycle): + these = t == self.t_cycle + cNrm[these], MPCnow[these] = self.solution[t].cFunc.eval_with_derivative( + self.state_now['mNrm'][these] + ) + self.controls['cNrm'] = cNrm + + # MPCnow is not really a control + self.MPCnow = MPCnow + return None + + get_controls_mcrlo = mcrlo_get_controls = get_controls + + def get_poststates(self): # -> mcrlo_get_poststes + """ + Calculates end-of-period assets for each consumer of this type. + + Parameters + ---------- + None + + Returns + ------- + None + """ + # should this be "", or "Prev"?!? + self.state_now['aNrm'] = self.state_now['mNrm'] - self.controls['cNrm'] + # Useful in some cases to precalculate asset level + self.state_now['aLvl'] = self.state_now['aNrm'] * self.state_now['pLvl'] + + # moves now to prev + super().get_poststates() + + return None + + mcrlo_get_poststates = get_poststates_mcrlo = get_poststates + + +class IndShockConsumerType(PerfForesightConsumerType): + """ + A consumer with idiosyncratic shocks to permanent and transitory income. + + Problem is defined by a sequence of income distributions, survival prob- + abilities, permanent income growth rates, and time invariant values for + risk aversion, the discount factor, the interest rate, the grid of end-of- + period assets, and (optionally) an artificial borrowing constraint. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods should be solved. If zero, + the solver will continue until successive policy functions are closer + than the tolerance specified as a default parameter. + + solution_startfrom : agent_stage_solution, optional + A user-specified terminal period/stage solution for the iteration, + to be used in place of the hardwired solution_terminal. One use + might be to set a loose tolerance to get a quick `solution_rough` + using the default hardwired solution (nobequest), then + set the tolerance tighter, or change some approximation parameter, + and resume iteration using `solution_startfrom = solution_rough` until + the new tolerance is met with the (presumably better but slower) + approximation parameter. + """ + + # Time invariant parameters + time_inv_ = PerfForesightConsumerType.time_inv_ + [ + "vFuncBool", + "CubicBool", + ] + time_inv_.remove( # Unwanted item(s) inherited from PerfForesight + "MaxKinks" # PF infhor with MaxKinks equiv to finhor with hor=MaxKinks + ) + + def __init__(self, + messaging_level=logging.INFO, quietly=False, + solution_startfrom=None, + solverType='HARK', + solveMethod='EGM', + eventTiming='EOP', + solverName=ConsIndShockSolverBasic, + **kwds): + params = init_idiosyncratic_shocks.copy() # Get default params + params.update(kwds) # Update/overwrite defaults with user-specified + + # Inherit characteristics of a PF model with the same parameters + PerfForesightConsumerType.__init__(self, # cycles=cycles, + messaging_level=messaging_level, + quietly=quietly, + **params) + + self.update_parameters_for_this_agent_subclass() # Add new Pars + + # If precooked terminal stage not provided by user ... + if not hasattr(self, 'solution_startfrom'): # .. then init the default + self._agent_force_prepare_info_needed_to_begin_solving() + + # - Default interpolation method is piecewise linear + # - Cubic is smoother, works if problem has no constraints + # - User may or may not want to create the value function + # TODO: CDC 20210428: Basic solver is not worth preserving + # - 1. We might as well always compute vFunc + # - 2. Cubic vs linear interpolation is not worth two different solvers + # - * Cubic should be preserved as an option + if self.CubicBool or self.vFuncBool: + solverName = ConsIndShockSolver + + # Attach the corresponding one-stage solver to the agent + # This is what gets called when the user invokes [instance].solve() + if (solverType == 'HARK') or (solverType == 'DARKolo'): + # breakpoint() + self.solve_one_period = \ + make_one_period_oo_solver( + solverName, + solveMethod=solveMethod, + eventTiming=eventTiming + ) + + if (solverType == 'dolo') or (solverType == 'DARKolo'): + # If we want to solve with dolo, set up the model + self.dolo_model() + + # Store setup parameters so later we can check for changes + # that necessitate restarting solution process + + self.agent_store_model_params(params['prmtv_par'], params['aprox_lim']) + + # Put the (enhanced) solution_terminal in self.solution[0] + + self.make_solution_for_final_period() + + def dolo_model(self): + # Create a dolo version of the model + return # return because the code below is the sketch of a beginning.. + from dolo import yaml_import + self.dolo_modl = yaml_import( + '/Volumes/Data/Code/ARK/DARKolo/chimeras/BufferStock/bufferstock.yaml' + ) + if self.verbose >= 2: + _log.info(self.dolo_modl) + + def _agent_force_prepare_info_needed_to_begin_solving(self): + """ + Update characteristics of the agent that need to be recomputed. + + Update parameters changed since the last time the solver was + invoked. + + Parameters + ---------- + None + + Returns + ------- + None + + """ + solve_par_vals_now = {} + if not hasattr(self, 'solve_par_vals'): # We haven't set it up yet + self.update_income_process() + self.update_assets_grid() + else: # it has been set up, so see if anything changed + for par in self.solve_par_vals: + solve_par_vals_now[par] = getattr(self, par) + if not solve_par_vals_now == self.solve_par_vals: + if not self.quietly: + _log.info('Some parameter has changed since last update.') + _log.info('Storing calculated consequences for grid etc.') + self.update_income_process() + self.update_assets_grid() + + pre_solve = _agent_force_prepare_info_needed_to_begin_solving + + # The former "[AgentType].update_pre_solve()" was not good nomenclature -- + # easy to confuse with the also-existing "[AgentType].pre_solve()" and with + # "[SolverType].prepare_to_solve()". The new name, + # + # _agent_force_prepare_info_needed_to_begin_solving() + # + # is better. The old one + # is preserved as an alias, below, to prevent breakage of existing code: + + def update_income_process(self): + """ + Updates agent's income shock specs based on its current attributes. + + Parameters + ---------- + none + + Returns: + -------- + none + """ + + (self.IncShkDstn, + self.permShkDstn, + self.tranShkDstn, + ) = self.construct_lognormal_income_process_unemployment() + self.add_to_time_vary("IncShkDstn", "permShkDstn", "tranShkDstn") + self.parameters.update({'IncShkDstn': self.IncShkDstn, + 'permShkDstn': self.permShkDstn, + 'tranShkDstn': self.tranShkDstn}) + + def update_assets_grid(self): + """ + Updates this agent's end-of-period assets grid by constructing a multi- + exponentially spaced grid of aXtra values. + + Parameters + ---------- + none + + Returns + ------- + none + """ + self.aXtraGrid = construct_assets_grid(self) + self.add_to_time_inv("aXtraGrid") + self.parameters.update({'aXtraGrid': self.aXtraGrid}) + + def reset_rng(self): + """ + Reset the RNG behavior of this type. This method is called automatically + by initialize_sim(), ensuring that each simulation run uses the same sequence + of random shocks; this is necessary for structural estimation to work. + This method extends AgentType.reset_rng() to also reset elements of IncShkDstn. + + Parameters + ---------- + None + + Returns + ------- + None + """ + PerfForesightConsumerType.reset_rng(self) + + # Reset IncShkDstn if it exists (it might not because reset_rng is called at init) + if hasattr(self, "IncShkDstn"): + for dstn in self.IncShkDstn: + dstn.reset() + + mcrlo_reset_rng = reset_rng_mcrlo = reset_rng + + def construct_lognormal_income_process_unemployment(self): + """ + Generates a sequence of discrete approximations to the income process for each + life period, from end of life to beginning of life. Permanent shocks are mean + one lognormally distributed with standard deviation permShkStd[t] during the + working life, and degenerate at 1 in the retirement period. transitory shocks + are mean one lognormally distributed with a point mass at IncUnemp with + probability UnempPrb while working; they are mean one with a point mass at + IncUnempRet with probability UnempPrbRet. Retirement occurs + after t=T_retire periods of working. + + Note 1: All time in this function runs forward, from t=0 to t=T + + Note 2: All parameters are passed as attributes of the input parameters. + + Parameters (passed as attributes of the input parameters) + ---------- + permShkStd : [float] + List of standard deviations in log permanent income uncertainty during + the agent's life. + permShkCount : int + The number of approximation points to be used in the discrete approxima- + tion to the permanent income shock distribution. + tranShkStd : [float] + List of standard deviations in log transitory income uncertainty during + the agent's life. + tranShkCount : int + The number of approximation points to be used in the discrete approxima- + tion to the permanent income shock distribution. + UnempPrb : float + The probability of becoming unemployed during the working period. + UnempPrbRet : float + The probability of not receiving typical retirement income when retired. + T_retire : int + The index value for the final working period in the agent's life. + If T_retire <= 0 then there is no retirement. + IncUnemp : float + transitory income received when unemployed. + IncUnempRet : float + transitory income received while "unemployed" when retired. + T_cycle : int + Total number of non-terminal periods in the consumer's sequence of periods. + + Returns + ------- + IncShkDstn : [distribution.Distribution] + A list with elements from t = 0 to T_cycle, each of which is a + discrete approximation to the joint income distribution at at [t] + permShkDstn : [[distribution.Distribution]] + A list with elements from t = 0 to T_cycle, each of which is a + discrete approximation to the permanent shock distribution at [t] + tranShkDstn : [[distribution.Distribution]] + A list with elements from t = 0 to T_cycle, each of which is a + discrete approximation to the transitory shock distribution at [t] + """ + # Unpack the parameters from the input + + permShkStd = self.permShkStd + permShkCount = self.permShkCount + tranShkStd = self.tranShkStd + tranShkCount = self.tranShkCount + UnempPrb = self.UnempPrb + UnempPrbRet = self.UnempPrbRet + T_retire = self.T_retire + IncUnemp = self.IncUnemp + IncUnempRet = self.IncUnempRet + T_cycle = self.T_cycle + + # make a dictionary of the parameters + # Created so later we can determine whether any have changed + parameters = { + 'permShkStd': self.permShkStd, + 'permShkCount': self.permShkCount, + 'tranShkStd': self.tranShkStd, + 'tranShkCount': self.tranShkCount, + 'UnempPrb': self.UnempPrb, + 'UnempPrbRet': self.UnempPrbRet, + 'T_retire': self.T_retire, + 'IncUnemp': self.IncUnemp, + 'IncUnempRet': self.IncUnempRet, + 'T_cycle': self.T_cycle, + 'ShkPosn': {'perm': 0, 'tran': 1} + } + + # constructed_by: later, we can determine whether another distribution + # object was constructed using the same method or a different method + constructed_by = {'method': + 'construct_lognormal_income_process_unemployment'} + + IncShkDstn = [] # Discrete approximations to income process in each period + permShkDstn = [] # Discrete approximations to permanent income shocks + tranShkDstn = [] # Discrete approximations to transitory income shocks + + # Fill out a simple discrete RV for retirement, with value 1.0 (mean of shocks) + # in normal times; value 0.0 in "unemployment" times with small prob. + if T_retire > 0: + if UnempPrbRet > 0: + # permShkValsNxtRet = np.array([1.0, 1.0]) # Permanent income is deterministic in retirement (2 states for temp income shocks) + tranShkValsRet = np.array( + [ + IncUnempRet, + (1.0 - UnempPrbRet * IncUnempRet) / (1.0 - UnempPrbRet), + ] + ) + ShkPrbsRet = np.array([UnempPrbRet, 1.0 - UnempPrbRet]) + else: + (IncShkDstnRet, + permShkDstnRet, + tranShkDstnRet, + ) = self.construct_lognormal_income_process_unemployment() + ShkPrbsRet = IncShkDstnRet.pmf + + # Loop to fill in the list of IncShkDstn random variables. + for t in range(T_cycle): # Iterate over all periods, counting forward + if T_retire > 0 and t >= T_retire: + # Then we are in the "retirement period" and add a retirement income object. + IncShkDstn.append(deepcopy(IncShkDstnRet)) + permShkDstn.append([np.array([1.0]), np.array([1.0])]) + tranShkDstn.append([ShkPrbsRet, tranShkValsRet]) + else: + # We are in the "working life" periods. + tranShkDstn_t = MeanOneLogNormal(sigma=tranShkStd[t]).approx( + tranShkCount, tail_N=0 + ) + if UnempPrb > 0: + tranShkDstn_t = add_discrete_outcome_constant_mean( + tranShkDstn_t, p=UnempPrb, x=IncUnemp + ) + permShkDstn_t = MeanOneLogNormal(sigma=permShkStd[t]).approx( + permShkCount, tail_N=0 + ) + IncShkDstn.append( + combine_indep_dstns( + permShkDstn_t, + tranShkDstn_t, + seed=self.RNG.randint(0, 2 ** 31 - 1), + ) + ) # mix the independent distributions + permShkDstn.append(permShkDstn_t) + tranShkDstn.append(tranShkDstn_t) + + IncShkDstn[-1].parameters = parameters + IncShkDstn[-1].constructed_by = constructed_by + + return IncShkDstn, permShkDstn, tranShkDstn + + def get_shocks(self): # mcrlo simulation tool + """ + Gets permanent and transitory income shocks for this period. Samples from IncShkDstn for + each period in the cycle. + + Parameters + ---------- + None + + Returns + ------- + None + """ + permShk = np.zeros(self.AgentCount) # Initialize shock arrays + tranShk = np.zeros(self.AgentCount) + newborn = self.t_age == 0 + for t in range(self.T_cycle): + these = t == self.t_cycle + N = np.sum(these) + if N > 0: + IncShkDstn = self.IncShkDstn[ + t - 1 + ] # set current income distribution + PermGroFac = self.PermGroFac[t - 1] # and permanent growth factor + # Get random draws of income shocks from the discrete distribution + IncShks = IncShkDstn.draw(N) + + permShk[these] = ( + IncShks[0, :] * PermGroFac + ) # permanent "shock" includes expected growth + tranShk[these] = IncShks[1, :] + + # That procedure used the *last* period in the sequence for newborns, but that's not right + # Redraw shocks for newborns, using the *first* period in the sequence. Approximation. + N = np.sum(newborn) + if N > 0: + these = newborn + IncShkDstn = self.IncShkDstn[0] # set current income distribution + PermGroFac = self.PermGroFac[0] # and permanent growth factor + + # Get random draws of income shocks from the discrete distribution + EventDraws = IncShkDstn.draw_events(N) + permShk[these] = ( + IncShkDstn.X[0][EventDraws] * PermGroFac + ) # permanent "shock" includes expected growth + tranShk[these] = IncShkDstn.X[1][EventDraws] + # permShk[newborn] = 1.0 + tranShk[newborn] = 1.0 + + # Store the shocks in self + self.Emp = np.ones(self.AgentCount, dtype=bool) + self.Emp[tranShk == self.IncUnemp] = False + self.shocks['permShk'] = permShk + self.shocks['tranShk'] = tranShk + + get_shocks_mcrlo = mcrlo_get_shocks = get_shocks + + +# Make a dictionary to specify a "kinked R" idiosyncratic shock consumer +init_kinked_R = dict( + init_idiosyncratic_shocks, + **{ + "Rboro": 1.20, # Interest factor on assets when borrowing, a < 0 + "Rsave": 1.02, # Interest factor on assets when saving, a > 0 + "BoroCnstArt": None, # kinked R is a bit silly if borrowing not allowed + "CubicBool": True, # kinked R is now compatible with linear cFunc and cubic cFunc + "aXtraCount": 48, # ...so need lots of extra gridpoints to make up for it + } +) +del init_kinked_R["Rfree"] # get rid of constant interest factor + + +class KinkedRconsumerType(IndShockConsumerType): + """ + A consumer type that faces idiosyncratic shocks to income and has a different + interest factor on saving vs borrowing. Extends IndShockConsumerType, with + very small changes. Solver for this class is currently only compatible with + linear spline interpolation. + + Parameters + ---------- + cycles : int + Number of times the sequence of periods should be solved. + """ + + time_inv_ = copy(IndShockConsumerType.time_inv_) + time_inv_.remove("Rfree") + time_inv_ += ["Rboro", "Rsave"] + + def __init__(self, cycles=1, **kwds): + params = init_kinked_R.copy() + params.update(kwds) + + # Initialize a basic AgentType + PerfForesightConsumerType.__init__(self, cycles=cycles, **params) + + # Add consumer-type specific objects, copying to create independent versions + self.solve_one_period = make_one_period_oo_solver( + ConsKinkedRsolver) + # Make assets grid, income process, terminal solution + + def _agent_force_prepare_info_needed_to_begin_solving(self): + self.update_assets_grid() + self.update_income_process() + + def make_euler_error_func(self, mMax=100, approx_inc_dstn=True): + """ + Creates a "normalized Euler error" function for this instance, mapping + from market resources to "consumption error per dollar of consumption." + Stores result in attribute eulerErrorFunc as an interpolated function. + Has option to use approximate income distribution stored in self.IncShkDstn + or to use a (temporary) very dense approximation. + + SHOULD BE INHERITED FROM ConsIndShockModel + + Parameters + ---------- + mMax : float + Maximum normalized market resources for the Euler error function. + approx_inc_dstn : Boolean + Indicator for whether to use the approximate discrete income distri- + bution stored in self.IncShkDstn[0], or to use a very accurate + discrete approximation instead. When True, uses approximation in + IncShkDstn; when False, makes and uses a very dense approximation. + + Returns + ------- + None + + Notes + ----- + This method is not used by any other code in the library. Rather, it is here + for expository and benchmarking purposes. + """ + raise NotImplementedError() + + def get_Rfree(self): + """ + Returns an array of size self.AgentCount with self.Rboro or self.Rsave in each entry, based + on whether self.aNrm >< 0. + + Parameters + ---------- + None + + Returns + ------- + Rfree : np.array + Array of size self.AgentCount with risk free interest rate for each agent. + """ + Rfree = self.Rboro * np.ones(self.AgentCount) + Rfree[self.state_prev['aNrm'] > 0] = self.Rsave + return Rfree + + mcrlo_get_Rfree = get_Rfree_mcrlo = get_Rfree diff --git a/HARK/ConsumptionSaving/ConsIndShockModel_Both.py b/HARK/ConsumptionSaving/ConsIndShockModel_Both.py new file mode 100755 index 000000000..78f728355 --- /dev/null +++ b/HARK/ConsumptionSaving/ConsIndShockModel_Both.py @@ -0,0 +1,330 @@ +# -*- coding: utf-8 -*- +from HARK.utilities import make_grid_exp_mult +from HARK.interpolation import (LinearInterp, ValueFuncCRRA, MargValueFuncCRRA, + MargMargValueFuncCRRA) +from HARK.utilities import ( # These are used in exec so IDE doesn't see them + CRRAutility, CRRAutilityPP, CRRAutilityP_invP, + CRRAutility_inv, CRRAutility_invP, CRRAutilityP, CRRAutilityP_inv) +import numpy as np +from copy import deepcopy + +from types import SimpleNamespace +from ast import parse as parse # Allow storing python stmts as objects + + +class ValueFunctions(SimpleNamespace): + """Equations that define value function and related Bellman objects.""" + + pass + + +def define_transition(soln, transition_name): + """ + Add to Modl.Transitions the transition defined by transition_name. + + Parameters + ---------- + soln : agent_stage_solution + A solution with an atached Modl object. + + transition_name : str + Name of the step in Pars.transitions_possible to execute + + Returns + ------- + None. + + """ + transitions_possible = soln.Bilt.transitions_possible + transition = transitions_possible[transition_name] + transiter = {} # It's the actor that actually does the job + transiter['compiled'] = {} + transiter['raw_text'] = {} + transiter['last_val'] = {} + + for eqn_name in transition: + transiter['raw_text'].update({eqn_name: transition[eqn_name]}) + tree = parse(transition[eqn_name], mode='exec') + compiled = compile(tree, filename="", mode='exec') + transiter['compiled'].update({eqn_name: compiled}) + + soln.Modl.Transitions[transition_name] = transiter + return soln + + +def def_utility_CRRA(soln, CRRA): + """ + Define CRRA utility function and its relatives (derivatives, inverses). + + Saves them as attributes of self for other methods to use. + + Parameters + ---------- + soln : ConsumerSolutionOneStateCRRA + + Returns + ------- + none + """ + Bilt, Pars, Modl = soln.Bilt, soln.Pars, soln.Modl + Info = Modl.Info = {**Bilt.__dict__, **Pars.__dict__} + + Modl.Rewards = SimpleNamespace() + + Modl.Rewards.raw_text = {} + Modl.Rewards.eqns = {} + Modl.Rewards.vals = {} + + # Add required funcs to Modl.Info + for func in {'CRRAutility', 'CRRAutilityP', 'CRRAutilityPP', + 'CRRAutility_inv', 'CRRAutility_invP', 'CRRAutilityP_inv', + 'CRRAutilityP_invP'}: + Info[func] = globals()[func] + + # Hard-wire the passed CRRA into the utility function and its progeny + eqns_source = { + 'u_D0': + 'u = lambda c: CRRAutility(c,' + str(CRRA) + ')', + 'u_D1': + 'u.dc = lambda c: CRRAutilityP(c, ' + str(CRRA) + ' )', + 'u_D2': + 'u.dc.dc = lambda c: CRRAutilityPP(c, ' + str(CRRA) + ')', + 'uNvrs_D0': + 'u.Nvrs = lambda u: CRRAutility_inv(u, ' + str(CRRA) + ')', + 'uNvrs_D1': + 'u.Nvrs.du = lambda u: CRRAutility_invP(u, ' + str(CRRA) + ' )', + 'u_D1_Nvrs': + 'u.dc.Nvrs = lambda uP: CRRAutilityP_inv(uP, ' + str(CRRA) + ')', + 'u_D1_Nvrs_D1': + 'u.dc.Nvrs.du = lambda uP: CRRAutilityP_invP(uP, ' + str(CRRA) + ')', + } + + # Put the utility function in the "rewards" part of the Modl object + for eqn_name in eqns_source.keys(): + tree = parse(eqns_source[eqn_name], mode='exec') + code = compile(tree, filename="", mode='exec') + Modl.Rewards.eqns.update({eqn_name: code}) + exec(code, {**globals(), **Info}, Modl.Rewards.vals) + + Modl.Rewards.raw_text = eqns_source + + Bilt.__dict__.update({k: v for k, v in Modl.Rewards.vals.items()}) + + return soln + + +def def_value_funcs(soln, CRRA): + r""" + Define the value and function and its derivatives for this period. + + See PerfForesightConsumerType.ipynb for a brief explanation + and the links below for a fuller treatment. + + https://llorracc.github.io/SolvingMicroDSOPs/#vFuncPF + + Parameters + ---------- + soln : agent_stage_solution + + Returns + ------- + soln : agent_stage_solution, enhanced with value function + + Notes + ----- + Call vFuncPF the value function for solution to the perfect foresight CRRA + consumption problem in t for a consumer with no bequest motive and no + constraints. ('Top' because this is an upper bound for the value functions + that would characterize consumers with constraints or uncertainty). For + such a problem, the MPC in period t is constant at :math:`\\kappa_{t}`, and + calling relative risk aversion :math:`\\rho`, the inverse value function + vFuncPFNvrs has constant slope :math:`\\kappa_{t}^{-\\rho/(1-\\rho)}` and + vFuncPFNvrs has value of zero at the lower bound of market resources. + """ + Bilt, Pars, Modl = soln.Bilt, soln.Pars, soln.Modl + + # Info needed to create the model objects + Info = Modl.Info = {**Bilt.__dict__, **Pars.__dict__} + Info['about'] = {'Info available when model creation equations executed'} + + Modl.Value = ValueFunctions() + Modl.Value.eqns = {} # Equations + Modl.Value.vals = {} # Compiled and executed result at time of exec + + eqns_source = {} # For storing the equations + # Pattern below: Equations needed to define value function and derivatives + # Each eqn is preceded by adding to the scope whatever is needed + # to make sure the variables in the equation + +# CRRA, MPCmin = Pars.CRRA, Bilt.MPCmin + eqns_source.update( + {'vFuncPFNvrsSlopeLim': + 'vFuncPFNvrsSlopeLim = MPCmin ** (-CRRA / (1.0 - CRRA))'}) + + # vFuncPFNvrs function +# mNrmMin = Bilt.mNrmMin + Info['LinearInterp'] = LinearInterp # store so it can be retrieved later + + eqns_source.update( + {'vFuncPFNvrs': + 'vFuncPFNvrs = LinearInterp(' + + 'np.array([mNrmMin, mNrmMin + 1.0]),' + + 'np.array([0.0, vFuncPFNvrsSlopeLim]))'}) + + # vFunc and its derivatives + Info['ValueFuncCRRA'] = ValueFuncCRRA + Info['MargValueFuncCRRA'] = MargValueFuncCRRA + Info['MargMargValueFuncCRRA'] = MargMargValueFuncCRRA + + # Derivative 0 (undifferentiated) + eqns_source.update( + {'vFunc_D0': + 'vFunc = ValueFuncCRRA(vFuncPFNvrs, CRRA)'}) + +# cFunc = Bilt.cFunc + + # Derivative 1 + eqns_source.update( + {'vFunc_D1': + 'vFunc.dm = MargValueFuncCRRA(cFunc, CRRA)'}) + + # Derivative 2 + eqns_source.update( + {'vFunc_D2': + 'vFunc.dm.dm = MargMargValueFuncCRRA(cFunc, CRRA)'}) + + # Store the equations in Modl.Value.eqns so they can be retrieved later + # then execute them now + for eqn_name in eqns_source.keys(): + # print(eqn_name+': '+eqns_source[eqn_name]) + tree = parse(eqns_source[eqn_name], mode='exec') + code = compile(tree, filename="", mode='exec') + Modl.Value.eqns.update({eqn_name: code}) + exec(code, {**globals(), **Modl.Info}, Modl.Value.vals) + + # Add newly created stuff to Bilt namespace + Bilt.__dict__.update({k: v for k, v in Modl.Value.vals.items()}) + + soln.vFunc = Bilt.vFunc # vFunc needs to be on root as well as Bilt + + Modl.Value.eqns_source = eqns_source # Save uncompiled source code + + return soln + + +def_value_CRRA = def_value_funcs + + +def apply_flat_income_tax( + IncShkDstn, tax_rate, T_retire, unemployed_indices=None, + transitory_index=2): + """ + Apply a flat income tax rate to employed income states. + + Effective only during the working period of life (those before T_retire). + + (Time runs forward in this function.) + + Parameters + ---------- + IncShkDstn : [distribution.Distribution] + The discrete approximation to income distribution in each time period. + tax_rate : float + A flat income tax rate to be applied to all employed income. + T_retire : int + The time index after which the agent retires. + unemployed_indices : [int] + Indices of transitory shocks representing unemployment states (no tax). + transitory_index : int + The index of each element of IncShkDstn representing transitory shocks. + + Returns + ------- + IncShkDstn_new : [distribution.Distribution] + The updated income distributions, after applying the tax. + """ + unemployed_indices = ( + unemployed_indices if unemployed_indices is not None else list() + ) + IncShkDstn_new = deepcopy(IncShkDstn) + i = transitory_index + for t in range(len(IncShkDstn)): + if t < T_retire: + for j in range((IncShkDstn[t][i]).size): + if j not in unemployed_indices: + IncShkDstn_new[t][i][j] = \ + IncShkDstn[t][i][j] * (1 - tax_rate) + return IncShkDstn_new + +# ======================================================= +# ================ Other useful functions =============== +# ======================================================= + + +def construct_assets_grid(parameters): + """ + Construct base grid of post-decision states. + + Represents end-of-period assets above the absolute minimum. + + All parameters passed as attributes of the single input parameters. The + input can be an instance of a ConsumerType, or a custom Parameters class. + + Parameters + ---------- + aXtraMin: float + Minimum value for the a-grid + aXtraMax: float + Maximum value for the a-grid + aXtraCount: int + Size of the a-grid + aXtraExtra: [float] + Extra values for the a-grid. + exp_nest: int + Level of nesting for the exponentially spaced grid + + Returns + ------- + aXtraGrid: np.ndarray + Base array of values for the post-decision-state grid. + """ + # Unpack the parameters + aXtraMin = parameters.aXtraMin + aXtraMax = parameters.aXtraMax + aXtraCount = parameters.aXtraCount + aXtraExtra = parameters.aXtraExtra + grid_type = "exp_mult" + exp_nest = parameters.aXtraNestFac + + # Set up post decision state grid: + aXtraGrid = None + if grid_type == "linear": + aXtraGrid = np.linspace(aXtraMin, aXtraMax, aXtraCount) + elif grid_type == "exp_mult": + aXtraGrid = make_grid_exp_mult( + ming=aXtraMin, maxg=aXtraMax, ng=aXtraCount, timestonest=exp_nest + ) + else: + raise Exception( + "grid_type not recognized in __init__." + + "Please ensure grid_type is 'linear' or 'exp_mult'" + ) + # Add in additional points for the grid: + for a in aXtraExtra: + if a is not None: + if a not in aXtraGrid: + j = aXtraGrid.searchsorted(a) + aXtraGrid = np.insert(aXtraGrid, j, a) + return aXtraGrid + + +def define_reward(soln, reward=def_utility_CRRA): + """Bellman reward.""" + soln = reward(soln, soln.Pars.CRRA) + return soln + + +def define_t_reward(soln, reward): + """Bellman reward.""" + soln = reward(soln, soln.Pars.CRRA) + return soln diff --git a/HARK/ConsumptionSaving/ConsIndShockModel_KinkedRSolver.py b/HARK/ConsumptionSaving/ConsIndShockModel_KinkedRSolver.py new file mode 100755 index 000000000..d51cf0e2f --- /dev/null +++ b/HARK/ConsumptionSaving/ConsIndShockModel_KinkedRSolver.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon Jun 21 23:21:19 2021 + +@author: ccarroll +""" + +############################################################################## + +from HARK.ConsumptionSaving.ConsIndShockModel import ConsIndShockSolver + + +class ConsKinkedRsolver(ConsIndShockSolver): + """ + A class to solve a single period consumption-saving problem where the interest + rate on debt differs from the interest rate on savings. Inherits from + ConsIndShockSolver, with nearly identical inputs and outputs. The key diff- + erence is that Rfree is replaced by Rsave (a>0) and Rboro (a<0). The solver + can handle Rboro == Rsave, which makes it identical to ConsIndShocksolver, but + it terminates immediately if Rboro < Rsave, as this has a different solution_current. + + Parameters + ---------- + folw : ConsumerSolution + The solution to next period's one period problem. + IncShkDstn : distribution.Distribution + A discrete + approximation to the income process between the period being solved + and the one immediately following (in folw). + LivPrb : float + Survival probability; likelihood of being alive at the beginning of + the succeeding period. + DiscFac : float + Intertemporal discount factor for future utility. + CRRA : float + Coefficient of relative risk aversion. + Rboro: float + Interest factor on assets between this period and the succeeding + period when assets are negative. + Rsave: float + Interest factor on assets between this period and the succeeding + period when assets are positive. + PermGroFac : float + Expected permanent income growth factor at the end of this period. + BoroCnstArt: float or None + Borrowing constraint for the minimum allowable assets to end the + period with. If it is less than the natural borrowing constraint, + then it is irrelevant; BoroCnstArt=None indicates no artificial bor- + rowing constraint. + aXtraGrid: np.array + Array of "extra" end-of-period asset values-- assets above the + absolute minimum acceptable level. + vFuncBool: boolean + An indicator for whether the value function should be computed and + included in the reported soln_crnt. + CubicBool: boolean + An indicator for whether the solver should use cubic or linear inter- + polation. + """ + + def __init__( + self, + folw, + IncShkDstn, + LivPrb, + DiscFac, + CRRA, + Rboro, + Rsave, + PermGroFac, + BoroCnstArt, + aXtraGrid, + vFuncBool, + CubicBool, + ): + assert ( + Rboro >= Rsave + ), "Interest factor on debt less than interest factor on savings!" + + # Initialize the solver. Most of the steps are exactly the same as in + # the non-kinked-R basic case, so start with that. + ConsIndShockSolver.__init__( + self, + folw, + IncShkDstn, + LivPrb, + DiscFac, + CRRA, + Rboro, + PermGroFac, + BoroCnstArt, + aXtraGrid, + vFuncBool, + CubicBool, + ) + + # Assign the interest rates as class attributes, to use them later. + self.bilt.Rboro = self.Rboro = Rboro + self.bilt.Rsave = self.Rsave = Rsave + self.bilt.cnstrct = {'vFuncBool', 'IncShkDstn'} + + self.Rboro = Rboro + self.Rsave = Rsave + self.cnstrct = {'vFuncBool', 'IncShkDstn'} + + def make_cubic_cFunc(self, mNrm, cNrm): + """ + Makes a cubic spline interpolation that contains the kink of the unconstrained + consumption function for this period. + + + ---------- + mNrm : np.array + Corresponding market resource points for interpolation. + cNrm : np.array + Consumption points for interpolation. + + Returns + ------- + cFunc_unconstrained : CubicInterp + The unconstrained consumption function for this period. + """ + # Call the make_cubic_cFunc from ConsIndShockSolver. + cFuncUncKink = super().make_cubic_cFunc(mNrm, cNrm) + + # Change the coeffients at the kinked points. + cFuncUncKink.coeffs[self.i_kink + 1] = [ + cNrm[self.i_kink], + mNrm[self.i_kink + 1] - mNrm[self.i_kink], + 0, + 0, + ] + + return cFuncUncKink + + def make_ending_states(self): + """ + Prepare to calculate end-of-period marginal value by creating an array + of market resources that the agent could have next period, considering + the grid of end-of-period assets and the distribution of shocks he might + experience next period. This differs from the baseline case because + different savings choices yield different interest rates. + + Parameters + ---------- + none + + Returns + ------- + aNrm : np.array + A 1D array of end-of-period assets; stored as attribute of self. + """ + KinkBool = ( + self.bilt.Rboro > self.bilt.Rsave + ) # Boolean indicating that there is actually a kink. + # When Rboro == Rsave, this method acts just like it did in IndShock. + # When Rboro < Rsave, the solver would have terminated when it was called. + + # Make a grid of end-of-period assets, including *two* copies of a=0 + if KinkBool: + aNrm = np.sort( + np.hstack( + (np.asarray(self.aXtraGrid) + self.mNrmMin, np.array([0.0, 0.0])) + ) + ) + else: + aNrm = np.asarray(self.aXtraGrid) + self.mNrmMin + aXtraCount = aNrm.size + + # Make tiled versions of the assets grid and income shocks + ShkCount = self.Pars.tranShkVals.size + aNrm_temp = np.tile(aNrm, (ShkCount, 1)) + permShkVals_temp = (np.tile(self.Pars.permShkVals, (aXtraCount, 1))).transpose() + tranShkVals_temp = (np.tile(self.Pars.tranShkVals, (aXtraCount, 1))).transpose() + ShkPrbs_temp = (np.tile(self.ShkPrbs, (aXtraCount, 1))).transpose() + + # Make a 1D array of the interest factor at each asset gridpoint + Rfree_vec = self.bilt.Rsave * np.ones(aXtraCount) + if KinkBool: + self.i_kink = ( + np.sum(aNrm <= 0) - 1 + ) # Save the index of the kink point as an attribute + Rfree_vec[0: self.i_kink] = self.bilt.Rboro +# Rfree = Rfree_vec + Rfree_temp = np.tile(Rfree_vec, (ShkCount, 1)) + + # Make an array of market resources that we could have next period, + # considering the grid of assets and the income shocks that could occur + mNrmNext = ( + Rfree_temp / (self.PermGroFac * permShkVals_temp) * aNrm_temp + + tranShkVals_temp + ) + + # Recalculate the minimum MPC and human wealth using the interest factor on saving. + # This overwrites values from set_and_update_values, which were based on Rboro instead. + if KinkBool: + RPFTop = ( + (self.bilt.Rsave * self.DiscLiv) ** (1.0 / self.CRRA) + ) / self.bilt.Rsave + self.MPCmin = 1.0 / (1.0 + RPFTop / self.solution_current.bilt.MPCmin) + self.hNrm = ( + self.PermGroFac + / self.bilt.Rsave + * ( + 𝔼_dot( + self.ShkPrbs, self.Pars.tranShkVals * self.Pars.permShkVals + ) + + self.solution_current.bilt.hNrm + ) + ) + + # Store some of the constructed arrays for later use and return the assets grid + self.permShkVals_temp = permShkVals_temp + self.ShkPrbs_temp = ShkPrbs_temp + self.mNrmNext = mNrmNext + self.aNrm = aNrm + return aNrm diff --git a/HARK/ConsumptionSaving/ConsRiskyContribModel.py b/HARK/ConsumptionSaving/ConsRiskyContribModel.py index a0c4fe81b..25f73f005 100644 --- a/HARK/ConsumptionSaving/ConsRiskyContribModel.py +++ b/HARK/ConsumptionSaving/ConsRiskyContribModel.py @@ -1907,3 +1907,4 @@ def solveRiskyContrib( init_risky_contrib_lifecycle = init_lifecycle.copy() init_risky_contrib_lifecycle.update(risky_asset_parms) init_risky_contrib_lifecycle.update(risky_contrib_params) + diff --git a/HARK/ConsumptionSaving/dolo_models/IndShockConsumerType.yaml b/HARK/ConsumptionSaving/dolo_models/IndShockConsumerType.yaml new file mode 100644 index 000000000..d402999cc --- /dev/null +++ b/HARK/ConsumptionSaving/dolo_models/IndShockConsumerType.yaml @@ -0,0 +1,47 @@ +name: BufferStockTheory + +symbols: + exogenous: [lψ, lθ] + states: [m] + controls: [c] + parameters: [β, ρ, σ_lψ, σ_lθ, R, Γ] + +definitions: + Thetaθ[t] = exp(lθ[t]) + +equations: + +# The definition of θ[t] above was constructed so that it could +# be used instead of exp(lθ[t]) here. For some reason that does +# not work + transition: | + m[t] = exp(lθ[t]) + (m[t-1]-c[t-1])*(R/(Γ*exp(lψ[t]))) + + arbitrage: | + (R*β*((c[t+1]*exp(lψ[t+1])*Γ)/c[t])^(-ρ)-1 ) ⟂ 0.0 <= c[t] <= m[t] + +calibration: + + β: 0.96 + Γ: 1.03 + ρ: 2.0 + R: 1.04 + σ_lψ: 0.1 + σ_lθ: 0.1 + lψ: -(σ_lψ^2)/2 + lθ: -(σ_lθ^2)/2 + m: 1.0 + max_m: 500 + c: 0.9*m + θ: 1.0 + +domain: + m: [0.0, max_m] + +exogenous: !Normal + Σ: [[σ_lψ^2, 0] + ,[0, σ_lθ^2]] + +options: + grid: !Cartesian + orders: [1000] diff --git a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py index 6a01a4256..101d76548 100644 --- a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py +++ b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py @@ -576,4 +576,4 @@ def transition(self): AHist.append(np.array(listA)) JACA = (AHist[0]-A_dx0)/(dx) - self.assertAlmostEqual(JACA[175], 6.441930322509393e-06) \ No newline at end of file + self.assertAlmostEqual(JACA[175], 6.441930322509393e-06) diff --git a/HARK/core.py b/HARK/core.py index a01f00d6a..9146dec2e 100644 --- a/HARK/core.py +++ b/HARK/core.py @@ -16,6 +16,101 @@ from .parallel import multi_thread_commands, multi_thread_commands_fake from warnings import warn +# pyflakes kept flagging _log commands in core.py as undefined unless the log stuff +# was here at the beginning (and not just in __init__.py + +import logging + +logging.basicConfig(format="%(message)s") + +_log = logging.getLogger("HARK") + +_log.setLevel(logging.ERROR) + + +def disable_logging(): + _log.disabled = True + + +def enable_logging(): + _log.disabled = False + + +def warnings(): + _log.setLevel(logging.WARNING) + + +def quiet(): + _log.setLevel(logging.ERROR) + + +def verbose(): + _log.setLevel(logging.INFO) + + +def set_verbosity_level(level): + _log.setLevel(level) + + +def core_check_condition(name, test, messages, messaging_level, verbose_messages, fact, stage_solution, quietly=False): + """ + Checks whether parameter values of a model satisfy a condition + + Parameters + ---------- + name : string + Name for the condition. + + test : function(self -> boolean) + A function (of self) which tests the condition + + verbose : Boolean + If False, print minimal information about the condition and exit + If True, print more detailed information and a reference + + messages : dict{boolean : string} + A dictionary with boolean keys containing values + for messages to print if the condition is + true or false. + + messaging_level : int + Controls verbosity of messages. logging.DEBUG is most verbose, + logging.INFO is less verbose, logging.WARNING speaks up only if the + model might have problems, logging.CRITICAL indicates it is degenerate. + + verbose_messages : dict{boolean : string} + (Optional) A dictionary with boolean keys containing supplemental + messages to print if the condition is + true or false if messaging_level is logging.DEBUG + + fact : string + Name of the fact (for recording the results) + + stage_solution : solution for a stage of the problem containing a condition + to be tested. Must have dict 'conditions' [name] + + quiet : boolean + If True, construct the conditions but print nothing + """ + + soln = stage_solution + + TF = test(soln) + soln.Bilt.conditions[name] = TF # Set whether condition was true or false + # Messages of severity less than minimum intensity are not displayed + minimum_intensity = messaging_level # Do not show messages less important + _log.setLevel(minimum_intensity) # Uses python logger setLevel + # Store the messages for later retrieval if desired + soln.Bilt.conditions[fact] = ( + messages[soln.Bilt.conditions[name]] + + verbose_messages[soln.Bilt.conditions[name]]).format(soln.Bilt) + _log.info(messages[soln.Bilt.conditions[name]].format(soln.Bilt)) + # Debug log gets the verbose info + _log.debug( + verbose_messages[soln.Bilt.conditions[name]].format(soln.Bilt)) + + return TF + def distance_metric(thing_a, thing_b): """ @@ -66,20 +161,20 @@ def distance_metric(thing_a, thing_b): # If keys don't match, print a warning. if list(sorted_a.keys()) != list(sorted_b.keys()): warn( - 'Dictionaries with keys that do not match are being ' + + 'Dictionaries with keys that do not match are being ' + 'compared.' ) distance = distance_metric(list(sorted_a.values()), - list(sorted_b.values())) + list(sorted_b.values())) else: # If they have different lengths, log a warning and return the # difference in lengths. warn( - 'Objects of different lengths are being compared. ' + + 'Objects of different lengths are being compared. ' + 'Returning difference in lengths.' - ) + ) distance = float(abs(len_a - len_b)) # If both inputs are numbers, return their difference @@ -133,7 +228,12 @@ def distance(self, other): The distance between this object and another, using the "universal distance" metric. """ + if self.distance_criteria == []: + _log.critical( + "distance_criteria not set so distance between "+str(self)+" and " + str(other) + " cannot be computed.") + distance_list = [0.0] + for attr_name in self.distance_criteria: try: obj_a = getattr(self, attr_name) @@ -143,12 +243,18 @@ def distance(self, other): distance_list.append( 1000.0 ) # if either object lacks attribute, they are not the same + self.distance_last = max(distance_list) # Store it for later inspection return max(distance_list) + class Model(object): """ A class with special handling of parameters assignment. + + Creates a "self.parameters" attribute that contains all + keywords explicitly passed to the object. """ + def assign_parameters(self, **kwds): """ Assign an arbitrary number of attributes to this agent. @@ -167,7 +273,16 @@ def assign_parameters(self, **kwds): for key in kwds: setattr(self, key, kwds[key]) + assign_parameters_model = assign_parameters + def get_parameter(self, name): + # CDC 20210527: A global search across all HARK, REMARKs, + # and DemARKs does not find any instance of this being used. + # We ought either to: + # 1. use it pervasively + # * in which case there should be a companion set_parameter + # or + # 2. Eliminate it """ Returns a parameter of this model @@ -183,6 +298,8 @@ def get_parameter(self, name): """ return self.parameters[name] + get_parameter_model = get_parameter + def __eq__(self, other): if isinstance(other, type(self)): return self.parameters == other.parameters @@ -215,25 +332,26 @@ def __repr__(self): class AgentType(Model): """ A superclass for economic agents in the HARK framework. Each model should - specify its own subclass of AgentType, inheriting its methods and overwriting + specify its own subclass of AgentType, inheriting methods and overwriting as necessary. Critically, every subclass of AgentType should define class- specific static values of the attributes time_vary and time_inv as lists of strings. Each element of time_vary is the name of a field in AgentSubType - that varies over time in the model. Each element of time_inv is the name of + that varies over time in the model. Each element of time_inv is the name of a field in AgentSubType that is constant over time in the model. Parameters ---------- solution_terminal : Solution - A representation of the solution to the terminal period problem of + A representation of the solution to the terminal period/stage of this AgentType instance, or an initial guess of the solution if this is an infinite horizon problem. cycles : int - The number of times the sequence of periods is experienced by this - AgentType in their "lifetime". cycles=1 corresponds to a lifecycle - model, with a certain sequence of one period problems experienced + The number of times the sequence of periods/stages is experienced by + this AgentType in their lifetime. cycles=1 corresponds to a lifecycle + model, with a given sequence of one period/stage problems experienced once before terminating. cycles=0 corresponds to an infinite horizon - model, with a sequence of one period problems repeating indefinitely. + model, with a sequence of one period/stage problems repeating + indefinitely. pseudo_terminal : boolean Indicates whether solution_terminal isn't actually part of the solution to the problem (as a known solution to the terminal period @@ -241,8 +359,8 @@ class AgentType(Model): When True, solution_terminal is not included in the solution; when false, solution_terminal is the last element of the solution. tolerance : float - Maximum acceptable "distance" between successive solutions to the - one period problem in an infinite horizon (cycles=0) model in order + Maximum acceptable "distance" between successive solutions to the one + period/stage problem in an infinite horizon (cycles=0) model in order for the solution to be considered as having "converged". Inoperative when cycles>0. seed : int @@ -255,6 +373,7 @@ class AgentType(Model): state_vars : list of string The string labels for this AgentType's model state variables. + """ state_vars = [] @@ -267,7 +386,7 @@ def __init__( seed=0, **kwds ): - super().__init__() + Model.__init__(self) if solution_terminal is None: solution_terminal = NullFunc() @@ -278,15 +397,21 @@ def __init__( self.tolerance = tolerance # NOQA self.seed = seed # NOQA self.track_vars = [] # NOQA - self.state_now = {sv : None for sv in self.state_vars} + self.state_now = {sv: None for sv in self.state_vars} self.state_prev = self.state_now.copy() self.controls = {} self.shocks = {} self.read_shocks = False # NOQA self.shock_history = {} self.history = {} + self.assign_parameters(**kwds) # NOQA self.reset_rng() # NOQA + self.prmtv_par = dict() # 'primitives' define true model + # 'approximation' pars + self.aprox_par = {'tolerance': self.tolerance, 'seed': self.seed} + # if lim exists, sol approaches truth as all aprox_par -> lim + self.aprox_lim = {'tolerance': 0.0, 'seed': None} def add_to_time_vary(self, *params): """ @@ -329,7 +454,7 @@ def del_from_time_vary(self, *params): Parameters ---------- params : string - Any number of strings naming attributes to be removed from time_vary + Any number of strings naming attributes to remove from time_vary Returns ------- @@ -378,31 +503,37 @@ def unpack(self, parameter): self.__dict__[parameter].append(solution_t.__dict__[parameter]) self.add_to_time_vary(parameter) - def solve(self, verbose=False): + # At present, the only solution method is EGM + # The next method to add is value function iteration + def solve(self, messaging_level=logging.DEBUG, quietly=False, **kwds): # AgentType """ - Solve the model for this instance of an agent type by backward induction. - Loops through the sequence of one period problems, passing the solution - from period t+1 to the problem for period t. + Solve the model for this instance of an agent by backward induction. + Loops through sequence of one period/stage problems, passing solution + from next period/stage to the problem for current period/stage. Parameters ---------- - verbose : boolean - If True, solution progress is printed to screen. + messaging_level : logging level + From logging.DEBUG to logging.CRITICAL + + quietly : boolean + If True, suppress output Returns ------- none """ - + self.messaging_level = messaging_level + self.quietly = quietly # Ignore floating point "errors". Numpy calls it "errors", but really it's excep- # tions with well-defined answers such as 1.0/0.0 that is np.inf, -1.0/0.0 that is # -np.inf, np.inf/np.inf is np.nan and so on. with np.errstate( divide="ignore", over="ignore", under="ignore", invalid="ignore" ): - self.pre_solve() # Do pre-solution stuff + self.pre_solve() # Stuff to do before beginning to solve the model self.solution = solve_agent( - self, verbose + self, messaging_level, quietly, **kwds ) # Solve the model by backward induction self.post_solve() # Do post-solution stuff @@ -420,6 +551,8 @@ def reset_rng(self): """ self.RNG = np.random.RandomState(self.seed) + reset_rng_mcrlo = mcrlo_reset_rng = reset_rng + def check_elements_of_time_vary_are_lists(self): """ A method to check that elements of time_vary are lists. @@ -431,14 +564,12 @@ def check_elements_of_time_vary_are_lists(self): def check_restrictions(self): """ - A method to check that various restrictions are met for the model class. + Check that various restrictions are met for the model class. """ return - def pre_solve(self): - """ - A method that is run immediately before the model is solved, to check inputs or to prepare - the terminal solution, perhaps. + def pre_solve(self, quietly): + """Check agent immediately before beginning embarking on solution. Parameters ---------- @@ -452,10 +583,12 @@ def pre_solve(self): self.check_elements_of_time_vary_are_lists() return None + pre_solve_agent = pre_solve + def post_solve(self): """ - A method that is run immediately after the model is solved, to finalize - the solution in some way. Does nothing here. + An agent that is run immediately after the model is solved, to finalize + the solution in some way. Parameters ---------- @@ -467,6 +600,8 @@ def post_solve(self): """ return None + post_solve_agent = post_solve + def initialize_sim(self): """ Prepares this AgentType for a new simulation. Resets the internal random number generator, @@ -501,21 +636,23 @@ def initialize_sim(self): if self.state_now[var] is None: self.state_now[var] = copy(blank_array) - #elif self.state_prev[var] is None: + # elif self.state_prev[var] is None: # self.state_prev[var] = copy(blank_array) self.t_age = np.zeros( self.AgentCount, dtype=int - ) # Number of periods since agent entry + ) # Number of periods/stages since agent entry self.t_cycle = np.zeros( self.AgentCount, dtype=int - ) # Which cycle period each agent is on + ) # Which cycle period/stage each agent is on self.sim_birth(all_agents) self.clear_history() return None - def sim_one_period(self): + mcrlo_initialize_sim = initialize_sim_mcrlo = initialize_sim + + def sim_one_period(self): # -> mcrlo_sim_one_prd """ - Simulates one period for this type. Calls the methods get_mortality(), get_shocks() or + Simulates one period/stage for this type. Calls the methods get_mortality(), get_shocks() or read_shocks, get_states(), get_controls(), and get_poststates(). These should be defined for AgentType subclasses, except get_mortality (define its components sim_death and sim_birth instead) and read_shocks. @@ -535,7 +672,7 @@ def sim_one_period(self): ) # Mortality adjusts the agent population - self.get_mortality() # Replace some agents with "newborns" + self.get_mortality() # -> mcrlo_get_mortality Replace some with newborns # state_{t-1} for var in self.state_now: @@ -562,7 +699,9 @@ def sim_one_period(self): self.t_cycle == self.T_cycle ] = 0 # Resetting to zero for those who have reached the end - def make_shock_history(self): + mcrlo_sim_one_stge = sim_one_period + + def make_shock_history(self): # -> make_shock_hst """ Makes a pre-specified history of shocks for the simulation. Shock variables should be named in self.shock_vars, a list of strings that is subclass-specific. This method runs a subset @@ -590,7 +729,6 @@ def make_shock_history(self): self.shock_history["who_dies"] = np.zeros( (self.T_sim, self.AgentCount), dtype=bool ) - # Make and store the history of shocks for each period for t in range(self.T_sim): self.get_mortality() @@ -609,7 +747,9 @@ def make_shock_history(self): # Flag that shocks can be read rather than simulated self.read_shocks = True - def get_mortality(self): + make_shock_history_mcrlo = mcrlo_make_shocks_history = make_shock_history + + def get_mortality(self): # -> mcrlo_get_mrtlty """ Simulates mortality or agent turnover according to some model-specific rules named sim_death and sim_birth (methods of an AgentType subclass). sim_death takes no arguments and returns @@ -633,7 +773,9 @@ def get_mortality(self): self.who_dies = who_dies return None - def sim_death(self): + mcrlo_get_mortality = get_mortality_mcrlo = get_mortality + + def sim_death(self): # -> mcrlo_sim_deth """ Determines which agents in the current population "die" or should be replaced. Takes no inputs, returns a Boolean array of size self.AgentCount, which has True for agents who die @@ -652,7 +794,7 @@ def sim_death(self): who_dies = np.zeros(self.AgentCount, dtype=bool) return who_dies - def sim_birth(self, which_agents): + def sim_birth(self, which_agents): # -> mcrlo_sim_brth """ Makes new agents for the simulation. Takes a boolean array as an input, indicating which agent indices are to be "born". Does nothing by default, must be overwritten by a subclass. @@ -669,10 +811,12 @@ def sim_birth(self, which_agents): print("AgentType subclass must define method sim_birth!") return None - def get_shocks(self): + def get_shocks(self): # -> mcrlo_get_shks """ - Gets values of shock variables for the current period. Does nothing by default, but can - be overwritten by subclasses of AgentType. + Get values of shock variables for the current stage/period. + + Does nothing by default, but can be overwritten by subclasses of + AgentType. Parameters ---------- @@ -684,9 +828,11 @@ def get_shocks(self): """ return None - def read_shocks_from_history(self): + mcrlo_get_shocks = get_shocks_mcrlo = get_shocks + + def read_shocks_from_history(self): # -> mcrlo_hstry_shks_read """ - Reads values of shock variables for the current period from history arrays. + Reads values of shock variables for the current period/stage from history arrays. For each variable X named in self.shock_vars, this attribute of self is set to self.history[X][self.t_sim,:]. @@ -705,7 +851,10 @@ def read_shocks_from_history(self): for var_name in self.shock_vars: self.shocks[var_name] = self.shock_history[var_name][self.t_sim, :] - def get_states(self): + mcrlo_read_shocks_from_history = read_shocks_from_history_mcrlo = \ + read_shocks_from_history + + def get_states(self): # -> mcrlo_ get_stts """ Gets values of state variables for the current period. By default, calls transition function and assigns values @@ -728,13 +877,15 @@ def get_states(self): return None - def transition(self): + mcrlo_get_states = get_states_mcrlo = get_states + + def transition(self): # -> mcrlo_trnstn = inherit everything """ Parameters ---------- None - + [Eventually, to match dolo spec: exogenous_prev, endogenous_prev, controls, exogenous, parameters] @@ -747,9 +898,11 @@ def transition(self): return () + transition_mcrlo = mcrlo_transition = transition + def get_controls(self): """ - Gets values of control variables for the current period, probably by using current states. + Gets values of control variables for the current period/stage, probably by using current states. Does nothing by default, but can be overwritten by subclasses of AgentType. Parameters @@ -762,11 +915,13 @@ def get_controls(self): """ return None + get_controls_mcrlo = mcrlo_get_controls = get_controls + def get_poststates(self): """ - Gets values of post-decision state variables for the current period, + Gets values of post-decision state variables for the current period/stage, probably by current - states and controls and maybe market-level events or shock variables. + states and controls and maybe market-level events or shock variables. Does nothing by default, but can be overwritten by subclasses of AgentType. @@ -784,9 +939,11 @@ def get_poststates(self): return None - def simulate(self, sim_periods=None): + get_poststates_mcrlo = mcrlo_get_poststates = get_poststates + + def simulate(self, sim_periods=None): # -> sim_stage=None """ - Simulates this agent type for a given number of periods. Defaults to + Simulates this agent type for a given number of periods/stages. Defaults to self.T_sim if no input. Records histories of attributes named in self.track_vars in self.history[varname]. @@ -847,6 +1004,8 @@ def simulate(self, sim_periods=None): return self.history + simulate_mcrlo = mcrlo_simulate = simulate + def clear_history(self): """ Clears the histories of the attributes named in self.track_vars. @@ -862,15 +1021,15 @@ def clear_history(self): for var_name in self.track_vars: self.history[var_name] = np.empty((self.T_sim, self.AgentCount)) + np.nan + clear_history_mcrlo = mcrlo_clear_history = clear_history + -def solve_agent(agent, verbose): +def solve_agent(agent, messaging_level, quietly=False, **kwds): """ - Solve the dynamic model for one agent type - using backwards induction. - This function iterates on "cycles" - of an agent's model either a given number of times - or until solution convergence - if an infinite horizon model is used + Solve the dynamic model for one agent type using backwards induction. + + Iterates on "cycles" of an agent's model either a given number + of times or until solution convergence if an infinite horizon model is used (with agent.cycles = 0). Parameters @@ -878,191 +1037,287 @@ def solve_agent(agent, verbose): agent : AgentType The microeconomic AgentType whose dynamic problem is to be solved. - verbose : boolean - If True, solution progress is printed to screen (when cycles != 1). + messaging_level : logging level + Controls amount of output + quietly : boolean + If True, all printed output is suppressed. Returns ------- solution : [Solution] - A list of solutions to the one period problems that the agent will - encounter in his "lifetime". + A list of solutions to one period/stage problems that the agent will + encounter in a "lifetime". """ # Check to see whether this is an (in)finite horizon problem cycles_left = agent.cycles # NOQA infinite_horizon = cycles_left == 0 # NOQA - # Initialize the solution, which includes the terminal solution if it's not a pseudo-terminal period - solution = [] - if not agent.pseudo_terminal: - solution.insert(0, deepcopy(agent.solution_terminal)) + # If we are resuming a solution process, a solution might already exist + if not hasattr(agent, 'solution'): # Not resuming, create anew + # Initialize the solution, which includes the terminal solution + solution = [] + pseudo = (agent.pseudo_terminal is True) + if not pseudo: # Then it's a real solution; should be part of the list + solution.insert(0, deepcopy(agent.solution_terminal)) + completed_cycles = 0 # NOQA + max_cycles = 5000 # NOQA - escape clause, stop eventually + solution_next = agent.solution_terminal # NOQA + solution_next.cFunc = solution_next.Bilt.cFunc # Should be generic dr + else: # We are resuming solution of a model that has already converged + solution = agent.solution + solution_next = agent.solution[0] + if hasattr(solution_next, 'completed_cycles'): # keep counting + completed_cycles = solution_next.completed_cycles + else: # start counting + completed_cycles = solution_next.completed_cycles = 0 + if hasattr(agent, 'max_cycles'): # keep max + max_cycles = agent.max_cycles + else: + max_cycles = 5000 # stop eventually + + if hasattr(solution_next, 'stge_kind'): + # User who wants to resume, say to solve to tighter tolerance, needs + # of course to change the tolerance parameter but must also change the + # stge_kind from 'finished' to 'iterator' + if 'iter_status' in solution_next.stge_kind: + if solution_next.stge_kind['iter_status'] == 'finished': + _log.info('The model has already been solved.') +# print('The existing solution solves the problem') + return agent.solution # Initialize the process, then loop over cycles - solution_last = agent.solution_terminal # NOQA go = True # NOQA - completed_cycles = 0 # NOQA - max_cycles = 5000 # NOQA - escape clause - if verbose: + + if messaging_level < logging.INFO: # INFO or DEBUG or NOTSET t_last = time() - while go: - # Solve a cycle of the model, recording it if horizon is finite - solution_cycle = solve_one_cycle(agent, solution_last) + while go: # Solve a cycle of the model + solution_cycle = solve_one_cycle(agent, solution_next) + solution_now = solution_cycle[0] if not infinite_horizon: + # If finite horizon model, add cycle to the growing list solution = solution_cycle + solution - - # Check for termination: identical solutions across - # cycle iterations or run out of cycles - solution_now = solution_cycle[0] - if infinite_horizon: - if completed_cycles > 0: - solution_distance = solution_now.distance(solution_last) - agent.solution_distance = ( - solution_distance # Add these attributes so users can - ) - agent.completed_cycles = ( - completed_cycles # query them to see if solution is ready - ) - go = ( - solution_distance > agent.tolerance - and completed_cycles < max_cycles - ) - else: # Assume solution does not converge after only one cycle - solution_distance = 100.0 - go = True - else: cycles_left += -1 go = cycles_left > 0 - - # Update the "last period solution" - solution_last = solution_now + # Don't count replacement of terminal_partial as a cycle; see below + if solution_next.Bilt.stge_kind['iter_status'] == 'terminal_partial': + cycles_left += 1 + completed_cycles += -1 + go = True + else: # infinite horizon + solution = solution_cycle + solution_now = solution_cycle[0] # element 0 most recently solved + solution_now.solution_distance = \ + solution_distance = solution_now.distance(solution_next) + go = ( + solution_distance > agent.tolerance + and completed_cycles < max_cycles + ) + # To permit ".solve()" method on the agent to resume solution after + # reaching convergence under some initial tolerance, user must + # * Change something about the problem (e.g., tolerance) + # * Change solution[0] stge_kind['iter_status'] to 'iterator' + # * Restart the solution process with [instance].solve() + # TODO: this has been tested only for PerfForesightConsumerType + # and IndShockConsumerType. We should test whether agent is one of + # those before allowing resume + + if hasattr(agent, 'solve_resume') and (agent.solve_resume is True): # if resumption requested, + go = True # solve one period/stage for sure, then keep going + agent.solve_resume = False # go until stop criteria satisfied + if not go: # Finished solving + # All models should incorporate 'stge_kind', but some have not + # Handle cases where that has not yet been implemented: + if not hasattr(solution_now.Bilt, 'stge_kind'): + solution_now.Bilt.stge_kind = {'iter_status': 'iterator'} + if solution_next.Bilt.stge_kind['iter_status'] == 'terminal_partial': + completed_cycles += -1 # replacement is not a cycle + else: # Replacing terminal_partial is not a "real" cycle + # This if/else prevents a stage derived from one marked as + # 'terminal_partial' from being labeled as + # 'finished' even though its distance will be zero + # from the 'terminal_partial' stage. Lets us use + # our machinery to enrich the terminal_partial stage + solution_now.Bilt.stge_kind['iter_status'] = 'finished' + # Record the tolerance that was satisfied + solution_now.stge_kind['tolerance'] = agent.tolerance + # Update the "last period/stage solution" for next iteration completed_cycles += 1 - - # Display progress if requested - if verbose: - t_now = time() - if infinite_horizon: - print( - "Finished cycle #" - + str(completed_cycles) - + " in " - + str(t_now - t_last) - + " seconds, solution distance = " - + str(solution_distance) - ) - else: - print( - "Finished cycle #" - + str(completed_cycles) - + " of " - + str(agent.cycles) - + " in " - + str(t_now - t_last) - + " seconds." - ) - t_last = t_now - - # Record the last cycle if horizon is infinite (solution is still empty!) - if infinite_horizon: - solution = ( - solution_cycle # PseudoTerminal=False impossible for infinite horizon - ) + solution_now.completed_cycles = deepcopy(completed_cycles) + solution_next = solution_now + + if not quietly: + if messaging_level >= logging.DEBUG: + print('.', end='') # visually indicate something is happening + else: # Display progress + t_now = time() + if infinite_horizon: + print( + "Finished cycle # " + + str(completed_cycles).zfill(6) + + " in " + + str("{:9.6f}".format(t_now - t_last)) + + " seconds, solution distance = " + + str("{:.3e}".format(solution_distance)) + ) + else: + print( + "Finished cycle # " + + str(completed_cycles).zfill(len(str(agent.cycles))) + + " of " + + str(agent.cycles) + + " in " + + str("{:9.6f}".format(t_now - t_last)) + + " seconds." + ) + t_last = t_now return solution -def solve_one_cycle(agent, solution_last): +def solve_one_cycle(agent, solution_next): """ - Solve one "cycle" of the dynamic model for one agent type. This function - iterates over the periods within an agent's cycle, updating the time-varying - parameters and passing them to the single period solver(s). + Solve one "cycle" of the dynamic model for one agent type. + + This function iterates over the stages within an agent's cycle, updating + the stage-varying parameters and passing them to the single-stage + solver(s). Parameters ---------- agent : AgentType - The microeconomic AgentType whose dynamic problem is to be solved. - solution_last : Solution - A representation of the solution of the period that comes after the - end of the sequence of one period problems. This might be the term- - inal period solution, a "pseudo terminal" solution, or simply the - solution to the earliest period from the succeeding cycle. + An instance of an AgentType whose dynamic problem is to be solved. + + solution_next : Solution + A representation of the solution of the period/stage that comes after the + end of the sequence of one period/stage problems. This might be the term- + inal period/stage solution, a "pseudo terminal" solution, or simply the + solution to the earliest period/stage from the succeeding cycle. Returns ------- - solution_cycle : [Solution] - A list of one period solutions for one "cycle" of the AgentType's - microeconomic model. + full_cycle : [Solution] + An ordered list of solutions ('stages') for a full "cycle" + of the AgentType's problem, constructed by backward + induction. After construction, each solution is prepended to the + existing collection of solutions, with the result that in the completed + `full_cycle` object element 0 is the solution to the problem at the + beginning of the cycle, and full_cycle[-1] is the solution to the last + problem completed before moving to the next cycle. """ - # Calculate number of periods per cycle, defaults to 1 if all variables are time invariant + # Calculate number of stages per cycle; + # defaults to 1 if all variables are stage invariant if len(agent.time_vary) > 0: - # name = agent.time_vary[0] - # T = len(eval('agent.' + name)) - T = len(agent.__dict__[agent.time_vary[0]]) + num_stges = len(agent.__dict__[agent.time_vary[0]]) else: - T = 1 - - solve_dict = {parameter: agent.__dict__[parameter] for parameter in agent.time_inv} - solve_dict.update({parameter: None for parameter in agent.time_vary}) - - # Initialize the solution for this cycle, then iterate on periods - solution_cycle = [] - solution_next = solution_last - for t in range(T): - # Update which single period solver to use (if it depends on time) - if hasattr(agent.solve_one_period, "__getitem__"): - solve_one_period = agent.solve_one_period[T - 1 - t] + num_stges = 1 + + # Add to solve_dict all the parameters in time_inv and time_vary + solve_dict = {parameter: agent.__dict__[parameter] + for parameter in agent.time_inv} + solve_dict.update({parameter: None + for parameter in agent.time_vary}) + + # Initialize the solution for this cycle, then iterate through stages + full_cycle = [] + + for this_stge in range(num_stges): # for quarterly model, num_stges = 4 qtrs + # Update which single period/stage solver to use (if depends on stage) + if hasattr(agent.solve_one_period, "__getitem__"): # ->solve_this_stge + solve_one_period = agent.solve_one_period[num_stges - 1 - this_stge] else: solve_one_period = agent.solve_one_period + # Code below has been made standalone in get_solve_one_period_args + # which returns the solve_dict without the "solution_next" object + + # Construct arguments demanded by solve_one_period if hasattr(solve_one_period, "solver_args"): these_args = solve_one_period.solver_args else: these_args = get_arg_names(solve_one_period) - # Update time-varying single period inputs + # Update any stage-varying single period/stage inputs + # This obtains the value for the current step by indexing + # into the attribute's list at [num_stges - 1 - this_stge] for name in agent.time_vary: if name in these_args: - # solve_dict[name] = eval('agent.' + name + '[t]') - solve_dict[name] = agent.__dict__[name][T - 1 - t] - solve_dict["solution_next"] = solution_next + solve_dict[name] = agent.__dict__[name][num_stges - 1 - this_stge] + + solve_dict['solution_next'] = solution_next # solution_stage_next + # solution_next is added here because it is a required argument but is + # included in neither time_vary nor time_inv. Seems like maybe it could + # (and should) be included in one of those ... # Make a temporary dictionary for this period temp_dict = {name: solve_dict[name] for name in these_args} - # Solve one period, add it to the solution, and move to the next period - solution_t = solve_one_period(**temp_dict) - solution_cycle.insert(0, solution_t) - solution_next = solution_t + # Solve one stage, add it to the collection, and designate + # the just-solved solution as being in the future for the + # purposes of any remaining iteration(s) + + solution_current = solve_one_period(**temp_dict) # -> solve_this_stage + full_cycle.insert(0, solution_current) + solution_next = solution_current + + # Return the list of per-period/stage solutions + return full_cycle + + +# def get_solve_one_period_args(agent, solve_one_period, stge_which): +# # Add to dict all the parameters in time_inv and time_vary +# solve_dict = \ +# {parameter: agent.__dict__[parameter] for parameter in agent.time_inv} +# solve_dict.update({parameter: None for parameter in agent.time_vary}) + +# # The code below allows stage-varying arguments by constructing the +# # arguments demanded by the given solve_one_period +# if hasattr(solve_one_period, "solver_args"): +# these_args = solve_one_period.solver_args +# else: +# these_args = get_arg_names(solve_one_period) - # Return the list of per-period solutions - return solution_cycle +# # Update stage-varying single period/stage inputs +# # This obtains the value for the current step by indexing +# # into the attribute's list at [num_stges - 1 - stge] +# for name in agent.time_vary: +# if name in these_args: +# solve_dict[name] = agent.__dict__[name][stge_which] +# return solve_dict -def make_one_period_oo_solver(solver_class): + +def make_one_period_oo_solver(solver_class, **kwds): + # Allow for future methods by making solveMethod an option """ - Returns a function that solves a single period consumption-saving - problem. + Returns a function that solves a single period/stage problem. Parameters ---------- solver_class : Solver A class of Solver to be used. + + Returns ------- solver_function : function - A function for solving one period of a problem. + A function for solving one period/stage of a problem. """ def one_period_solver(**kwds): - solver = solver_class(**kwds) + solver = solver_class(**kwds) # defined externally - # not ideal; better if this is defined in all Solver classes if hasattr(solver, "prepare_to_solve"): - solver.prepare_to_solve() + # Steps, if any, to prep for sol of stge + solver.prepare_to_solve() # TODO: rename to prepare_to_solve_stge - solution_now = solver.solve() - return solution_now + solution_current = solver.solve() # TODO: rename to solve_stge + return solution_current one_period_solver.solver_class = solver_class - # This can be revisited once it is possible to export parameters + one_period_solver.solver_args = get_arg_names(solver_class.__init__)[1:] - return one_period_solver + return one_period_solver # TODO: rename to one_stge_solver someday + + +make_one_stage_oo_solver = make_one_period_oo_solver # ======================================================================== diff --git a/HARK/distribution.py b/HARK/distribution.py index 1e3668323..97a1f3cb8 100644 --- a/HARK/distribution.py +++ b/HARK/distribution.py @@ -726,7 +726,7 @@ def draw(self, N): return draws[0] if len(draws) == 1 else draws -class DiscreteDistribution(Distribution): +class DiscreteDistributionOld(Distribution): """ A representation of a discrete probability distribution. @@ -838,6 +838,36 @@ def draw(self, N, X=None, exact_match=False): return draws +# CDC 20210621: We should not use pmf for the point masses of the realizations, because it +# is not a probability mass 'function.' Scipy.discrete_rv, sympy, and Mathematica all +# return pmf (or pdf) as a function. They have different syntaxes for retrieving the +# vector of point masses; here it is called the pmv (probability mass vector) + + +class DiscreteDistribution(DiscreteDistributionOld): + __doc__ = DiscreteDistributionOld.__doc__ + __doc__ += """ + XYZ : np.array + Restructure the dimensions of the np.array so that successive + columns in XYZ correspond to the vectors of values of each + discrete random variables across the broadcasted combinations. + Thus, [instance].XYZ[0] will return the vector of discrete + realizations of the first variable, [instance].XYZ[-1] will + get the last RV, etc. + pmv : The vector of point masses of the broadcasted collection + of random variables +""" + + def __init__(self, pmf, X, seed=0): # Get the old definition + super().__init__(pmf, X, seed) # execute the old def + XYZ = np.column_stack(X) # stack actually unstacks them + if self.dim() == 1: # numpy 1 dimensional arrays want to be + XYZ = XYZ.T # the wrong shape + self.XYZ = XYZ # [ N dimensional matrix ] + # The pmf should be a function, not a vector (as now) + # TODO: Replace invocations of pmf with pmv + self.pmv = pmf + def approx_lognormal_gauss_hermite(N, mu=0.0, sigma=1.0, seed=0): d = Normal(mu, sigma).approx(N) return DiscreteDistribution(d.pmf, np.exp(d.X), seed=seed) diff --git a/HARK/utilities.py b/HARK/utilities.py index 3f7be22d9..04dd49f01 100644 --- a/HARK/utilities.py +++ b/HARK/utilities.py @@ -132,7 +132,7 @@ def CRRAutility(c, gam): >>> utility(c=c, gam=gamma) -1.0 """ - + if gam == 1: return np.log(c) else: @@ -165,9 +165,9 @@ def uFunc_CRRA_stone_geary(c, CRRA, stone_geary): -1.0 """ if CRRA == 1: - return np.log( stone_geary + c) + return np.log(stone_geary + c) else: - return ( stone_geary + c ) ** (1.0 - CRRA) / (1.0 - CRRA) + return (stone_geary + c) ** (1.0 - CRRA) / (1.0 - CRRA) def uPFunc_CRRA_stone_geary(c, CRRA, stone_geary): """ @@ -189,7 +189,7 @@ def uPFunc_CRRA_stone_geary(c, CRRA, stone_geary): marginal utility """ - return ( stone_geary + c ) ** (- CRRA) + return (stone_geary + c) ** (- CRRA) def uPPFunc_CRRA_stone_geary(c, CRRA, stone_geary): """ @@ -210,7 +210,7 @@ def uPPFunc_CRRA_stone_geary(c, CRRA, stone_geary): marginal utility """ - return (- CRRA)*( stone_geary + c ) ** (- CRRA - 1) + return (- CRRA)*(stone_geary + c) ** (- CRRA - 1) def CRRAutilityP(c, gam): @@ -233,7 +233,7 @@ def CRRAutilityP(c, gam): if gam == 1: return 1/c - + return c ** -gam @@ -254,7 +254,7 @@ def CRRAutilityPP(c, gam): (unnamed) : float Marginal marginal utility """ - + return -gam * c ** (-gam - 1.0) @@ -275,7 +275,7 @@ def CRRAutilityPPP(c, gam): (unnamed) : float Marginal marginal marginal utility """ - + return (gam + 1.0) * gam * c ** (-gam - 2.0) @@ -296,7 +296,7 @@ def CRRAutilityPPPP(c, gam): (unnamed) : float Marginal marginal marginal marginal utility """ - + return -(gam + 2.0) * (gam + 1.0) * gam * c ** (-gam - 3.0) @@ -1016,19 +1016,56 @@ def setup_latex_env_notebook(pf, latexExists): plt.rc("text", usetex=latexExists) if latexExists: latex_preamble = ( - r"\usepackage{amsmath}\usepackage{amsfonts}" - r"\usepackage[T1]{fontenc}" + r"\providecommand{\aFunc}{\mathrm{a}}" + r"\providecommand{\ALev}{{\mathbf{A}}}" + r"\providecommand{\aLev}{{\mathbf{a}}}" + r"\providecommand{\ANrm}{A}" + r"\providecommand{\aNrm}{a}" + r"\providecommand{\bFunc}{\mathrm{b}}" + r"\providecommand{\BLev}{{\mathbf{B}}}" + r"\providecommand{\bLev}{{\mathbf{B}}}" + r"\providecommand{\BNrm}{B}" + r"\providecommand{\bNrm}{b}" + r"\providecommand{\cFunc}{\mathrm{c}}" + r"\providecommand{\CLev}{{\mathbf{C}}}" + r"\providecommand{\cLev}{{\mathbf{c}}}" + r"\providecommand{\CNrm}{C}" + r"\providecommand{\cNrm}{c}" + r"\providecommand{\CRRA}{\rho}" + r"\providecommand{\DiscFac}{\beta}" r"\providecommand{\Ex}{\mathbb{E}}" - r"\providecommand{\StE}{\check}" - r"\providecommand{\Trg}{\hat}" + r"\providecommand{\HLev}{{\mathbf{H}}}" + r"\providecommand{\hLev}{{\mathbf{h}}}" + r"\providecommand{\HNrm}{H}" + r"\providecommand{\hNrm}{h}" + r"\providecommand{\KLev}{{\mathbf{K}}}" + r"\providecommand{\kLev}{{\mathbf{k}}}" + r"\providecommand{\KNrm}{K}" + r"\providecommand{\kNrm}{k}" + r"\providecommand{\MLev}{{\mathbf{M}}}" + r"\providecommand{\mLev}{{\mathbf{m}}}" + r"\providecommand{\MNrm}{M}" + r"\providecommand{\mNrm}{m}" + r"\providecommand{\MPC}{\kappa}" r"\providecommand{\PermGroFac}{\Gamma}" - r"\providecommand{\cLev}{\pmb{\mathrm{c}}}" - r"\providecommand{\mLev}{\pmb{\mathrm{m}}}" + r"\providecommand{\PLev}{{\mathbf{P}}}" + r"\providecommand{\pLev}{{\mathbf{p}}}" r"\providecommand{\Rfree}{\mathsf{R}}" - r"\providecommand{\DiscFac}{\beta}" - r"\providecommand{\CRRA}{\rho}" - r"\providecommand{\MPC}{\kappa}" + r"\providecommand{\Risky}{\mathcal{R}}" + r"\providecommand{\StE}{\check}" + r"\providecommand{\Trg}{\hat}" r"\providecommand{\UnempPrb}{\wp}" + r"\providecommand{\vFunc}{\mathrm{v}}" + r"\providecommand{\VLev}{{\mathbf{V}}}" + r"\providecommand{\vLev}{{\mathbf{v}}}" + r"\providecommand{\VNrm}{V}" + r"\providecommand{\vNrm}{v}" + r"\providecommand{\YLev}{{\mathbf{Y}}}" + r"\providecommand{\yLev}{{\mathbf{y}}}" + r"\providecommand{\YNrm}{Y}" + r"\providecommand{\yNrm}{y}" + r"\usepackage[T1]{fontenc}" + r"\usepackage{amsmath}\usepackage{amsfonts}" ) # Latex expects paths to be separated by /. \ might result in pieces # being interpreted as commands. diff --git a/examples/ConsIndShockModel/IndShockConsumerType.ipynb b/examples/ConsIndShockModel/IndShockConsumerType.ipynb index 127c62fa1..7f0f2795d 100644 --- a/examples/ConsIndShockModel/IndShockConsumerType.ipynb +++ b/examples/ConsIndShockModel/IndShockConsumerType.ipynb @@ -16,18 +16,7 @@ 0 ] }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/sb/projects/econ-ark/HARK/HARK/Calibration/Income/IncomeTools.py:449: UserWarning: Sabelhaus and Song (2010) provide variance profiles for ages 27 to 54. Extrapolating variances using the extreme points.\n", - " warn(\n", - "/home/sb/projects/econ-ark/HARK/HARK/datasets/SCF/WealthIncomeDist/SCFDistTools.py:79: UserWarning: Returning SCF summary statistics for ages (20,25].\n", - " warn(\"Returning SCF summary statistics for ages \" + age_bracket + \".\")\n" - ] - } - ], + "outputs": [], "source": [ "# Initial imports and notebook setup, click arrow to show\n", "from HARK.ConsumptionSaving.ConsIndShockModel import IndShockConsumerType\n", @@ -235,16 +224,16 @@ "name": "stderr", "output_type": "stream", "text": [ - "GPFPF = 0.984539 \n", - "GPFInd = 0.993777 \n", - "GPFAgg = 0.964848 \n", - "Thorn = APF = 0.994384 \n", - "PermGroFacAdj = 1.000611 \n", - "uInvEpShkuInv = 0.990704 \n", - "FVAF = 0.932054 \n", - "WRPF = 0.213705 \n", - "DiscFacGPFIndMax = 0.972061 \n", - "DiscFacGPFAggMax = 1.010600 \n" + "GPFRaw = 0.984539 \n", + "GPFNrm = 0.993777 \n", + "GPFAggLivPrb = 0.964848 \n", + "Thorn = APF = 0.994384 \n", + "PermGroFacAdj = 1.000611 \n", + "uInvEpShkuInv = 0.990704 \n", + "VAF = 0.932054 \n", + "WRPF = 0.213705 \n", + "DiscFacGPFNrmMax = 0.972061 \n", + "DiscFacGPFAggLivPrbMax = 1.010600 \n" ] } ], @@ -274,7 +263,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'cFunc': , 'vFunc': , 'vPfunc': , 'vPPfunc': , 'mNrmMin': 0.0, 'hNrm': 44.991920196607595, 'MPCmin': 0.044536273404377116, 'MPCmax': 1.0, 'mNrmSS': 1.5488165705077026}\n" + "{'cFunc': , 'vFunc': , 'vPfunc': , 'vPPfunc': , 'mNrmMin': 0.0, 'hNrm': 44.991920196607595, 'MPCmin': 0.044536273404377116, 'MPCmax': 1.0, 'mNrmStE': 1.5488165705077033, 'mNrmTrg': 1.5799173260214119}\n" ] } ], @@ -311,7 +300,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD4CAYAAAAXUaZHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAg4UlEQVR4nO3de3hV9Z3v8fc3CeGSK5AQICGE+0VEgQgqClatVeto6zhOqb1YrWhnnGmnPTPTOT1PO+Occ+b0zDOX0zPOILaO2laptrXDUVovowVUUKKA3G/hlhCSECBXct3f80c2IUUgG9hh7cvn9Tx5svfaP9f+suT5sJ7f+q3vMndHREQSS0rQBYiISPQp3EVEEpDCXUQkASncRUQSkMJdRCQBpQX1xXl5eV5SUhLU14uIxKUPPvjgiLvn9zUusHAvKSmhrKwsqK8XEYlLZrY/knF9TsuY2VNmVmNmm/sYd5WZdZrZPZEWKSIi/SOSOfengVvPNcDMUoHvA69FoSYREblIfYa7u68CjvYx7E+AXwA10ShKREQuzkWvljGzQuCzwL9FMHaxmZWZWVltbe3FfrWIiJxFNJZC/jPwl+4e6muguy9191J3L83P7/Nir4iIXKBorJYpBZaZGUAecLuZdbr7r6KwbxERuQAXHe7uPu7kazN7GnhZwS4iEqw+w93MngduAPLMrAL4HjAAwN2X9Gt1IiJJLhRyDtWfYHdNE3tqmyP+7/oMd3dfFOnO3P3+iL9ZRER6dHSF2F/XzO6aplM/tU2U1zbT0t513vsL7A5VEZFkdKK9iz21pwJ8V00ju2ua2F/XQmfo1MOTRucMYsKITP7wqmFMHJHJxPxMJo7IJO/7kX2Pwl1EpB80tXX+boBXN7GrpomDx1o4+QC81BRj7PAhTMzP5FOXjewO8RGZTMjPJGPgxcWzwl1E5CLUt3Swu7aRXeHw3lXTxO7qRg7Vt/aMSU9NYXx+BjOLcvj92UVMKugO8ZLhGaSn9U9zXoW7iEgE6prafie8T76ubWzrGTNoQAoTR2Qyd9wwJhVkMXFEJpNGZFI8bAhpqZe2w7rCXUQkzN2paWwLn4V3B/jJqZWjze094zLSU5lYkMXCyflMGpHJpIJMJo3IojB3MCkpFuCf4BSFu4gkpSNNbew83MiO6kZ2Vjexs7qRndWNNLZ29ozJHpTG5IIsPnVZARNHZDEpPCc+KmcQ4Rs3Y5bCXUQSWv2JDnZVh0M8HOa7qpuo63UmnjtkAJMLsrjzitFMLgiHeEEm+ZkDYz7Ez0bhLiIJoaW9e3XKjsPdZ+A7qpvYebiRww2nLmxmpKcyqSCLm6cVMHlkFlMKspg8Mr5D/GwU7iISV9o6uyivbe6ZRtlxuHtKpfcSw/S0FCbmZ3LNhOFMLshiyshMJhdkMTondubE+5vCXURiUijkVBw7wbbDDWyvOnk23sjeI810hW/2SU0xxuVlcHlh9xLDkyEexOqUWKNwF5HANbR2sONwI9urGtgW/r3jcCPNvW67Lx42pOfiZvfZeBbj8jIYmJYaYOWxS+EuIpdMZ1eIfXXNbKtqZPvh7gDfVtVI5fETPWOyB6UxdVQ298wpYuqobKaOzGJyQdZF37GZbHS0RKRf1DW1sf1wI9uqGth+uDvMd1Y30d7Z/Vyf1BRjQn4Gs8cO5fPzipk2KoupI7PjYplhPFC4i8hF6ewKsfdIM1sONbC1qqEnzHvfuZmXOZBpo7L48jVjmToym6mjspiQn8mgAZpS6S8KdxGJWHNbJ9sPN7L1UD1bqxrYeqg7yNvCZ+PpqSlMHpnJgkn5PWfiU0ZmkZ81MODKk4/CXUTOqKaxla3hs/EthxrYdqiBvXXNPcsNcwYP4LLR2Xzx6rFMH53N9NHZTMjPZECSr1KJFQp3kSTXFXL21TX3BPnWQ91hfqTp1LRK0dDBXDY6m7uuLOwJ8tGaG49pCneRJNLZFWJ3bRObKurZcqiBTZX1bKtq6HnST1qKMakgixum5DN9VHeITxuVTc7gAQFXLudL4S6SoDq6QuyuaWJTZT2bK+t7gry1o3t+fEh6KpeNzube0jFcFj4bnzgiU+vGE4TCXSQBdHSF2Fnd2BPimyob2F7V0HOhMyM9lcsKc7hv3lhmFGZzeWEO4/IySU2SW/GTUZ/hbmZPAXcANe4+4wyf3wf8JWBAI/A1d98Y7UJFpFtnV4id1U18VHG856x82+HGnvXjmQPTei50Xl6Uw4zCHMYNz0ianirSLZIz96eBfwGePcvne4GF7n7MzG4DlgLzolOeSHJzdw4ePcGGiuNsPHi8J9BPTq1kDUpjxugc7r+2hBmFOVxemMPYYUMU5NJ3uLv7KjMrOcfn7/Z6uxYoikJdIknpSFMbGw8eZ2NFfU+YH2vpAGBgWgozCnNYNLeYK8fkMrMol5LhQ7RiRc4o2nPuDwK/PtuHZrYYWAxQXFwc5a8WiS/NbZ1sqjwZ4vVsOHi8p8dKisHkgixumT6SmWNyuKIolykjs7SGXCIWtXA3s0/QHe7XnW2Muy+le9qG0tJSj9Z3i8Q6d2d/XQsfHjjW/bP/ODuqG3ta1xYNHcyVxbncf20JM8Pz5GqUJRcjKn97zGwm8EPgNnevi8Y+ReJZS3snGw/W8+GBY6w/cIz1B473PNYtIz2VK4tz+aMbJjCrOJcrinIZnqnb8yW6LjrczawY+CXwRXffefElicQXd+fA0ZaeM/IPDxxj++FTZ+Xj8zK4YcoIZo/NZXbxUCYXZGkJovS7SJZCPg/cAOSZWQXwPWAAgLsvAb4LDAf+NXxhp9PdS/urYJGgdXaF2FbVyPv7jlK27yjr9h3ruVU/Iz2VK8bk8rWFE5g9NpdZY4YyNCM94IolGUWyWmZRH59/Ffhq1CoSiTEn2rtYf/AYZfuOsW7fUT7cf6znCUGFuYO5flIec8YOZXbxUKaM1Fm5xAZdsRE5zbHmdsr2dwf5+3uPsrmyns6QYwZTCrK4e3YRpSVDuapkGKNzBwddrsgZKdwl6R1vaWdt+VHWltextryO7Ycbge7e5DOLcnhowXiuKhnKnOJh5AxRAy2JDwp3STr1LR28t7eOteVHWVNex/bDDbjDoAEpXFUyjDtmjmLuuOHMLMrRk4IkbincJeE1tnbw/t6jrNlTx9q9dWw51B3mA9NSmDN2KN+8eTJXTxjOFUW5pKfpJiFJDAp3STidXSE2Vhxn9a4jrN51hA0Hj9MVctJTU5hVnMvXb5rENeOHc8WYXJ2ZS8JSuEvcc3f21bXw9q5aVu86wpo9dTS2dWIGMwtzeGTheOZPzGN28VCFuSQNhbvEpYbWDt7edYTV4UCvONbdk6UwdzB3XDGK6ybmc+2E4VpjLklL4S5xwd3ZVdPEW9treHN7DR/sP0ZnyMkamMY1E4bz8ILxXDcpX10SRcIU7hKzTrR3sab8CG9ur+Gt7bU9HROnjcpm8YLx3bf0F+eSpk6JIh+jcJeYUtPQyuvbqnl9azXv7qmjvTPEkPRUrpuYx6M3TuSGKfmMytGNQyJ9UbhL4PbUNvHalmpe23qY9QeOAzB2+BC+MG8sN04dwVXjhuqhzSLnSeEul1wo5GysOM5rW6t5bcth9tQ2AzCzKIf/cstkbrlsJJNGZGruXOQiKNzlkgiFnPUHj/HyR1Ws2FRFdUMbaSnG1eOH8+VrS7h5WoH6tIhEkcJd+o27s/7gcV4JB3pVfSvpaSncMDmf2y4fyY1TCtSrRaSfKNwlqtydTZX1vPxRFa98VEXl8ROkp6awYHI+f3nrVG6aNoKsQQp0kf6mcJeoOHi0hf/YUMkv11dSXtvMgFRjwaR8vnXLZG6eXkC2Al3kklK4ywWrP9HBik1VvPRhJe/vOwrAvHHDWHz9eG6bMUpTLiIBUrjLeekKOat21fJi2UHe2FpDe1eICfkZ/PmnpnDXlaMpGjok6BJFBIW7RKjy+AleLDvIi2UVVB4/wbCMdD4/r5i7ZxdyeWGOli2KxBiFu5xVR1eI/9xWw7J1B1i5sxaA6ybm8Z1PT+PmaQXqfS4Sw/oMdzN7CrgDqHH3GWf43ID/A9wOtAD3u/uH0S5ULp3qhlZ+snY/y9YdpLaxjYLsgTz6iYncWzqGMcM07SISDyI5c38a+Bfg2bN8fhswKfwzD/i38G+JMx9VHOept/fy8kdVdLlz45QRLJpbzA1T8tWcSyTO9Bnu7r7KzErOMeQu4Fl3d2CtmeWa2Sh3r4pWkdJ/OrtCvLqlmn9/Zy9l+4+ROTCNL11TwpevHcvY4RlBlyciFygac+6FwMFe7yvC2z4W7ma2GFgMUFxcHIWvlgvV3NbJT9/bz9Pv7ONQfStjhw/he783nXvmFOkmI5EEcEkvqLr7UmApQGlpqV/K75ZuJ9q7+PHafSxZWc7R5nauGT+cv7lrBjdOHUFqila8iCSKaIR7JTCm1/ui8DaJIa0dXfxk7X6WrNzDkaZ2rp+Ux599cjKzi4cGXZqI9INohPty4FEzW0b3hdR6zbfHjs6uEM+/f4AfvLmb2sY25k8czpKbJ1NaMizo0kSkH0WyFPJ54AYgz8wqgO8BAwDcfQmwgu5lkLvpXgr5lf4qVs7P27uO8NjLW9hZ3cTcccP4l0WzmDd+eNBlicglEMlqmUV9fO7AH0etIrlo+4408z9WbOP1rdUUDxvCE1+cwy3TC3QXqUgS0R2qCeREexc/eHMXP1xdTnpqCn9x6xQemD+OQQP0iDqRZKNwTxCrd9XynZc2c+BoC3fPLuTbt05lRPagoMsSkYAo3ONcXVMb//2Vbby0vpLxeRk8/9DVXDNB8+oiyU7hHqfcnZfWV/LYy1tpbuvkT2+cyB99YqKmYEQEULjHpdrGNv7rS5t4fWs1c8YO5X/dfTmTCrKCLktEYojCPc78elMV3/nVZpraOvnO7dN44LpxurNURD5G4R4n6ls6+N7yzfxqwyFmFGbzT/deqbN1ETkrhXscWFtexzeWbaC2qY2v3zSJR2+cyAC14BWRc1C4x7CukPN/39zFD/5zFyXDM3jpj65lZlFu0GWJSBxQuMeo6oZWvrFsA2vK6/jsrEL+9jMzyByo/10iEhmlRQz67Y4avvXCRlrau/j7e2Zyz5witQ4QkfOicI8hoZDzgzd38c9v7GJKQRaP3zeLiSN00VREzp/CPUY0tnbwZz/byBvbqrl7diH/87OX64YkEblgCvcYsKe2icXPlrGvroXv/d507r+2RNMwInJRFO4Be2NrNX/2sw2kp6Xw06/O42r1WxeRKFC4B8TdeXJ1OX/36+3MGJ3Dki/OoTB3cNBliUiCULgHoLMrxF//vy38ZO0BPj1zFP/wB1dofl1Eokrhfok1tXXyJ899yFs7anlk4QT+4lNTSFFvGBGJMoX7JXS4vpUHnl7HjupG/u7uy1k0tzjokkQkQSncL5HdNU186Ufv0dDayVP3X8XCyflBlyQiCSyi7lNmdquZ7TCz3Wb27TN8Xmxmb5nZejP7yMxuj36p8WtzZT33PrGG9q4QP3v4agW7iPS7PsPdzFKBx4HbgOnAIjObftqw/wa84O6zgM8B/xrtQuPVe+V1LFq6lsEDUnnxkWu5bHRO0CWJSBKI5Mx9LrDb3cvdvR1YBtx12hgHssOvc4BD0Ssxfr21vYYvPfU+I7IH8vOvXcO4vIygSxKRJBHJnHshcLDX+wpg3mlj/hp4zcz+BMgAbj7TjsxsMbAYoLg4sS8mvvzRIb6xbAPTRmXz9FeuYnjmwKBLEpEkEq0nPiwCnnb3IuB24Mdm9rF9u/tSdy9199L8/MSdd37loyq+vmwDs4pzee6heQp2EbnkIgn3SmBMr/dF4W29PQi8AODua4BBQF40Cow3v9lcxZ8uW8+sMbk8/ZW5ZA0aEHRJIpKEIgn3dcAkMxtnZul0XzBdftqYA8BNAGY2je5wr41mofHg1S2HefS59VxRlMPTD8wlQw/XEJGA9Bnu7t4JPAq8Cmyje1XMFjN7zMzuDA/7FvCQmW0Engfud3fvr6Jj0Rtbq3n0uQ+ZUZjDMw/M1VOTRCRQESWQu68AVpy27bu9Xm8F5ke3tPjx1vYavvbTD5g+KptnH9RUjIgEL1oXVJPWe+V1PPKTD5gyMotnH5xHtoJdRGKAwv0ibK6s56vPlFE0dDDPPjCPnMEKdhGJDQr3C9Ta0cWDz6wje/AAfvzgPIZlpAddkohID131u0A//6CC6oY2nn/oakbrIRsiEmN05n4BukLdT1G6ckwuV48fFnQ5IiIfo3C/AL/ZfJj9dS08snC8HmQtIjFJ4X6e3J0lK/cwPi+DT04fGXQ5IiJnpHA/T2v21LGpsp6HFownVY/HE5EYpXA/T0tWlZOXOZDPzioMuhQRkbNSuJ+HLYfqWbWzlgeuK2HQgNSgyxEROSuF+3lYuqqczIFp3DdvbNCliIick8I9QgePtvDyR1V8fl6x7kQVkZincI/Qj97eS4rBA/PHBV2KiEifFO4RONrczrJ1B/jMlYWMzBkUdDkiIn1SuEfg2TX7aO0IsXjB+KBLERGJiMK9Dyfau3jm3X3cPG0Ekwqygi5HRCQiCvc+vFB2kGMtHTyycELQpYiIREzhfg6dXSGeXF3OnLFDKS1RgzARiR8K93NYsfkwFcdO6KxdROKOwv0s3J0lv93DhPwMbpo6IuhyRETOS0Thbma3mtkOM9ttZt8+y5h7zWyrmW0xs+eiW+al9/buI2ytauDhBRNIUYMwEYkzfT6JycxSgceBTwIVwDozW+7uW3uNmQT8FTDf3Y+ZWdyf6i5ZuYeC7IHcNWt00KWIiJy3SM7c5wK73b3c3duBZcBdp415CHjc3Y8BuHtNdMu8tDZV1PPO7joemD+OgWlqECYi8SeScC8EDvZ6XxHe1ttkYLKZvWNma83s1jPtyMwWm1mZmZXV1tZeWMWXwBOr9pA1MI3PzysOuhQRkQsSrQuqacAk4AZgEfCkmeWePsjdl7p7qbuX5ufnR+mro2t/XTMrNlVx39VjyRqkBmEiEp8iCfdKYEyv90Xhbb1VAMvdvcPd9wI76Q77uPPD1XtJS0nhgfklQZciInLBIgn3dcAkMxtnZunA54Dlp435Fd1n7ZhZHt3TNOXRK/PSONLUxgtlB7l7diEjstUgTETiV5/h7u6dwKPAq8A24AV332Jmj5nZneFhrwJ1ZrYVeAv4c3ev66+i+8uz7+6jvSvEQ2oQJiJxrs+lkADuvgJYcdq27/Z67cA3wz9xqbmtk2fW7OeW6QVMyM8MuhwRkYuiO1TDfrbuIPUnOnhYrQZEJAEo3IGOrhA/ensvc0uGMbt4aNDliIhcNIU78PJHh6g8foJHbtBcu4gkhqQPd3fniZXlTC7I5IbJcd81QUQEULjz2521bD/cqAZhIpJQkj7cn1i5h1E5g/i9K9QgTEQSR1KH+4aDx1lbfpQHrxtHelpSHwoRSTBJnWhPrNxD9qA0PjdXDcJEJLEkbbjvPdLMb7Yc5ovXjCVzYET3comIxI2kDfelq8oZkJrC/deOC7oUEZGoS8pwr2ls5RcfVnDPnCLyswYGXY6ISNQlZbg/8+4+OrpCPHS9bloSkcSUdOHe1NbJj9fs57YZIxmXlxF0OSIi/SLpwn3Z+wdoaO3k4QVqECYiiSupwr29M8QPV+/lmvHDuWJMbtDliIj0m6QK9+UbD3G4oZWHF2quXUQSW9KEeyjkPLFyD1NHZrFwcmw+nFtEJFqSJtzf2lHDrpomHlk4ATM1CBORxJY04f7EynIKcwfz6Zmjgi5FRKTfJUW4f7D/GO/vO8pXrx/HgNSk+COLSJKLKOnM7FYz22Fmu83s2+cY9/tm5mZWGr0SL94TK/eQO2QAf3jVmKBLERG5JPoMdzNLBR4HbgOmA4vMbPoZxmUBXwfei3aRF2N3TROvb6vmS1ePZUi6GoSJSHKI5Mx9LrDb3cvdvR1YBtx1hnF/C3wfaI1ifRftyVXlpKem8OVrS4IuRUTkkokk3AuBg73eV4S39TCz2cAYd3/lXDsys8VmVmZmZbW1tedd7PmqbmjlpfWV3Fs6huGZahAmIsnjoq8umlkK8I/At/oa6+5L3b3U3Uvz8/t/rflT7+ylM6QGYSKSfCIJ90qg95XIovC2k7KAGcBvzWwfcDWwPOiLqg2tHTy39gC3Xz6K4uFDgixFROSSiyTc1wGTzGycmaUDnwOWn/zQ3evdPc/dS9y9BFgL3OnuZf1ScYSee+8AjW2dPLJQDcJEJPn0Ge7u3gk8CrwKbANecPctZvaYmd3Z3wVeiLbOLp56ey/XTcxjRmFO0OWIiFxyEa0NdPcVwIrTtn33LGNvuPiyLs5/rD9ETWMb/3DvFUGXIiISiIS7XTMUcpas2sNlo7O5bmJe0OWIiAQi4cL9jW3VlNc287AahIlIEkuocHd3lqzcw5hhg7l9xsigyxERCUxChXvZ/mN8eOA4D10/njQ1CBORJJZQCfjEyj0My0jnD+aoQZiIJLeECfed1Y28sa2GL19TwuD01KDLEREJVMKE+9JV5QwekMqXrhkbdCkiIoFLiHCvqj/Bf2yo5A+vGsPQjPSgyxERCVxChPtTb+8l5PDgdeOCLkVEJCbEfbjXt3Tw3HsHuGPmKMYMU4MwERFIgHD/yXv7aW7v4uEFahAmInJSXId7a0cX//7OPhZMzmf66OygyxERiRlxHe6//LCSI01tPLJQD+MQEektbsO9K+Q8ubqcmUU5XDN+eNDliIjElLgN99e2HGbvkWYeXqAGYSIip4vLcD/ZIGzs8CHcqgZhIiIfE5fh/t7eo2ysqOeh68eTmqKzdhGR08VluC9ZuYe8zHTumVMUdCkiIjEp7sJ9W1UDv91Ry/3XljBogBqEiYicSdyF+9JV5QxJT+ULV6tBmIjI2UQU7mZ2q5ntMLPdZvbtM3z+TTPbamYfmdl/mlm/JG/FsRaWbzzEornF5A5RgzARkbPpM9zNLBV4HLgNmA4sMrPppw1bD5S6+0zg58D/jnahAE+9vQ9DDcJERPoSyZn7XGC3u5e7ezuwDLir9wB3f8vdW8Jv1wJRv9J5vKWdZesOcOeVoxmdOzjauxcRSSiRhHshcLDX+4rwtrN5EPj1mT4ws8VmVmZmZbW1tZFXCfx4zX5a2rtYvECtBkRE+hLVC6pm9gWgFPj7M33u7kvdvdTdS/Pz8yPeb2tHF0+/u49PTMln6kg1CBMR6UtaBGMqgd5PnC4Kb/sdZnYz8B1gobu3Rae8bi9+UEFdczuPLFRbXxGRSERy5r4OmGRm48wsHfgcsLz3ADObBTwB3OnuNdEssCvkPLmqnCvH5DJ33LBo7lpEJGH1Ge7u3gk8CrwKbANecPctZvaYmd0ZHvb3QCbwopltMLPlZ9ndefv15ioOHG3hkYVqECYiEqlIpmVw9xXAitO2fbfX65ujXNfJ/fLEynLG52XwyekF/fEVIiIJKabvUH13Tx2bKut5aIEahImInI+YDvclK/eQnzWQz84618pLERE5XcyG++bKelbvOsJX5qtBmIjI+YrZcF+6qpzMgWncN08NwkREzldMhvvBoy28sqmKz88rJmfwgKDLERGJOzEZ7j9cXU6KwQPz1SBMRORCxFy4H21u52dlB/nMlYWMzBkUdDkiInEp5sL9mXf30doR4uGFahAmInKhYircW9o7eXbNPm6eVsDEEVlBlyMiErdiKtxfLKvgWEsHj+isXUTkosRMuHd2hXhydTlzxg6ltEQNwkRELkbMhPsrm6qoOHZCbX1FRKIgJsLd3VmyspyJIzK5aeqIoMsREYl7MRHuq3cdYVtVA4sXjCdFDcJERC5aTIT7E6v2UJA9kLuuHB10KSIiCSHwcN9UUc87u+t4YP44BqapQZiISDQEHu5LVu0ha2Aan59XHHQpIiIJI9Bw31/XzK83VXHf1WPJGqQGYSIi0RJouD+5upy0lBQemF8SZBkiIgknsHDvDDkvllVw9+xCRmSrQZiISDRFFO5mdquZ7TCz3Wb27TN8PtDMfhb+/D0zK+lrn3VNbbR3hXhogVoNiIhEW5/hbmapwOPAbcB0YJGZTT9t2IPAMXefCPwT8P2+9lvX1M4t0wuYkJ95/lWLiMg5RXLmPhfY7e7l7t4OLAPuOm3MXcAz4dc/B24ys3PejdTlzsNqNSAi0i8iCfdC4GCv9xXhbWcc4+6dQD0w/PQdmdliMyszs7LBKSFmFw+9sKpFROScLukFVXdf6u6l7l46cZSCXUSkv0QS7pXAmF7vi8LbzjjGzNKAHKAuGgWKiMj5iyTc1wGTzGycmaUDnwOWnzZmOfDl8Ot7gDfd3aNXpoiInI+0vga4e6eZPQq8CqQCT7n7FjN7DChz9+XAj4Afm9lu4Cjd/wCIiEhA+gx3AHdfAaw4bdt3e71uBf4guqWJiMiFCrxxmIiIRJ/CXUQkASncRUQSkMJdRCQBWVArFs2sEdgRyJfHnjzgSNBFxAgdi1N0LE7RsThlirtn9TUootUy/WSHu5cG+P0xw8zKdCy66VicomNxio7FKWZWFsk4TcuIiCQghbuISAIKMtyXBvjdsUbH4hQdi1N0LE7RsTglomMR2AVVERHpP5qWERFJQAp3EZEEFEi49/XA7WRhZk+ZWY2ZbQ66lqCZ2Rgze8vMtprZFjP7etA1BcXMBpnZ+2a2MXws/ibomoJkZqlmtt7MXg66lqCZ2T4z22RmG/paEnnJ59zDD9zeCXyS7kf2rQMWufvWS1pIDDCzBUAT8Ky7zwi6niCZ2ShglLt/aGZZwAfAZ5L074UBGe7eZGYDgLeBr7v72oBLC4SZfRMoBbLd/Y6g6wmSme0DSt29zxu6gjhzj+SB20nB3VfR3f8+6bl7lbt/GH7dCGzj48/qTQrerSn8dkD4JylXPphZEfBp4IdB1xJvggj3SB64LUnMzEqAWcB7AZcSmPBUxAagBnjd3ZP1WPwz8BdAKOA6YoUDr5nZB2a2+FwDdUFVYoqZZQK/AL7h7g1B1xMUd+9y9yvpfmbxXDNLumk7M7sDqHH3D4KuJYZc5+6zgduAPw5P7Z5REOEeyQO3JQmF55d/AfzU3X8ZdD2xwN2PA28BtwZcShDmA3eG55mXATea2U+CLSlY7l4Z/l0DvET3NPcZBRHukTxwW5JM+CLij4Bt7v6PQdcTJDPLN7Pc8OvBdC8+2B5oUQFw979y9yJ3L6E7J9509y8EXFZgzCwjvNgAM8sAbgHOutLukoe7u3cCJx+4vQ14wd23XOo6YoGZPQ+sAaaYWYWZPRh0TQGaD3yR7rOzDeGf24MuKiCjgLfM7CO6T4Zed/ekXwYoFABvm9lG4H3gFXf/zdkGq/2AiEgC0gVVEZEEpHAXEUlACncRkQSkcBcRSUAKdxGRBKRwFxFJQAp3EZEE9P8BQVzuRgTW/bMAAAAASUVORK5CYII=\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -330,7 +319,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -422,7 +411,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -548,7 +537,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -560,7 +549,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -597,7 +586,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -701,7 +690,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "First element of solution is \n", + "First element of solution is \n", "Solution has 11 elements.\n" ] } @@ -737,7 +726,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -844,7 +833,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -888,9 +877,9 @@ "formats": "ipynb,py:percent" }, "kernelspec": { - "display_name": "econ-ark-3.8", + "display_name": "Python 3", "language": "python", - "name": "econ-ark-3.8" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -902,7 +891,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.7" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/examples/ConsIndShockModel/PerfForesightConsumerType.ipynb b/examples/ConsIndShockModel/PerfForesightConsumerType.ipynb index 2077e3e5c..eaa1f8992 100644 --- a/examples/ConsIndShockModel/PerfForesightConsumerType.ipynb +++ b/examples/ConsIndShockModel/PerfForesightConsumerType.ipynb @@ -24,6 +24,7 @@ "from copy import copy\n", "\n", "import matplotlib.pyplot as plt\n", + "plt.ion # interactive figures\n", "import numpy as np\n", "\n", "from HARK.ConsumptionSaving.ConsIndShockModel import PerfForesightConsumerType\n", @@ -46,6 +47,7 @@ "This notebook provides documentation for the first of these three models.\n", "$\\newcommand{\\CRRA}{\\rho}$\n", "$\\newcommand{\\DiePrb}{\\mathsf{D}}$\n", + "$\\newcommand{\\LivPrb}{\\Pi}$\n", "$\\newcommand{\\PermGroFac}{\\Gamma}$\n", "$\\newcommand{\\Rfree}{\\mathsf{R}}$\n", "$\\newcommand{\\DiscFac}{\\beta}$" @@ -62,7 +64,7 @@ "\\begin{equation}\n", "U(C) = \\frac{C^{1-\\CRRA}}{1-\\rho},\n", "\\end{equation}\n", - "has perfect foresight about everything except whether he will die between the end of period $t$ and the beginning of period $t+1$, which occurs with probability $\\DiePrb_{t+1}$. Permanent labor income $P_t$ grows from period $t$ to period $t+1$ by factor $\\PermGroFac_{t+1}$.\n", + "has perfect foresight about everything except whether he will survive between the end of period $t$ and the beginning of period $t+1$, which occurs with probability $\\LivPrb_{t+1}$. Permanent labor income $P_t$ grows from period $t$ to period $t+1$ by factor $\\PermGroFac_{t+1}$.\n", "\n", "At the beginning of period $t$, the consumer has an amount of market resources $M_t$ (which includes both market wealth and currrent income) and must choose how much of those resources to consume $C_t$ and how much to retain in a riskless asset $A_t$, which will earn return factor $\\Rfree$. The consumer cannot necessarily borrow arbitarily; instead, he might be constrained to have a wealth-to-income ratio at least as great as some \"artificial borrowing constraint\" $\\underline{a} \\leq 0$.\n", "\n", @@ -71,7 +73,7 @@ "The agent's problem can be written in Bellman form as:\n", "\n", "\\begin{eqnarray*}\n", - "V_t(M_t,P_t) &=& \\max_{C_t}~U(C_t) ~+ \\DiscFac (1 - \\DiePrb_{t+1}) V_{t+1}(M_{t+1},P_{t+1}), \\\\\n", + "V_t(M_t,P_t) &=& \\max_{C_t}~U(C_t) ~+ \\DiscFac \\LivPrb_{t+1} V_{t+1}(M_{t+1},P_{t+1}), \\\\\n", "& s.t. & \\\\\n", "A_t &=& M_t - C_t, \\\\\n", "A_t/P_t &\\geq& \\underline{a}, \\\\\n", @@ -80,16 +82,35 @@ "P_{t+1} &=& \\PermGroFac_{t+1} P_t.\n", "\\end{eqnarray*}\n", "\n", - "The consumer's problem is characterized by a coefficient of relative risk aversion $\\CRRA$, an intertemporal discount factor $\\DiscFac$, an interest factor $\\Rfree$, and age-varying sequences of the permanent income growth factor $\\PermGroFac_t$ and survival probability $(1 - \\DiePrb_t)$.\n", + "The consumer's problem is characterized by a coefficient of relative risk aversion $\\CRRA$, an intertemporal discount factor $\\DiscFac$, an interest factor $\\Rfree$, and age-varying sequences of the permanent income growth factor $\\PermGroFac_t$ and survival probability $\\LivPrb_{t}$.\n", "\n", "While it does not reduce the computational complexity of the problem (as permanent income is deterministic, given its initial condition $P_0$), HARK represents this problem with *normalized* variables (represented in lower case), dividing all real variables by permanent income $P_t$ and utility levels by $P_t^{1-\\CRRA}$. The Bellman form of the model thus reduces to:\n", "\n", "\\begin{eqnarray*}\n", - "v_t(m_t) &=& \\max_{c_t}~U(c_t) ~+ \\DiscFac (1 - \\DiePrb_{t+1}) \\PermGroFac_{t+1}^{1-\\CRRA} v_{t+1}(m_{t+1}), \\\\\n", + "v_t(m_t) &=& \\max_{c_t}~u(c_t) ~+ \\DiscFac \\LivPrb_{t+1} \\PermGroFac_{t+1}^{1-\\CRRA} v_{t+1}(m_{t+1}), \\\\\n", "& s.t. & \\\\\n", "a_t &=& m_t - c_t, \\\\\n", "a_t &\\geq& \\underline{a}, \\\\\n", "m_{t+1} &=& \\Rfree/\\PermGroFac_{t+1} a_t + 1.\n", + "\\end{eqnarray*}\n", + "\n", + "whose first order condition is \n", + "\n", + "\\begin{align}\n", + "u^{\\prime}(c_{t}) & = \\DiscFac \\LivPrb_{t+1} \\PermGroFac_{t+1}^{-\\CRRA} v_{t+1}^{\\prime}(a_{t}(R/\\PermGroFac)+1)\n", + "\\\\ & \\equiv \\mathfrak{v}_{t}^{\\prime}(a_{t}), \n", + "\\end{align}\n", + "where $\\mathfrak{v}_{t}(a_{t})$ is the value of ending period $t$ with assets $a_{t}$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{eqnarray*}\n", + "v_t(m_t) &=& u(c_t) ~+ \\DiscFac \\LivPrb_{t+1} \\PermGroFac_{t+1}^{1-\\CRRA} v_{t+1}(m_{t+1}), \\\\\n", + "&=& u(c_t)\\sum_{t}^{t+h-1}()+(\\DiscFac \\LivPrb_{t+1} \\PermGroFac_{t+1}^{1-\\CRRA})^{h} v_{t+h}(1.)\\\\\n", + "v_t(m_t)-(\\DiscFac \\LivPrb_{t+1} \\PermGroFac_{t+1}^{1-\\CRRA})^{h} v_{t+h}(1.)&=& u(c_t)\\sum_{t}^{t+h-1}()\\\\\n", "\\end{eqnarray*}" ] }, @@ -99,7 +120,11 @@ "source": [ "## Solution method for PerfForesightConsumerType\n", "\n", - "Because of the assumptions of CRRA utility, no risk other than mortality, and no artificial borrowing constraint, the problem has a closed form solution. In fact, the consumption function is perfectly linear, and the value function composed with the inverse utility function is also linear. The mathematical solution of this model is described in detail in the lecture notes [PerfForesightCRRA](https://www.econ2.jhu.edu/people/ccarroll/public/lecturenotes/consumption/PerfForesightCRRA).\n", + "Because of the assumptions of CRRA utility, no risk other than mortality, and no artificial borrowing constraint, the problem has a closed form solution. In fact, in the absence of a liquidity constraint that could ever bind (equivalently, for $\\underline{a} = -\\infty$), the consumption function is perfectly linear, and the value function composed with the inverse utility function is also linear. The mathematical solution of this model is described in detail in the lecture notes [PerfForesightCRRA](https://www.econ2.jhu.edu/people/ccarroll/public/lecturenotes/consumption/PerfForesightCRRA), which also demonstrates that the Euler equation for the problem is\n", + "\n", + "\\begin{align}\n", + "u^{\\prime}(c_{t}) & = R \\beta \\LivPrb u^{\\prime}(c_{t+1})\n", + "\\end{align}\n", "\n", "The one period problem for this model is solved by the function `solveConsPerfForesight`, which creates an instance of the class `ConsPerfForesightSolver`. To construct an instance of the class `PerfForesightConsumerType`, several parameters must be passed to its constructor as shown in the table below." ] @@ -115,7 +140,7 @@ "| $\\DiscFac$ |Intertemporal discount factor | $\\texttt{DiscFac}$ | $0.96$ | |\n", "| $\\CRRA $ |Coefficient of relative risk aversion | $\\texttt{CRRA}$ | $2.0$ | |\n", "| $\\Rfree$ | Risk free interest factor | $\\texttt{Rfree}$ | $1.03$ | |\n", - "| $1 - \\DiePrb_{t+1}$ |Survival probability | $\\texttt{LivPrb}$ | $[0.98]$ | $\\surd$ |\n", + "| $\\LivPrb_{t+1}$ |Survival probability | $\\texttt{LivPrb}$ | $[0.98]$ | $\\surd$ |\n", "|$\\PermGroFac_{t+1}$|Permanent income growth factor|$\\texttt{PermGroFac}$| $[1.01]$ | $\\surd$ |\n", "|$\\underline{a}$|Artificial borrowing constraint|$\\texttt{BoroCnstArt}$| $None$ | |\n", "|$(none)$|Maximum number of gridpoints in consumption function |$\\texttt{aXtraCount}$| $200$ | |\n", @@ -194,7 +219,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[]\n" + "[]\n" ] } ], @@ -220,7 +245,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'cFunc': , 'vFunc': , 'vPfunc': , 'vPPfunc': , 'mNrmMin': -50.49994992551661, 'hNrm': 50.49994992551661, 'MPCmin': 0.04428139169919579, 'MPCmax': 0.04428139169919579}\n" + "{'cFunc': , 'vFunc': , 'vPfunc': , 'vPPfunc': , 'mNrmMin': -50.49994992551661, 'hNrm': 50.49994992551661, 'MPCmin': 0.04428139169919579, 'MPCmax': 0.04428139169919579}\n" ] } ], @@ -246,18 +271,6 @@ "text": [ "Linear perfect foresight consumption function:\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" } ], "source": [ @@ -277,18 +290,6 @@ "text": [ "Perfect foresight value function:\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" } ], "source": [ @@ -304,7 +305,7 @@ "\n", "### Liquidity constrained perfect foresight example\n", "\n", - "Without an artificial borrowing constraint, a perfect foresight consumer is free to borrow against the PDV of his entire future stream of labor income-- his \"human wealth\" $\\texttt{hNrm}$-- and he will consume a constant proportion of his total wealth (market resources plus human wealth). If we introduce an artificial borrowing constraint, both of these features vanish. In the cell below, we define a parameter dictionary that prevents the consumer from borrowing *at all*, create and solve a new instance of `PerfForesightConsumerType` with it, and then plot its consumption function." + "Without an artificial borrowing constraint, a perfect foresight consumer is free to borrow against the PDV of the entire future stream of labor income-- \"human wealth\" $\\texttt{hNrm}$-- and will consume a constant proportion of total wealth (market resources plus human wealth). If we introduce an artificial borrowing constraint, both of these features vanish. In the cell below, we define a parameter dictionary that prevents the consumer from borrowing *at all*, create and solve a new instance of `PerfForesightConsumerType` with it, and then plot its consumption function." ] }, { @@ -322,18 +323,6 @@ "text": [ "Liquidity constrained perfect foresight consumption function:\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" } ], "source": [ @@ -489,20 +478,7 @@ "name": "#%%\n" } }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "plt.plot(np.mean(PFexample.history['mNrm'], axis=1))\n", "plt.xlabel(\"Time\")\n", @@ -529,20 +505,7 @@ "name": "#%%\n" } }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "N = PFexample.AgentCount\n", "F = np.linspace(0.0, 1.0, N)\n", @@ -577,20 +540,7 @@ "name": "#%%\n" } }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "PFexample.initialize_sim()\n", "PFexample.simulate(80)\n", @@ -604,11 +554,256 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Appendix: Derivation of Analytical Formulae for Liquidity Constraints" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "In the simple case where there is a constraint that requires the consumer to end the period with nonnegative assets, we can obtain a closed form solution for the liquidity constrained PF consumption function as follows.\n", + "\n", + "Consider the consumer as of the end of the penultimate period $T-1$. There will be some value $m_{T-1}^{\\#,1}$ such that for any $m > m_{T-1}^{\\#,1}$ the unconstrained consumer would wish to end the period with positive assets, while for $m < m_{T-1}^{\\#,1}$ an unconstrained consumer would borrow.\n", + "\n", + "With a CRRA utility function for which marginal utility is $u^{\\prime}(c)=c^{-\\rho}$, the Euler equation above says\n", + "\\begin{align}\n", + "(c_{T-1}^{\\#,1})^{-\\rho} & = \\mathfrak{v}^{\\prime}_{T-1}(\\underline{a}_{T-1})\n", + "\\\\ m^{\\#} \\equiv m_{T-1}^{\\#,1} = c_{T-1}^{\\#,1} + \\underline{a}_{T-1}& = \\left(\\mathfrak{v}^{\\prime}_{T-1}(\\underline{a}_{T-1})\\right)^{-1/\\CRRA}\n", + "\\end{align}\n", + "\n", + "Under the [relevant impatience conditions](https://econ-ark.github.io/BufferStockTheory), we can show that the constraint will bind for $m_{T-n} 0$) as well. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The corresponding value function is \n", + "\\begin{align}\n", + "v_{T-1} &= u(c_{T-1})+ \\beta_{T-1} \\Gamma_{T-1}^{1-\\rho} v_{T}\n", + "\\end{align}\n", + "where we assume that the terminal value function has two components: \n", + "\\begin{align}\n", + "v_{T}(m) & = u(c_{T}(m)) + \\mathcal{V}_{T}(m-c_{T}(m))\n", + "\\end{align}\n", + "where $\\mathcal{V}$ is the utility from any bequest made from unconsumed resources. \n", + "\n", + "For the present, we assume that $\\mathcal{V}_{T}(a)=0$: No utility is gained from unspent assets at death. (Below see a discussion of an alternative).\n", + "\n", + "In this case, the consumer who chooses to end the penultimate period with a positive amount of assets will consume all remaining assets in period $T$, resulting in a terminal value function of $v_{T}(m_{T})=u(c_{T}(m_{T})=u(c_{T})$. The Euler equation will not bind for such a consumer, and if minimum income next period is 1, then a consumer on the cusp where the constraint makes a transition from binding to not binding will satisfy\n", + "\n", + "\\begin{align}\n", + "\\mathfrak{v}^{\\prime}_{T-1}(\\underline{a}_{T-1}) & = \\beta \\Gamma_{T}^{-\\rho} 1^{-\\rho}\n", + "\\\\ c^{\\#,1}_{T-1} & = \\left(\\beta \\Gamma_{T}^{-\\rho} 1^{-\\rho}\\right)^{-1/\\CRRA}\n", + "\\end{align}\n", + "\n", + "If the consumer satisfies the relevant borrowing constraints, the constraint will also bind in period $T-2$, at the point \n", + "\\begin{align}\n", + "\\mathfrak{v}^{\\prime}_{T-1}(\\underline{a}_{T-1}) & = \\beta \\Gamma_{T}^{-\\rho} 1^{-\\rho}\n", + "\\\\ c^{\\#,1}_{T-1} & = \\left(\\beta \\Gamma_{T}^{-\\rho} 1^{-\\rho}\\right)^{-1/\\CRRA}\n", + "\\end{align}\n", + "\n", + "\n", + "#### Stone Geary Bequests\n", + "\n", + "We now consider a bequest function of a Stone-Geary form like:\n", + "\\begin{align}\n", + "\\mathcal{V}_{T}(a) & = \\left(\\frac{(\\eta + a)^{1-\\rho}}{1-\\rho}\\right)\\Upsilon \n", + "\\end{align}\n", + "where $\\eta$ is an intercept that has the effect of causing bequests to be a luxury good: people with an absolute level of market resources $m_{T}$ below a certain level will wish to leave no bequest, $a_{T}=0$. (As wealth gets arbitrarily large, the ratio of bequest wealth to last period consumption approaches a constant whose size depends on $\\Upsilon$).\n", + "\n", + "For a consumer with $m_{T} > m_{T}^{\\#,0}$,\n", + "\\begin{align}\n", + "v_{T}(m) & = \\max_{c} u(c)+\\Upsilon u(\\eta+(m-c))\n", + "\\end{align}\n", + "has FOC\n", + "\\begin{align}\n", + "c^{-\\rho} & = \\Upsilon (\\eta+(m-c))^{-\\rho}\n", + "\\\\ c & = \\Upsilon^{-1/\\rho} (\\eta+m-c)\n", + "\\\\ (1+\\Upsilon^{1/\\rho})c & = \\eta+m\n", + "\\\\ c & = \\left(\\frac{\\eta+m}{1+\\Upsilon^{1/\\rho}}\\right)\n", + "\\end{align}\n", + "and so the point at which the constraint $(m-c) \\geq 0$ begins to bind is:\n", + "\\begin{align}\n", + "m & = \\left(\\frac{\\eta+m}{(1+\\Upsilon^{1/\\rho})}\\right) \n", + "\\\\ (1+\\Upsilon^{1/\\rho})m & = \\left(\\eta+m\\right) \n", + "\\\\ m & = \\eta \\Upsilon^{1/\\rho}\n", + "%\n", + "%\\\\ \\left(\\left(\\frac{1+\\Upsilon^{-1/\\rho}}{1+\\Upsilon^{-1/\\rho}}\\right)- \\left(\\frac{1}{1+\\Upsilon^{-1/\\rho}}\\right)\\right) m & = \\left(\\frac{\\eta}{(1+\\Upsilon^{-1/\\rho})}\\right)\n", + "%\\\\ m & = \\frac{\\left(\\frac{\\eta}{(1+\\Upsilon^{-1/\\rho})}\\right)}{1- \\left(\\frac{1}{(1+\\Upsilon^{-1/\\rho})}\\right)}\n", + "\\end{align}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is easy to show that the ratio of $(\\eta + a_{T})$ to $c_{T}$ will be constant at some $\\Phi_{T}$, so for this unconstrained consumer value will be \n", + "\\begin{align}\n", + "v^{u}_{T}(m) & = u(c_{T}(m)) + \\Upsilon u(\\Phi_{T} c_{T}) \\\\\n", + "(1-\\rho)v_{T}(m) & = c_{T}^{1-\\rho} + \\Upsilon (\\Phi_{T} c_{T})^{1-\\rho}\n", + "\\\\ & = c_{T}^{1-\\rho}\\left(1 + \\Upsilon \\Phi_{T}\\right)\n", + "\\\\ \\Lambda_{T}^{u} \\equiv u^{-1}(v_{T}) & = c_{T}\\left(1 + \\Upsilon \\Phi_{T}\\right)^{1/(1-\\rho)}\n", + "\\end{align}\n", + "and the budget constraint requires that\n", + "\\begin{align}\n", + "m_{T} & = c_{T} + a_{T} \\\\\n", + "\\eta + a_{T} &= \\Phi_{T} c_{T} \\\\\n", + "a_{T} &= \\Phi_{T} c_{T}-\\eta \\\\ \n", + "\\left(\\frac{m_{T}+\\eta}{1+\\Phi_{T}}\\right) & = c_{T}\n", + "\\end{align}\n", + "or defining $\\kappa_{T}=1/(1+\\Phi_{T})$ and $\\gamma_{T}=\\eta/(1+\\Phi_{T})$, we have \n", + "\\begin{align}\n", + "\\Lambda_{T}^{u} & = (\\kappa_{T}m_{T}+\\gamma_{T})\\left(1 + \\Upsilon \\Phi_{T}\\right)^{1/(1-\\rho)}\n", + "\\end{align}\n", + "\n", + "while for the constrained consumer value will be \n", + "\\begin{align}\n", + "v^{c}_{T}(m_{T}) & = u(c_{T}) + \\Upsilon u(\\eta)\n", + "% \\\\ (1-\\rho)v^{c}_{T}(m) & = m_{T}^{1-\\rho} + \\Upsilon (\\Phi_{T} \\eta)^{1-\\rho}\n", + " \\\\ \\left(\\left(1-\\rho\\right)(v^{c}_{T}(m) - \\Upsilon u( \\eta))\\right)^{1/(1-\\rho)} & = m_{T} \\kappa_{T} \\equiv \\Lambda^{c}_{T}(m)\n", + "\\end{align}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The value function is therefore piecewise. Using $\\mathbb{1}$ as an indicator of whether the bequest constraint is binding or not, it can be written as the sum of three components:\n", + "\\begin{align}\n", + "v_{T}(m) & = (1-\\mathbb{1}) v_{T}^{u} + v_{T}^{c}\\mathbb{1}\n", + "\\\\ & = (1-\\mathbb{1}) v_{T}^{u} + \\left(v_{T}^{c}-\\Upsilon (\\eta)^{1-\\rho}\\right)\\mathbb{1}+(\\Upsilon (\\eta)^{1-\\rho})\\mathbb{1}\n", + "\\\\ & = (1-\\mathbb{1}) u(\\Lambda_{T}^{u}) + u(\\Lambda_{T}^{c})\\mathbb{1}+(\\Upsilon (\\eta)^{1-\\rho})\\mathbb{1}\n", + "\\end{align}\n", + "where $\\Lambda_{T}^{c}$ and $\\Lambda_{T}^{u}$ are linear functions and $(\\Upsilon (\\eta)^{1-\\rho})\\mathbb{1}$ is a constant." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can obtain the $a_{T-2}^{\\#,2}$ such that a consumer who was unconstrained between $T-2$ and $T-1$ would arrive in period $T-1$ with $m_{T-1}^{\\#,1}$ via the DBC:\n", + "\\begin{align}\n", + "m_{T-1}^{\\#,1}& = a_{T-2}^{\\#,2} (\\Rfree/\\PermGroFac) + 1\n", + "\\\\ (\\PermGroFac/\\Rfree)(m_{T-1}^{\\#,1}-1) &= a_{T-2}^{\\#,2}\n", + "\\end{align}\n", + "and we know that for such an ($T-2$ unconstrained) consumer the growth factor for consumption will be $C_{t+1}/C_{t} = c_{t+1}\\PermGroFac/c_{t} = (\\Rfree \\beta)^{1/\\CRRA}$ so the corresponding \n", + "\\begin{align}\n", + "c_{T-2}^{\\#,2} & = c_{T-1}^{\\#,1} (\\PermGroFac/(\\Rfree \\beta)^{1/\\CRRA})\n", + "\\end{align}\n", + "\n", + "But if the value of $a_{T-2}^{\\#,2}$ obtained from this procedure violates the borrowing constraint, $a_{T-2}^{\\#,2} < \\underline{a}_{T-2},$ the conclusion must be that the consumer who ended at $m_{T-1}^{\\#,1}$ cannot have been unconstrained between $T-2$ and $T-1$. In this case, the lowest kink point in $T-2$ is the same $m^{\\#}$ that obtained in period $T-1$. \n", + "\n", + "Thus, defining $\\vec{\\bullet}_{1}$ as the vector of values of $\\bullet$ obtained for period $T-1$ above (for example, $\\vec{c}_{2}=(c_{T-1}^{\\#,1},c_{T-2}^{\\#,2})$), we can calculate the locations of the kink points corresponding to horizons at which constraints stop binding iteratively: Using the $\\frown$ operator to append vectors, \n", + "\n", + "\\begin{align}\n", + "\\vec{c}_{n+1} & = (c^{\\#})^{\\frown}\\vec{c}_{n}(\\PermGroFac/(\\Rfree \\beta)^{1/\\CRRA}) \\\\\n", + "\\vec{a}_{n+1} & = (\\underline{a})^{\\frown}\\left((\\vec{m}_{n}-1)(\\PermGroFac/\\Rfree)\\right) \\\\\n", + "\\vec{m}_{n+1} & = (m^{\\#})^{\\frown}\\left(\\vec{a}_{n}+\\vec{c}_{n}\\right)\n", + "\\end{align}\n", + "\n", + "Thus for any period $T-n$ the consumption function is defined by the set of line segments connecting the points defined by the corresponding locations in $\\vec{m}_{n}$ and $\\vec{c}_{n}$ (together with a segment connecting $(0.,0.)$ to $(m^{\\#},c^{\\#})$, and using the unconstrained perfect foresight consumption function obtaining for points above $(m[n],c[n])$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The value function in period $T-1$ can be split into two parts. Define $n_{T-1}(m)$ as, for any $m$, the number of periods before a constraint (including the `cannot die in debt` constraint for peirod $T$) binds. That is, for a period $T-1$ consumer with $m < m_{T-1}^{\\#,1}$ we will have $n=0$ while for a $T-1$ consumer with $m \\geq m_{T-1}^{\\#,1}$ we will have $n=1$.\n", + "\n", + "Using this notation, \n", + "\n", + "\\begin{align}\n", + "v_{T-1}(m) & = u(c_{T-1}(m))+ \\beta\\Gamma_{T-1}^{1-\\rho} v_{T} \\\\ \n", + "(1-\\rho)v_{T-1} & = (c_{T-1}(m))^{1-\\rho} + \\beta\\Gamma_{T-1}^{1-\\rho} \\left(c_{T}(m_{T})^{1-\\rho}+\\Upsilon (m_{T}-c_{T})^{1-\\rho}\\right)\n", + "\\end{align}\n", + "\n", + "Dropping the $m_{t}$ arguments to reduce clutter, we can write this as the sum of two components. For a consumer for whom $n=1$ (the consumer is unconstrained in period $T$, consumption will grow by $\\Phi_{T-1}$ between $T-1$ and $T$ (we choose a possibly surprising notational convention to designate the growth factor $\\Phi$ that connects $c_{T-1}$ and $c_{T}$ as being associated with period $T-1$. This is in keeping with our assumption that by the time the consumer is ready to make their decision, the state variable $m_{T}$ must have been determined already by prior events). " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "(1-\\rho)v_{T-1}^{u} & = c_{T-1}^{1-\\rho} + \\beta_{T-1}\\Gamma_{T-1}^{1-\\rho} \\left(\\Phi_{T-1}c_{T-1})^{1-\\rho}+\\Upsilon (m_{T}-c_{T})^{1-\\rho}\\right)\n", + "\\\\ & = c_{T-1}^{1-\\rho}\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}\\right)+\\Upsilon (m_{T}-\\Phi_{T-1}c_{T-1})^{1-\\rho}\n", + "\\end{align}\n", + "\n", + "while for a consumer for whom $n=2$ (the 'bequest constraint' is also not binding)\n", + "\\begin{align}\n", + "(1-\\rho)v_{T-2}^{u} & = c_{T-2}^{1-\\rho} + \\beta_{T-2}(1-\\rho)v_{T-1}^{u}\n", + "\\end{align}\n", + "while for a consumer for whom $n=2$ (the 'bequest constraint' is also not binding)\n", + "\\begin{align}\n", + "(1-\\rho)v_{T-1}^{u} & = c_{T-1}^{1-\\rho} + \\beta_{T-1}\\Gamma_{T-1}^{1-\\rho} \\left(\\Phi_{T-1}c_{T-1})^{1-\\rho}+\\Upsilon (m_{T}-c_{T})^{1-\\rho}\\right)\n", + "\\\\ & = c_{T-1}^{1-\\rho}\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}+\\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}\\Upsilon \\Phi_{T}^{1-\\rho}\\right)\n", + "\\\\ & = c_{T-1}^{1-\\rho}\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}(1+\\Upsilon \\Phi_{T}^{1-\\rho})\\right)\n", + "\\end{align}\n", + "which has the convenient feature that if we define $u^{-1}(v) = \\left((1-\\rho)v\\right)^{1/(1-\\rho)}$ we can obtain\n", + "\\begin{align}\n", + "(1-\\rho)v_{T-1}^{u} & = c_{T-1}^{1-\\rho} + \\beta_{T-1}\\Gamma_{T-1}^{1-\\rho} \\left(\\Phi_{T-1}c_{T-1})^{1-\\rho}+\\Upsilon (m_{T}-c_{T})^{1-\\rho}\\right)\n", + "\\\\ & = c_{T-1}^{1-\\rho}\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}+\\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}\\Upsilon \\Phi_{T}^{1-\\rho}\\right)\n", + "\\\\ u^{-1}( v_{T-1}^{u} ) & = c_{T-1}\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}(1+\\Upsilon \\Phi_{T}^{1-\\rho})\\right)^{1/(1-\\rho)}\n", + "\\\\ & = \\kappa_{T-1} (m_{T-1}+h_{T-1})\\left(1 + \\beta_{T-1}(\\Gamma_{T-1}\\Phi_{T-1})^{1-\\rho}(1+\\Upsilon \\Phi_{T}^{1-\\rho})\\right)^{1/(1-\\rho)}\n", + "\\end{align}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\\begin{align}\n", + "v_{t} = & u(c_{t})+ \\beta \\Gamma^{1-\\rho} v_{t+1} \\\\\n", + "v_{t}/u(c_{t}) = & (1+\\beta \\Gamma^{1-\\rho} (u(c_{t+1})/u(c_{t}) +\\beta \\Gamma^{1-\\rho} v_{t+2}/u(c_{t}) \\\\\n", + "v_{t}/u(c_{t}) - 1 = & \\beta \\Gamma^{1-\\rho} (1+\\beta \\Gamma^{1-\\rho} v_{t+2}/u(c_{t}))\n", + "\\end{align}\n", + "\n", + "Deriving the value function is more complicated, because it needs to be split up into two parts.\n", + "\n", + "\\begin{align}\n", + "v_{t} = & u(c_{t})+ \\beta \\Gamma^{1-\\rho} v_{t+1}\n", + "\\\\ = & \\left(1-\\rho\\right)^{-1}\\left(c_{t}^{1-\\rho}+\\beta \\Gamma^{1-\\rho} v_{t+1} \\right) \n", + "\\\\ \\left(1-\\rho\\right) v_{t} = & c_{t}^{1-\\rho}\\left(1+...+(\\Phi_{\\Gamma} \\beta \\Gamma^{1-\\rho})^{n-1}\\right)+\n", + "\\\\ & (\\beta \\Gamma^{1-\\rho})^{n}\\left(c_{t+n}^{1-\\rho}(\\underline{a}_{t+n})+(\\beta \\Gamma^{1-\\rho})c_{t+n+1}^{1-\\rho}(\\underline{a}_{t+n+1})+...)\\right)\n", + "\\\\ \\left(1-\\rho\\right) v_{t} = & c_{t}^{1-\\rho}\\left(1+...+(\\Phi_{\\Gamma} \\beta \\Gamma^{1-\\rho})^{n-1}\\right)+\n", + "\\\\ & (\\beta \\Gamma^{1-\\rho})^{n}\\left((c_{t+n}(\\underline{a}_{t+n})/c_{t})^{1-\\rho}+(\\beta \\Gamma^{1-\\rho})(c_{t+n+1}(\\underline{a}_{t+n+1})/c_{t})+...)\\right)\n", + "\\\\ (\\left(1-\\rho\\right) v_{t})^{1/(1-\\rho)} & = \n", + "\\end{align}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "v_{t}(m) & = v_{t}(0)+\\kappa_{t} c(m) \\\\\n", + "v^{-1}_{t}(m) = u^{-1}(v_{t}) & = u^{-1}\\left(v_{t}(0)+\\kappa_{t} c(m)\\right) \\\\\n", + "\\frac{d}{dm} u^{-1}(v_{t}) & = \\frac{d}{dv}(u^{-1}(v))\\frac{d}{dm}v_{t}(m) \\\\\n", + "\\frac{d}{dm} (v^{-1}_{t}) & = \\underbrace{\\frac{d}{dv}((1-\\rho)v)^{1/(1-\\rho)})}_{\\equiv ((1-\\rho)v)^{-1+1/(1-\\rho)}}\\frac{d}{dm}v_{t}(m) \\\\\n", + "(\\frac{d}{dm}v^{-1}_{t}(m))\\left(v^{-1}_{t}(m)((1-\\rho)v)^{-1}\\right)^{-1} & = \\frac{d}{dm}v_{t}(m) \\\\ \n", + "(\\frac{d}{dm}v^{-1}_{t}(m))\\left(((1-\\rho)v)/(v^{-1}_{t}(m)))\\right) & = \\frac{d}{dm}v_{t}(m) \\\\ \n", + "(\\frac{d}{dm}v^{-1}_{t}(m))\\left((\\underbrace{(1-\\rho)v}_{\\equiv (v^{-1}(m))^{1-\\rho}})/(v^{-1}_{t}(m)))\\right) & = \\frac{d}{dm}v_{t}(m) \\\\ \n", + "(\\frac{d}{dm}v^{-1}_{t}(m))\\left(((1-\\rho)v)^{\\frac{\\rho}{1-\\rho}}\\right)^{-1} & = \\frac{d}{dm}v_{t}(m) \\\\ \n", + "(\\frac{d}{dm}v^{-1}_{t}(m))\\left(((1-\\rho)v)^{\\frac{1-\\rho}{\\rho}}\\right) & = \\frac{d}{dm}v_{t}(m) \\\\ \n", + "\\frac{d}{dm} u^{-1}(v_{t}) & = \\frac{d}{dv}((1-\\rho)v)^{1/(1-\\rho)})\n", + "\\end{align}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "v_{t} & = \\left(\\frac{1}{1-\\rho}\\right)\\left(c_{t}^{1-\\rho}\\right)(1+\\beta\\Phi^{1-\\rho}+((\\beta\\Phi)^2)^{1-\\rho}+...) \\\\ \n", + "v^{\\prime}_{t} & = c_{t}^{-\\rho}(1+\\beta\\Phi^{1-\\rho}+((\\beta\\Phi)^2)^{1-\\rho}+...) \n", + "\\end{align}" + ] } ], "metadata": { @@ -617,21 +812,15 @@ "formats": "ipynb,py:percent" }, "kernelspec": { - "display_name": "econ-ark-3.8", + "display_name": "Python 3.9 (XPython)", "language": "python", - "name": "econ-ark-3.8" + "name": "xpython" }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.7" + "version": "3.9.2" } }, "nbformat": 4, diff --git a/examples/ConsumptionSaving/example_ConsPortfolioModel.ipynb b/examples/ConsumptionSaving/example_ConsPortfolioModel.ipynb index 056db5f9a..1dd25067f 100644 --- a/examples/ConsumptionSaving/example_ConsPortfolioModel.ipynb +++ b/examples/ConsumptionSaving/example_ConsPortfolioModel.ipynb @@ -309,26 +309,6 @@ " ] , 0., 200.)" ] }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "print('\\n\\n\\n')" - ] - }, { "cell_type": "code", "execution_count": 10, @@ -692,20 +672,6 @@ " plt.ioff()\n", " plt.draw()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -729,7 +695,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/requirements.txt b/requirements.txt index 4de5983bf..c98389e42 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,3 +14,4 @@ interpolation numba quantecon pandas +