Skip to content

Commit 17138dc

Browse files
authored
Merge branch 'master' into i583-bl
2 parents 21f0c7e + f5784d5 commit 17138dc

21 files changed

+1317
-689
lines changed

HARK/ConsumptionSaving/ConsAggShockModel.py

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
from builtins import range
1111
import numpy as np
1212
import scipy.stats as stats
13+
from HARK.distribution import DiscreteDistribution, combineIndepDstns, approxMeanOneLognormal
1314
from HARK.interpolation import LinearInterp, LinearInterpOnInterp1D, ConstantFunction, IdentityFunction,\
1415
VariableLowerBoundFunc2D, BilinearInterp, LowerEnvelope2D, UpperEnvelope
1516
from HARK.utilities import CRRAutility, CRRAutilityP, CRRAutilityPP, CRRAutilityP_inv,\
16-
CRRAutility_invP, CRRAutility_inv, combineIndepDstns,\
17-
approxMeanOneLognormal
18-
from HARK.simulation import drawDiscrete, drawUniform
17+
CRRAutility_invP, CRRAutility_inv
18+
from HARK.simulation import drawUniform
1919
from HARK.ConsumptionSaving.ConsIndShockModel import ConsumerSolution, IndShockConsumerType, init_idiosyncratic_shocks
2020
from HARK import HARKobject, Market, AgentType
2121
from copy import deepcopy
@@ -416,15 +416,18 @@ def addAggShkDstn(self, AggShkDstn):
416416
state. AggShkDstn is a list of aggregate productivity shock distributions
417417
for each Markov state.
418418
'''
419-
if len(self.IncomeDstn[0][0]) > 3:
419+
if len(self.IncomeDstn[0][0].X) > 2:
420420
self.IncomeDstn = self.IncomeDstnWithoutAggShocks
421421
else:
422422
self.IncomeDstnWithoutAggShocks = self.IncomeDstn
423423

424424
IncomeDstnOut = []
425425
N = self.MrkvArray.shape[0]
426426
for t in range(self.T_cycle):
427-
IncomeDstnOut.append([combineIndepDstns(self.IncomeDstn[t][n], AggShkDstn[n]) for n in range(N)])
427+
IncomeDstnOut.append(
428+
[combineIndepDstns(self.IncomeDstn[t][n],
429+
AggShkDstn[n])
430+
for n in range(N)])
428431
self.IncomeDstn = IncomeDstnOut
429432

430433
def updateSolutionTerminal(self):
@@ -475,8 +478,12 @@ def getShocks(self):
475478
PermGroFacNow = self.PermGroFac[t-1] # and permanent growth factor
476479
Indices = np.arange(IncomeDstnNow[0].size) # just a list of integers
477480
# Get random draws of income shocks from the discrete distribution
478-
EventDraws = drawDiscrete(N, X=Indices, P=IncomeDstnNow[0],
479-
exact_match=True, seed=self.RNG.randint(0, 2**31-1))
481+
EventDraws = DiscreteDistribution(
482+
IncomeDstnNow[0],
483+
Indices
484+
).drawDiscrete(N,
485+
exact_match=True,
486+
seed=self.RNG.randint(0, 2**31-1))
480487
# permanent "shock" includes expected growth
481488
PermShkNow[these] = IncomeDstnNow[1][EventDraws]*PermGroFacNow
482489
TranShkNow[these] = IncomeDstnNow[2][EventDraws]
@@ -490,8 +497,10 @@ def getShocks(self):
490497
PermGroFacNow = self.PermGroFac[0] # and permanent growth factor
491498
Indices = np.arange(IncomeDstnNow[0].size) # just a list of integers
492499
# Get random draws of income shocks from the discrete distribution
493-
EventDraws = drawDiscrete(N, X=Indices, P=IncomeDstnNow[0],
494-
exact_match=False, seed=self.RNG.randint(0, 2**31-1))
500+
EventDraws = DiscreteDistribution(
501+
IncomeDstnNow[0], Indices
502+
).drawDiscrete(N,
503+
seed=self.RNG.randint(0, 2**31-1))
495504
# permanent "shock" includes expected growth
496505
PermShkNow[these] = IncomeDstnNow[1][EventDraws]*PermGroFacNow
497506
TranShkNow[these] = IncomeDstnNow[2][EventDraws]
@@ -1121,10 +1130,13 @@ def makeAggShkHist(self):
11211130
None
11221131
'''
11231132
sim_periods = self.act_T
1124-
Events = np.arange(self.AggShkDstn[0].size) # just a list of integers
1125-
EventDraws = drawDiscrete(N=sim_periods, P=self.AggShkDstn[0], X=Events, seed=0)
1126-
PermShkAggHist = self.AggShkDstn[1][EventDraws]
1127-
TranShkAggHist = self.AggShkDstn[2][EventDraws]
1133+
Events = np.arange(self.AggShkDstn.pmf.size) # just a list of integers
1134+
EventDraws = self.AggShkDstn.drawDiscrete(
1135+
N=sim_periods,
1136+
X=Events,
1137+
seed=0)
1138+
PermShkAggHist = self.AggShkDstn.X[0][EventDraws]
1139+
TranShkAggHist = self.AggShkDstn.X[1][EventDraws]
11281140

11291141
# Store the histories
11301142
self.PermShkAggHist = PermShkAggHist*self.PermGroFacAgg
@@ -1352,10 +1364,13 @@ def makeAggShkHist(self):
13521364
None
13531365
'''
13541366
sim_periods = self.act_T
1355-
Events = np.arange(self.AggShkDstn[0].size) # just a list of integers
1356-
EventDraws = drawDiscrete(N=sim_periods, P=self.AggShkDstn[0], X=Events, seed=0)
1357-
PermShkAggHist = self.AggShkDstn[1][EventDraws]
1358-
TranShkAggHist = self.AggShkDstn[2][EventDraws]
1367+
Events = np.arange(self.AggShkDstn.pmf.size) # just a list of integers
1368+
EventDraws = self.AggShkDstn.drawDiscrete(
1369+
N=sim_periods,
1370+
X=Events,
1371+
seed=0)
1372+
PermShkAggHist = self.AggShkDstn.X[0][EventDraws]
1373+
TranShkAggHist = self.AggShkDstn.X[1][EventDraws]
13591374

13601375
# Store the histories
13611376
self.PermShkAggHist = PermShkAggHist
@@ -1543,10 +1558,13 @@ def makeAggShkHist(self):
15431558
PermShkAggHistAll = np.zeros((StateCount, sim_periods))
15441559
TranShkAggHistAll = np.zeros((StateCount, sim_periods))
15451560
for i in range(StateCount):
1546-
Events = np.arange(self.AggShkDstn[i][0].size) # just a list of integers
1547-
EventDraws = drawDiscrete(N=sim_periods, P=self.AggShkDstn[i][0], X=Events, seed=0)
1548-
PermShkAggHistAll[i, :] = self.AggShkDstn[i][1][EventDraws]
1549-
TranShkAggHistAll[i, :] = self.AggShkDstn[i][2][EventDraws]
1561+
Events = np.arange(self.AggShkDstn[i].pmf.size) # just a list of integers
1562+
EventDraws = self.AggShkDstn[i].drawDiscrete(
1563+
N=sim_periods,
1564+
X=Events,
1565+
seed=0)
1566+
PermShkAggHistAll[i, :] = self.AggShkDstn[i].X[0][EventDraws]
1567+
TranShkAggHistAll[i, :] = self.AggShkDstn[i].X[1][EventDraws]
15501568

15511569
# Select the actual history of aggregate shocks based on the sequence
15521570
# of Markov states that the economy experiences

HARK/ConsumptionSaving/ConsGenIncProcessModel.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
from copy import deepcopy
1212
import numpy as np
1313
from HARK import AgentType, HARKobject
14+
from HARK.distribution import DiscreteDistribution
1415
from HARK.interpolation import LowerEnvelope2D, BilinearInterp, VariableLowerBoundFunc2D, \
1516
LinearInterpOnInterp1D, LinearInterp, CubicInterp, UpperEnvelope
1617
from HARK.utilities import CRRAutility, CRRAutilityP, CRRAutilityPP, CRRAutilityP_inv, \
1718
CRRAutility_invP, CRRAutility_inv, CRRAutilityP_invP,\
1819
getPercentiles
19-
from HARK.simulation import drawLognormal, drawDiscrete, drawUniform
20+
from HARK.simulation import drawLognormal, drawUniform
2021
from HARK.ConsumptionSaving.ConsIndShockModel import ConsIndShockSetup, ConsumerSolution, IndShockConsumerType, init_idiosyncratic_shocks
2122

2223
__all__ = ['ValueFunc2D', 'MargValueFunc2D', 'MargMargValueFunc2D', 'pLvlFuncAR1',
@@ -1119,8 +1120,9 @@ def updatepLvlGrid(self):
11191120
# Calculate distribution of persistent income in each period of lifecycle
11201121
for t in range(len(self.PermShkStd)):
11211122
if t > 0:
1122-
PermShkNow = drawDiscrete(N=self.AgentCount, P=self.PermShkDstn[t-1][0],
1123-
X=self.PermShkDstn[t-1][1], exact_match=False, seed=t)
1123+
PermShkNow = self.PermShkDstn[t-1].drawDiscrete(
1124+
N=self.AgentCount,
1125+
seed=t)
11241126
pLvlNow = self.pLvlNextFunc[t-1](pLvlNow)*PermShkNow
11251127
pLvlGrid.append(getPercentiles(pLvlNow, percentiles=self.pLvlPctiles))
11261128

@@ -1136,10 +1138,12 @@ def updatepLvlGrid(self):
11361138
pLvlNow[who_dies] = drawLognormal(np.sum(who_dies), mu=self.pLvlInitMean,
11371139
sigma=self.pLvlInitStd, seed=t+92615)
11381140
t_cycle[who_dies] = 0
1141+
11391142
for j in range(self.T_cycle): # Update persistent income
11401143
these = t_cycle == j
1141-
PermShkTemp = drawDiscrete(N=np.sum(these), P=self.PermShkDstn[j][0],
1142-
X=self.PermShkDstn[j][1], exact_match=False, seed=t+13*j)
1144+
PermShkTemp = self.PermShkDstn[j].drawDiscrete(
1145+
N=np.sum(these),
1146+
seed=t+13*j)
11431147
pLvlNow[these] = self.pLvlNextFunc[j](pLvlNow[these])*PermShkTemp
11441148
t_cycle = t_cycle + 1
11451149
t_cycle[t_cycle == self.T_cycle] = 0

HARK/ConsumptionSaving/ConsIndShockModel.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
from HARK import AgentType, Solution, NullFunc, HARKobject
2525
from HARK.utilities import warnings # Because of "patch" to warnings modules
2626
from HARK.interpolation import CubicInterp, LowerEnvelope, LinearInterp
27-
from HARK.simulation import drawDiscrete, drawLognormal, drawUniform
28-
from HARK.utilities import approxMeanOneLognormal, addDiscreteOutcomeConstantMean,\
29-
combineIndepDstns, makeGridExpMult, CRRAutility, CRRAutilityP, \
27+
from HARK.simulation import drawLognormal, drawUniform
28+
from HARK.distribution import DiscreteDistribution, approxMeanOneLognormal, addDiscreteOutcomeConstantMean, combineIndepDstns
29+
from HARK.utilities import makeGridExpMult, CRRAutility, CRRAutilityP, \
3030
CRRAutilityPP, CRRAutilityP_inv, CRRAutility_invP, CRRAutility_inv, \
3131
CRRAutilityP_invP
3232

@@ -768,11 +768,10 @@ def setAndUpdateValues(self,solution_next,IncomeDstn,LivPrb,DiscFac):
768768
----------
769769
solution_next : ConsumerSolution
770770
The solution to next period's one period problem.
771-
IncomeDstn : [np.array]
772-
A list containing three arrays of floats, representing a discrete
773-
approximation to the income process between the period being solved
774-
and the one immediately following (in solution_next). Order: event
775-
probabilities, permanent shocks, transitory shocks.
771+
IncomeDstn : distribution.DiscreteDistribution
772+
A DiscreteDistribution with a pmf
773+
and two point value arrays in X, order:
774+
permanent shocks, transitory shocks.
776775
LivPrb : float
777776
Survival probability; likelihood of being alive at the beginning of
778777
the succeeding period.
@@ -783,10 +782,13 @@ def setAndUpdateValues(self,solution_next,IncomeDstn,LivPrb,DiscFac):
783782
-------
784783
None
785784
'''
785+
if isinstance(IncomeDstn, list):
786+
import pdb; pdb.set_trace()
787+
786788
self.DiscFacEff = DiscFac*LivPrb # "effective" discount factor
787-
self.ShkPrbsNext = IncomeDstn[0]
788-
self.PermShkValsNext = IncomeDstn[1]
789-
self.TranShkValsNext = IncomeDstn[2]
789+
self.ShkPrbsNext = IncomeDstn.pmf
790+
self.PermShkValsNext = IncomeDstn.X[0]
791+
self.TranShkValsNext = IncomeDstn.X[1]
790792
self.PermShkMinNext = np.min(self.PermShkValsNext)
791793
self.TranShkMinNext = np.min(self.TranShkValsNext)
792794
self.vPfuncNext = solution_next.vPfunc
@@ -2157,11 +2159,12 @@ def getShocks(self):
21572159
if N > 0:
21582160
IncomeDstnNow = self.IncomeDstn[t-1] # set current income distribution
21592161
PermGroFacNow = self.PermGroFac[t-1] # and permanent growth factor
2160-
Indices = np.arange(IncomeDstnNow[0].size) # just a list of integers
21612162
# Get random draws of income shocks from the discrete distribution
2162-
EventDraws = drawDiscrete(N,X=Indices,P=IncomeDstnNow[0],exact_match=False,seed=self.RNG.randint(0,2**31-1))
2163-
PermShkNow[these] = IncomeDstnNow[1][EventDraws]*PermGroFacNow # permanent "shock" includes expected growth
2164-
TranShkNow[these] = IncomeDstnNow[2][EventDraws]
2163+
EventDraws = IncomeDstnNow.draw_events(N,
2164+
seed=self.RNG.randint(0,2**31-1))
2165+
2166+
PermShkNow[these] = IncomeDstnNow.X[0][EventDraws]*PermGroFacNow # permanent "shock" includes expected growth
2167+
TranShkNow[these] = IncomeDstnNow.X[1][EventDraws]
21652168

21662169
# That procedure used the *last* period in the sequence for newborns, but that's not right
21672170
# Redraw shocks for newborns, using the *first* period in the sequence. Approximation.
@@ -2170,11 +2173,12 @@ def getShocks(self):
21702173
these = newborn
21712174
IncomeDstnNow = self.IncomeDstn[0] # set current income distribution
21722175
PermGroFacNow = self.PermGroFac[0] # and permanent growth factor
2173-
Indices = np.arange(IncomeDstnNow[0].size) # just a list of integers
2176+
21742177
# Get random draws of income shocks from the discrete distribution
2175-
EventDraws = drawDiscrete(N,X=Indices,P=IncomeDstnNow[0],exact_match=False,seed=self.RNG.randint(0,2**31-1))
2176-
PermShkNow[these] = IncomeDstnNow[1][EventDraws]*PermGroFacNow # permanent "shock" includes expected growth
2177-
TranShkNow[these] = IncomeDstnNow[2][EventDraws]
2178+
EventDraws = IncomeDstnNow.draw_events(N,
2179+
seed=self.RNG.randint(0,2**31-1))
2180+
PermShkNow[these] = IncomeDstnNow.X[0][EventDraws]*PermGroFacNow # permanent "shock" includes expected growth
2181+
TranShkNow[these] = IncomeDstnNow.X[1][EventDraws]
21782182
# PermShkNow[newborn] = 1.0
21792183
TranShkNow[newborn] = 1.0
21802184

@@ -2375,7 +2379,8 @@ def checkFVAC(self,verbose,public_call):
23752379
Evaluate and report on the Finite Value of Autarky Condition
23762380
Hyperlink to paper: [url]/#Autarky-Value
23772381
'''
2378-
EpShkuInv = np.dot(self.PermShkDstn[0][0],self.PermShkDstn[0][1]**(1-self.CRRA))
2382+
EpShkuInv = np.dot(self.PermShkDstn[0].pmf,
2383+
self.PermShkDstn[0].X**(1-self.CRRA))
23792384
if self.CRRA != 1.0:
23802385
uInvEpShkuInv = EpShkuInv**(1/(1-self.CRRA)) # The term that gives a utility-consequence-adjusted utility growth
23812386
else:
@@ -2431,8 +2436,9 @@ def checkConditions(self,verbose=False,public_call=True):
24312436
# [url]/#Uncertainty-Modified-Conditions
24322437

24332438
self.InvPermShkDstn=deepcopy(self.PermShkDstn)
2434-
self.InvPermShkDstn[0][1]=1/self.PermShkDstn[0][1]
2435-
EPermShkInv=np.dot(self.InvPermShkDstn[0][0],1/self.PermShkDstn[0][1]) # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec)
2439+
self.InvPermShkDstn[0].X = 1/self.PermShkDstn[0].X
2440+
EPermShkInv=np.dot(self.InvPermShkDstn[0].pmf,
2441+
1/self.PermShkDstn[0].X) # $\Ex_{t}[\psi^{-1}_{t+1}]$ (in first eqn in sec)
24362442

24372443
InvEPermShkInv=(1/EPermShkInv) # $\underline{\psi}$ in the paper (\bar{\isp} in private version)
24382444
PermGroFacAdj=self.PermGroFac[0]*InvEPermShkInv # [url]/#PGroAdj
@@ -2782,7 +2788,9 @@ def constructLognormalIncomeProcessUnemployment(parameters):
27822788
PermShkValsRet = np.array([1.0])
27832789
TranShkValsRet = np.array([1.0])
27842790
ShkPrbsRet = np.array([1.0])
2785-
IncomeDstnRet = [ShkPrbsRet,PermShkValsRet,TranShkValsRet]
2791+
IncomeDstnRet = DiscreteDistribution(ShkPrbsRet,
2792+
[PermShkValsRet,
2793+
TranShkValsRet])
27862794

27872795
# Loop to fill in the list of IncomeDstn random variables.
27882796
for t in range(T_cycle): # Iterate over all periods, counting forward

0 commit comments

Comments
 (0)