Skip to content

Commit fc75df4

Browse files
authored
Merge pull request #633 from sbenthall/i632-markov
Fixes for ConsMarkovModel, example, tests
2 parents 78d1981 + 844ea17 commit fc75df4

File tree

4 files changed

+66
-37
lines changed

4 files changed

+66
-37
lines changed

HARK/ConsumptionSaving/ConsMarkovModel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,7 @@ def getShocks(self):
897897
if N > 0:
898898
IncomeDstnNow = self.IncomeDstn[t-1][j] # set current income distribution
899899
PermGroFacNow = self.PermGroFac[t-1][j] # and permanent growth factor
900+
900901
Indices = np.arange(IncomeDstnNow[0].size) # just a list of integers
901902
# Get random draws of income shocks from the discrete distribution
902903
EventDraws = DiscreteDistribution(

HARK/ConsumptionSaving/tests/test_ConsMarkovModel.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22
from HARK.ConsumptionSaving.ConsIndShockModel import init_idiosyncratic_shocks
33
from HARK.ConsumptionSaving.ConsMarkovModel import MarkovConsumerType
4+
from HARK.distribution import DiscreteDistribution
45
from copy import copy
56
import unittest
67

@@ -17,7 +18,7 @@ def setUp(self):
1718
p_unemploy_good = p_reemploy * urate_good / (1 - urate_good)
1819
p_unemploy_bad = p_reemploy * urate_bad / (1 - urate_bad)
1920
boom_prob = 1.0 / recession_length
20-
self.MrkvArray = np.array(
21+
MrkvArray = np.array(
2122
[
2223
[
2324
(1 - p_unemploy_good) * (1 - bust_prob),
@@ -47,15 +48,32 @@ def setUp(self):
4748
)
4849

4950
init_serial_unemployment = copy(init_idiosyncratic_shocks)
50-
init_serial_unemployment["MrkvArray"] = [self.MrkvArray]
51-
self.model = MarkovConsumerType(**init_serial_unemployment)
52-
51+
init_serial_unemployment["MrkvArray"] = [MrkvArray]
52+
init_serial_unemployment["UnempPrb"] = 0 # to make income distribution when employed
53+
init_serial_unemployment["global_markov"] = False
54+
self.model = MarkovConsumerType(**init_serial_unemployment)
55+
self.model.cycles = 0
56+
self.model.vFuncBool = False # for easy toggling here
57+
58+
# Replace the default (lognormal) income distribution with a custom one
59+
employed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.ones(1)]) # Definitely get income
60+
unemployed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.zeros(1)]) # Definitely don't
61+
self.model.IncomeDstn = [
62+
[
63+
employed_income_dist,
64+
unemployed_income_dist,
65+
employed_income_dist,
66+
unemployed_income_dist,
67+
]
68+
]
69+
5370
def test_checkMarkovInputs(self):
5471
# check Rfree
5572
self.assertRaises(ValueError, self.model.checkMarkovInputs)
5673
# fix Rfree
5774
self.model.Rfree = np.array(4 * [self.model.Rfree])
5875
# check MrkvArray, first mess up the setup
76+
self.MrkvArray = self.model.MrkvArray
5977
self.model.MrkvArray = np.random.rand(3, 3)
6078
self.assertRaises(ValueError, self.model.checkMarkovInputs)
6179
# then fix it back
@@ -68,3 +86,7 @@ def test_checkMarkovInputs(self):
6886
self.assertRaises(ValueError, self.model.checkMarkovInputs)
6987
# fix PermGroFac
7088
self.model.PermGroFac = [np.array(4 * self.model.PermGroFac)]
89+
90+
def test_solve(self):
91+
self.test_checkMarkovInputs()
92+
self.model.solve()

examples/ConsumptionSaving/example_ConsMarkovModel.ipynb

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"import numpy as np\n",
1313
"from HARK.ConsumptionSaving.ConsIndShockModel import init_idiosyncratic_shocks\n",
1414
"from HARK.ConsumptionSaving.ConsMarkovModel import MarkovConsumerType\n",
15+
"from HARK.distribution import DiscreteDistribution\n",
1516
"mystr = lambda number: \"{:.4f}\".format(number)\n",
1617
"do_simulation = True"
1718
]
@@ -65,7 +66,11 @@
6566
{
6667
"cell_type": "code",
6768
"execution_count": 3,
68-
"metadata": {},
69+
"metadata": {
70+
"jupyter": {
71+
"source_hidden": true
72+
}
73+
},
6974
"outputs": [],
7075
"source": [
7176
"# Make a consumer with serially correlated unemployment, subject to boom and bust cycles\n",
@@ -85,8 +90,8 @@
8590
"outputs": [],
8691
"source": [
8792
"# Replace the default (lognormal) income distribution with a custom one\n",
88-
"employed_income_dist = [np.ones(1), np.ones(1), np.ones(1)] # Definitely get income\n",
89-
"unemployed_income_dist = [np.ones(1), np.ones(1), np.zeros(1)] # Definitely don't\n",
93+
"employed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.ones(1)]) # Definitely get income\n",
94+
"unemployed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.zeros(1)]) # Definitely don't\n",
9095
"SerialUnemploymentExample.IncomeDstn = [\n",
9196
" [\n",
9297
" employed_income_dist,\n",
@@ -120,7 +125,7 @@
120125
"name": "stdout",
121126
"output_type": "stream",
122127
"text": [
123-
"Solving a Markov consumer with serially correlated unemployment took 0.2911 seconds.\n",
128+
"Solving a Markov consumer with serially correlated unemployment took 0.2833 seconds.\n",
124129
"Consumption functions for each discrete state:\n"
125130
]
126131
},
@@ -190,16 +195,16 @@
190195
"outputs": [],
191196
"source": [
192197
"StateCount = ImmunityT + 1 # Total number of Markov states\n",
193-
"IncomeDstnReg = [\n",
198+
"IncomeDstnReg = DiscreteDistribution(\n",
194199
" np.array([1 - UnempPrb, UnempPrb]),\n",
195-
" np.array([1.0, 1.0]),\n",
196-
" np.array([1.0 / (1.0 - UnempPrb), 0.0]),\n",
197-
"] # Ordinary income distribution\n",
198-
"IncomeDstnImm = [\n",
199-
" np.array([1.0]),\n",
200+
" [np.array([1.0, 1.0]),\n",
201+
" np.array([1.0 / (1.0 - UnempPrb), 0.0])]\n",
202+
") # Ordinary income distribution\n",
203+
"IncomeDstnImm = DiscreteDistribution(\n",
200204
" np.array([1.0]),\n",
201-
" np.array([1.0]),\n",
202-
"] # Income distribution when unemployed\n",
205+
" [np.array([1.0]),\n",
206+
" np.array([1.0])]\n",
207+
")\n",
203208
"IncomeDstn = [IncomeDstnReg] + ImmunityT * [\n",
204209
" IncomeDstnImm\n",
205210
"] # Income distribution for each Markov state, in a list"
@@ -260,7 +265,7 @@
260265
"name": "stdout",
261266
"output_type": "stream",
262267
"text": [
263-
"Solving an \"unemployment immunity\" consumer took 0.3454 seconds.\n",
268+
"Solving an \"unemployment immunity\" consumer took 0.3062 seconds.\n",
264269
"Consumption functions for each discrete state:\n"
265270
]
266271
},
@@ -320,11 +325,11 @@
320325
"metadata": {},
321326
"outputs": [],
322327
"source": [
323-
"IncomeDstnReg = [\n",
328+
"IncomeDstnReg = DiscreteDistribution(\n",
324329
" np.array([1 - UnempPrb, UnempPrb]),\n",
325-
" np.array([1.0, 1.0]),\n",
326-
" np.array([1.0, 0.0]),\n",
327-
"]\n",
330+
" [np.array([1.0, 1.0]),\n",
331+
" np.array([1.0, 0.0])]\n",
332+
")\n",
328333
"IncomeDstn = StateCount * [\n",
329334
" IncomeDstnReg\n",
330335
"] # Same simple income distribution in each state"
@@ -375,7 +380,7 @@
375380
"name": "stdout",
376381
"output_type": "stream",
377382
"text": [
378-
"Solving a serially correlated growth consumer took 0.2647 seconds.\n",
383+
"Solving a serially correlated growth consumer took 0.2594 seconds.\n",
379384
"Consumption functions for each discrete state:\n"
380385
]
381386
},
@@ -431,7 +436,7 @@
431436
"name": "stdout",
432437
"output_type": "stream",
433438
"text": [
434-
"Solving a serially correlated interest consumer took 0.2409 seconds.\n",
439+
"Solving a serially correlated interest consumer took 0.2642 seconds.\n",
435440
"Consumption functions for each discrete state:\n"
436441
]
437442
},

examples/ConsumptionSaving/example_ConsMarkovModel.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import numpy as np
66
from HARK.ConsumptionSaving.ConsIndShockModel import init_idiosyncratic_shocks
77
from HARK.ConsumptionSaving.ConsMarkovModel import MarkovConsumerType
8+
from HARK.distribution import DiscreteDistribution
89
mystr = lambda number: "{:.4f}".format(number)
910
do_simulation = True
1011

@@ -60,8 +61,8 @@
6061

6162
# %%
6263
# Replace the default (lognormal) income distribution with a custom one
63-
employed_income_dist = [np.ones(1), np.ones(1), np.ones(1)] # Definitely get income
64-
unemployed_income_dist = [np.ones(1), np.ones(1), np.zeros(1)] # Definitely don't
64+
employed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.ones(1)]) # Definitely get income
65+
unemployed_income_dist = DiscreteDistribution(np.ones(1), [np.ones(1), np.zeros(1)]) # Definitely don't
6566
SerialUnemploymentExample.IncomeDstn = [
6667
[
6768
employed_income_dist,
@@ -114,16 +115,16 @@
114115

115116
# %%
116117
StateCount = ImmunityT + 1 # Total number of Markov states
117-
IncomeDstnReg = [
118+
IncomeDstnReg = DiscreteDistribution(
118119
np.array([1 - UnempPrb, UnempPrb]),
119-
np.array([1.0, 1.0]),
120-
np.array([1.0 / (1.0 - UnempPrb), 0.0]),
121-
] # Ordinary income distribution
122-
IncomeDstnImm = [
120+
[np.array([1.0, 1.0]),
121+
np.array([1.0 / (1.0 - UnempPrb), 0.0])]
122+
) # Ordinary income distribution
123+
IncomeDstnImm = DiscreteDistribution(
123124
np.array([1.0]),
124-
np.array([1.0]),
125-
np.array([1.0]),
126-
] # Income distribution when unemployed
125+
[np.array([1.0]),
126+
np.array([1.0])]
127+
)
127128
IncomeDstn = [IncomeDstnReg] + ImmunityT * [
128129
IncomeDstnImm
129130
] # Income distribution for each Markov state, in a list
@@ -185,11 +186,11 @@
185186
) # Probability of getting the same permanent income growth rate next period
186187

187188
# %%
188-
IncomeDstnReg = [
189+
IncomeDstnReg = DiscreteDistribution(
189190
np.array([1 - UnempPrb, UnempPrb]),
190-
np.array([1.0, 1.0]),
191-
np.array([1.0, 0.0]),
192-
]
191+
[np.array([1.0, 1.0]),
192+
np.array([1.0, 0.0])]
193+
)
193194
IncomeDstn = StateCount * [
194195
IncomeDstnReg
195196
] # Same simple income distribution in each state

0 commit comments

Comments
 (0)