From a71e9504e0906eb8654175e64a2bb53a2d7dfde3 Mon Sep 17 00:00:00 2001 From: sb Date: Fri, 21 Feb 2020 10:24:50 -0500 Subject: [PATCH 1/3] functionalize out the conditions (AIC, GICPF, RIC, FHWC) from checkConditions() --- HARK/ConsumptionSaving/ConsIndShockModel.py | 89 ++++++++++++--------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index bc77c42fd..efebbaeae 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -1850,40 +1850,12 @@ def getPostStates(self): self.aLvlNow = self.aNrmNow*self.pLvlNow # Useful in some cases to precalculate asset level return None - def checkConditions(self,verbose=False,verbose_reference=False,public_call=False): + def checkAIC(self, thorn): ''' - 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) and the perfect foresight - model's version of the Finite Value of the Growth Impatience Condition (GIC_PF) and - Autarky Condition (FVAC_PF). 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 + Evaluate and report on the Absolute Impatience Condition ''' - # 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 + AIF = thorn - violated = False - - Thorn = (self.Rfree*self.DiscFac*self.LivPrb[0])**(1/self.CRRA) - AIF = Thorn - - #Evaluate and report on the Absolute Impatience Condition - - self.Thorn = Thorn self.AIF = AIF if AIF<1: self.AIC = True @@ -1900,9 +1872,12 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False violated = True print(' Because the AIF > 1, the absolute amount of consumption is expected to grow over time') print() - - #Evaluate and report on the Growth Impatience Condition - GIFPF = Thorn/self.PermGroFac[0] + + def checkGICPF(self,thorn): + ''' + Evaluate and report on the Growth Impatience Condition + ''' + GIFPF = thorn/self.PermGroFac[0] self.GIFPF = GIFPF if GIFPF<1: @@ -1919,9 +1894,11 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False if verbose: print(' Therefore, for a perfect foresight consumer the ratio of individual wealth to permanent income is expected to grow toward infinity.') print() - - #Evaluate and report on the Return Impatience Condition + def checkRIC(self, thorn): + ''' + Evaluate and report on the Return Impatience Condition + ''' RIF = Thorn/self.Rfree self.RIF = RIF @@ -1940,7 +1917,11 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False print('Therefore, the limiting consumption function is c(m)=0 for all m') print() - #Evaluate and report on the Finite Human Wealth Condition + def checkFHWC(self): + ''' + Evaluate and report on the Finite Human Wealth Condition + ''' + FHWF = self.PermGroFac[0]/self.Rfree self.FHWF = FHWF if FHWF<1: @@ -1966,6 +1947,40 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False return violated + def checkConditions(self,verbose=False,verbose_reference=False,public_call=False): + ''' + 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) and the perfect foresight + model's version of the Finite Value of the Growth Impatience Condition (GIC_PF) and + Autarky Condition (FVAC_PF). 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 + ''' + # 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 + + Thorn = (self.Rfree*self.DiscFac*self.LivPrb[0])**(1/self.CRRA) + self.Thorn = thorn + + self.checkAIC(Thorn) + self.checkGICPF(Thorn) + self.checkRIC(Thorn) + self.checkFHWC() + class IndShockConsumerType(PerfForesightConsumerType): ''' A consumer type with idiosyncratic shocks to permanent and transitory income. From c5f0ee5b56e532a320f2ee9f97311c100b98071d Mon Sep 17 00:00:00 2001 From: sb Date: Fri, 21 Feb 2020 11:00:50 -0500 Subject: [PATCH 2/3] functionalize out IndShockConsumerType conditions --- HARK/ConsumptionSaving/ConsIndShockModel.py | 177 ++++++++++---------- 1 file changed, 91 insertions(+), 86 deletions(-) diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index efebbaeae..7cba62da6 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -1850,7 +1850,7 @@ def getPostStates(self): self.aLvlNow = self.aNrmNow*self.pLvlNow # Useful in some cases to precalculate asset level return None - def checkAIC(self, thorn): + def checkAIC(self, thorn,verbose,public_call): ''' Evaluate and report on the Absolute Impatience Condition ''' @@ -1873,7 +1873,7 @@ def checkAIC(self, thorn): print(' Because the AIF > 1, the absolute amount of consumption is expected to grow over time') print() - def checkGICPF(self,thorn): + def checkGICPF(self,thorn,verbose,public_call): ''' Evaluate and report on the Growth Impatience Condition ''' @@ -1895,7 +1895,7 @@ def checkGICPF(self,thorn): print(' Therefore, for a perfect foresight consumer the ratio of individual wealth to permanent income is expected to grow toward infinity.') print() - def checkRIC(self, thorn): + def checkRIC(self, thorn,verbose,public_call): ''' Evaluate and report on the Return Impatience Condition ''' @@ -1917,7 +1917,7 @@ def checkRIC(self, thorn): print('Therefore, the limiting consumption function is c(m)=0 for all m') print() - def checkFHWC(self): + def checkFHWC(self,verbose,public_call): ''' Evaluate and report on the Finite Human Wealth Condition ''' @@ -1947,6 +1947,7 @@ def checkFHWC(self): return violated + def checkConditions(self,verbose=False,verbose_reference=False,public_call=False): ''' This method checks whether the instance's type satisfies the Absolute Impatience Condition (AIC), @@ -1976,10 +1977,10 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False Thorn = (self.Rfree*self.DiscFac*self.LivPrb[0])**(1/self.CRRA) self.Thorn = thorn - self.checkAIC(Thorn) - self.checkGICPF(Thorn) - self.checkRIC(Thorn) - self.checkFHWC() + self.checkAIC(Thorn,verbose,public_call) + self.checkGICPF(Thorn,verbose,public_call) + self.checkRIC(Thorn,verbose,public_call) + self.checkFHWC(verbose,public_call) class IndShockConsumerType(PerfForesightConsumerType): ''' @@ -2264,80 +2265,12 @@ def preSolve(self): if not self.quiet: self.checkConditions(verbose=self.verbose,public_call=False) - def checkConditions(self,verbose=False,public_call=True): + def checkGICInd(self,Thorn,verbose,public_call): ''' - 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 http://econ.jhu.edu/people/ccarroll/papers/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 + Check Individual Growth Impatience Factor. ''' - violated = False # PerfForesightConsumerType.checkConditions(self, verbose=False, verbose_reference=False) - - if self.cycles!=0 or self.T_cycle > 1: - return - - # For theory, see hyperlink targets to expressions in - # url=http://econ.jhu.edu/people/ccarroll/papers/BufferStockTheory - # For example, the hyperlink to the relevant section of the paper - url='http://econ.jhu.edu/people/ccarroll/papers/BufferStockTheory' - # would be referenced below as: - # [url]/#Uncertainty-Modified-Conditions - - self.InvPermShkDstn=deepcopy(self.PermShkDstn) - self.InvPermShkDstn[0][1]=1/self.PermShkDstn[0][1] - EPermShkInv=np.dot(self.InvPermShkDstn[0][0],1/self.PermShkDstn[0][1]) # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec) - InvEPermShkInv=(1/EPermShkInv) # $\underline{\psi}$ in the paper (\bar{\isp} in private version) - PermGroFacAdj=self.PermGroFac[0]*InvEPermShkInv # [url]/#PGroAdj - # [url]/#Pat, adjusted to include mortality -# Thorn = ((self.Rfree/self.LivPrb[0])*(self.DiscFac*self.LivPrb[0]))**(1/self.CRRA) - Thorn = ((self.Rfree*self.DiscFac))**(1/self.CRRA) - GIFPF = Thorn/(self.PermGroFac[0] ) # [url]/#GIF - GIFInd = Thorn/(self.PermGroFac[0]*InvEPermShkInv) # [url]/#GIFI - GIFAgg = Thorn*self.LivPrb[0]/self.PermGroFac[0] # Lower bound of aggregate wealth growth if all inheritances squandered - -# self.Rnorm = self.Rfree*EPermShkInv/(self.PermGroFac[0]*self.LivPrb[0]) - self.GIFPF = GIFPF - self.GIFInd = GIFInd - self.GIFAgg = GIFAgg - self.Thorn = Thorn - self.PermGroFacAdj = PermGroFacAdj - self.EPermShkInv = EPermShkInv - self.InvEPermShkInv = InvEPermShkInv - self.DiscFacGIFPFMax = ((self.PermGroFac[0] )**(self.CRRA))/(self.Rfree) # DiscFac at growth impatience knife edge - self.DiscFacGIFIndMax = ((self.PermGroFac[0]*InvEPermShkInv)**(self.CRRA))/(self.Rfree) # DiscFac at growth impatience knife edge - self.DiscFacGIFAggMax = ((self.PermGroFac[0] )**(self.CRRA))/(self.Rfree*self.LivPrb[0]) # DiscFac at growth impatience knife edge - - #Evaluate and report on the Growth Impatience Condition - # [url]/#GIC - if GIFPF<1: - self.GICPF = True - if public_call or verbose: - print('The value of the Perfect Foresight Growth Impatience Factor for the supplied parameter values satisfies the Perfect Foresight Growth Impatience Condition.', end = " ") - if verbose: - print(' Therefore, in the absence of any risk, the ratio of individual wealth to permanent income would fall indefinitely.') - print() - else: - self.GICPF = False - violated = True - print('The given parameter values violate the Perfect Foresight Growth Impatience Condition; the GIFPF is: %2.4f' % (GIFPF), end = " ") - if verbose: - print('') - print('Therefore, the ratio of wealth to permanent income approaches infinity in the perfect foresight model. (see '+url+' for more).') - print() - if GIFInd<=1: + if self.GIFInd<=1: self.GICInd = True if public_call or verbose: print('The value of the Individual Growth Impatience Factor for the supplied parameter values satisfies the Individual Growth Impatience Condition.', end = " ") @@ -2347,13 +2280,15 @@ def checkConditions(self,verbose=False,public_call=True): else: self.GICInd = False violated = True - print('The given parameter values violate the Individual Growth Impatience Condition; the GIFInd is: %2.4f' % (GIFInd), end = " ") + print('The given parameter values violate the Individual Growth Impatience Condition; the GIFInd is: %2.4f' % (self.GIFInd), end = " ") if verbose: print('') print('Therefore, a target ratio of individual market resources to individual permanent income does not exist. (see '+url+'/#onetarget for more).') print() - if GIFAgg<=1: + def checkCIGAgg(self, Thorn,verbose,public_call): + + if self.GIFAgg<=1: self.GICAgg = True if public_call or verbose: print('The value of the Aggregate Growth Impatience Factor for the supplied parameter values satisfies the Aggregate Growth Impatience Condition.', end = " ") @@ -2363,14 +2298,17 @@ def checkConditions(self,verbose=False,public_call=True): else: self.GICAgg = False violated = True - print('The given parameter values violate the Aggregate Growth Impatience Condition; the GIFAgg is: %2.4f' % (GIFAgg), end = " ") + print('The given parameter values violate the Aggregate Growth Impatience Condition; the GIFAgg is: %2.4f' % (self.GIFAgg), end = " ") if verbose: print('') print('Therefore, a target ratio of aggregate resources to aggregate permanent income does not exist.') # Need to provide reference print() - #Evaluate and report on the Weak Return Impatience Condition - # [url]/#WRIF modified to incorporate LivPrb + def checkWRIC(self, verbose,public_call): + ''' + Evaluate and report on the Weak Return Impatience Condition + [url]/#WRIF modified to incorporate LivPrb + ''' WRIF=(self.UnempPrb**(1/self.CRRA))*(self.Rfree*self.DiscFac*self.LivPrb[0])**(1/self.CRRA)/self.Rfree self.WRIF = WRIF if WRIF<=1: @@ -2387,8 +2325,11 @@ def checkConditions(self,verbose=False,public_call=True): print('Therefore, a nondegenerate solution is not available (see '+url+'/#WRIC for more.') print() - #Evaluate and report on the Finite Value of Autarky Condition - # Hyperlink to paper: [url]/#Autarky-Value + def checkFVAC(self,verbose,public_call): + ''' + Evaluate and report on the Finite Value of Autarky Condition + Hyperlink to paper: [url]/#Autarky-Value + ''' EpShkuInv = np.dot(self.PermShkDstn[0][0],self.PermShkDstn[0][1]**(1-self.CRRA)) if self.CRRA != 1.0: uInvEpShkuInv = EpShkuInv**(1/(1-self.CRRA)) # The term that gives a utility-consequence-adjusted utility growth @@ -2412,6 +2353,70 @@ def checkConditions(self,verbose=False,public_call=True): print('Therefore, a nondegenerate solution is not available (see '+url+'/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping') print() + + + + def checkConditions(self,verbose=False,public_call=True): + ''' + 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 http://econ.jhu.edu/people/ccarroll/papers/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 + ''' + violated = False # PerfForesightConsumerType.checkConditions(self, verbose=False, verbose_reference=False) + + if self.cycles!=0 or self.T_cycle > 1: + return + + # For theory, see hyperlink targets to expressions in + # url=http://econ.jhu.edu/people/ccarroll/papers/BufferStockTheory + # For example, the hyperlink to the relevant section of the paper + url='http://econ.jhu.edu/people/ccarroll/papers/BufferStockTheory' + # would be referenced below as: + # [url]/#Uncertainty-Modified-Conditions + + self.InvPermShkDstn=deepcopy(self.PermShkDstn) + self.InvPermShkDstn[0][1]=1/self.PermShkDstn[0][1] + EPermShkInv=np.dot(self.InvPermShkDstn[0][0],1/self.PermShkDstn[0][1]) # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec) + + InvEPermShkInv=(1/EPermShkInv) # $\underline{\psi}$ in the paper (\bar{\isp} in private version) + PermGroFacAdj=self.PermGroFac[0]*InvEPermShkInv # [url]/#PGroAdj + # [url]/#Pat, adjusted to include mortality +# Thorn = ((self.Rfree/self.LivPrb[0])*(self.DiscFac*self.LivPrb[0]))**(1/self.CRRA) + Thorn = ((self.Rfree*self.DiscFac))**(1/self.CRRA) + GIFPF = Thorn/(self.PermGroFac[0] ) # [url]/#GIF + GIFInd = Thorn/(self.PermGroFac[0]*InvEPermShkInv) # [url]/#GIFI + GIFAgg = Thorn*self.LivPrb[0]/self.PermGroFac[0] # Lower bound of aggregate wealth growth if all inheritances squandered + +# self.Rnorm = self.Rfree*EPermShkInv/(self.PermGroFac[0]*self.LivPrb[0]) + self.GIFPF = GIFPF + self.GIFInd = GIFInd + self.GIFAgg = GIFAgg + self.Thorn = Thorn + self.PermGroFacAdj = PermGroFacAdj + self.EPermShkInv = EPermShkInv + self.InvEPermShkInv = InvEPermShkInv + self.DiscFacGIFPFMax = ((self.PermGroFac[0] )**(self.CRRA))/(self.Rfree) # DiscFac at growth impatience knife edge + self.DiscFacGIFIndMax = ((self.PermGroFac[0]*InvEPermShkInv)**(self.CRRA))/(self.Rfree) # DiscFac at growth impatience knife edge + self.DiscFacGIFAggMax = ((self.PermGroFac[0] )**(self.CRRA))/(self.Rfree*self.LivPrb[0]) # DiscFac at growth impatience knife edge + + self.checkGICPF(Thorn,verbose,public_call) + self.checkGICInd(Thorn,verbose,public_call) + self.checkCIGAgg(Thorn,verbose,public_call) + self.checkWRIC(verbose,public_call) + if verbose and violated: print('\n[!] For more information on the conditions, see Tables 3 and 4 in "Theoretical Foundations of Buffer Stock Saving" at '+url+'/#Factors-Defined-And-Compared') print('') From d575be3fe33cdb7374e7ff6b8f1038ce25843ebd Mon Sep 17 00:00:00 2001 From: sb Date: Fri, 21 Feb 2020 11:30:31 -0500 Subject: [PATCH 3/3] violated now stored in the agent object to persist across tests --- HARK/ConsumptionSaving/ConsIndShockModel.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index 7cba62da6..7813703f2 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -1861,15 +1861,15 @@ def checkAIC(self, thorn,verbose,public_call): self.AIC = True if public_call or verbose: print('The value of the absolute impatience factor (AIF) for the supplied parameter values satisfies the Absolute Impatience Condition.', end = " ") + self.violated = False if verbose: - violated = False print(' Because the AIF < 1, the absolute amount of consumption is expected to fall over time.') print() else: self.AIC = False print('The given type violates the Absolute Impatience Condition with the supplied parameter values; the AIF is %1.5f ' % (AIF), end=" ") + self.violated = True if verbose: - violated = True print(' Because the AIF > 1, the absolute amount of consumption is expected to grow over time') print() @@ -1889,7 +1889,7 @@ def checkGICPF(self,thorn,verbose,public_call): print() else: self.GICPF = False - violated = True + self.violated = True print('The given parameter values violate the Perfect Foresight Growth Impatience Condition for this consumer type; the GIFPF is: %2.4f' % (GIFPF), end = " ") if verbose: print(' Therefore, for a perfect foresight consumer the ratio of individual wealth to permanent income is expected to grow toward infinity.') @@ -1911,7 +1911,7 @@ def checkRIC(self, thorn,verbose,public_call): print() else: self.RIC = False - violated = True + self.violated = True print('The given type violates the Return Impatience Condition with the supplied parameter values; the factor is %1.5f ' % (RIF), end = " ") if verbose: print('Therefore, the limiting consumption function is c(m)=0 for all m') @@ -1938,7 +1938,7 @@ def checkFHWC(self,verbose,public_call): else: self.FHWC = False print('The given type violates the Finite Human Wealth Condition; the Finite Human wealth factor value %2.5f ' % (FHWF), end = " ") - violated = True + self.violated = True if verbose: print('Therefore, the limiting consumption function is c(m)=Infinity for all m') print() @@ -2279,7 +2279,7 @@ def checkGICInd(self,Thorn,verbose,public_call): print() else: self.GICInd = False - violated = True + self.violated = True print('The given parameter values violate the Individual Growth Impatience Condition; the GIFInd is: %2.4f' % (self.GIFInd), end = " ") if verbose: print('') @@ -2297,7 +2297,7 @@ def checkCIGAgg(self, Thorn,verbose,public_call): print() else: self.GICAgg = False - violated = True + self.violated = True print('The given parameter values violate the Aggregate Growth Impatience Condition; the GIFAgg is: %2.4f' % (self.GIFAgg), end = " ") if verbose: print('') @@ -2318,7 +2318,7 @@ def checkWRIC(self, verbose,public_call): print() else: self.WRIC = False - violated = True + self.violated = True print('The given type violates the Weak Return Impatience Condition with the supplied parameter values. The WRIF is: %2.4f' % (WRIF), end = " ") if verbose: print('') @@ -2348,7 +2348,7 @@ def checkFVAC(self,verbose,public_call): else: self.FVAC = False print('The given type violates the Finite Value of Autarky Condition with the supplied parameter values. The FVAF is %2.4f' %(FVAF), end = " ") - violated = True + self.violated = True if public_call or verbose: print('Therefore, a nondegenerate solution is not available (see '+url+'/#Conditions-Under-Which-the-Problem-Defines-a-Contraction-Mapping') print() @@ -2417,7 +2417,7 @@ def checkConditions(self,verbose=False,public_call=True): self.checkCIGAgg(Thorn,verbose,public_call) self.checkWRIC(verbose,public_call) - if verbose and violated: + if verbose and self.violated: print('\n[!] For more information on the conditions, see Tables 3 and 4 in "Theoretical Foundations of Buffer Stock Saving" at '+url+'/#Factors-Defined-And-Compared') print('')