Skip to content

Commit

Permalink
generalised unpack function after a model is solved (#784)
Browse files Browse the repository at this point in the history
* generalised unpack function after a model is solved

* fix examples with changes to unpackcFunc

* stripout notebook output

* add deprecate warning to unpackcFunc

* Update CHANGELOG.md

Co-authored-by: Sebastian Benthall <[email protected]>
  • Loading branch information
Mridul Seth and sbenthall authored Aug 7, 2020
1 parent f79568c commit 5a3ab2a
Show file tree
Hide file tree
Showing 18 changed files with 1,005 additions and 535 deletions.
3 changes: 2 additions & 1 deletion Documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ For more information on HARK, see [our Github organization](https://github.com/e

### 0.10.7

Release Date: XX-XX-2020
Release Date: 08-08-2020

#### Major Changes

Expand All @@ -21,6 +21,7 @@ Release Date: XX-XX-2020

#### Minor Changes

- unpackcFunc is deprecated, use unpack(parameter) to unpack a parameter after solving the model [#784](https://github.com/econ-ark/HARK/pull/784)
- Remove deprecated Solution Class, use HARKObject across the codebase [#772](https://github.com/econ-ark/HARK/pull/772)
- Add option to find crossing points in the envelope step of DCEGM algorithm [#758](https://github.com/econ-ark/HARK/pull/758)
- Fix reset bug in the behaviour of AgentType.resetRNG(), implemented individual resetRNG methods for AgentTypes [#757](https://github.com/econ-ark/HARK/pull/757)
Expand Down
12 changes: 5 additions & 7 deletions HARK/ConsumptionSaving/ConsIndShockModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1531,25 +1531,23 @@ def updateSolutionTerminal(self):
self.solution_terminal.vPPfunc = MargMargValueFunc(self.cFunc_terminal_,self.CRRA)

def unpackcFunc(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
'''
self.cFunc = []
for solution_t in self.solution:
self.cFunc.append(solution_t.cFunc)
self.addToTimeVary('cFunc')
_log.critical("unpackcFunc is deprecated and it will soon be removed, " \
"please use unpack('cFunc') instead.")
self.unpack('cFunc')


def initializeSim(self):
self.PlvlAggNow = 1.0
Expand Down
6 changes: 3 additions & 3 deletions HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def test_baseEx(self):
baseEx.cycles = 100 # Make this type have a finite horizon (Set T = 100)

baseEx.solve()
baseEx.unpackcFunc()
baseEx.unpack('cFunc')

m = np.linspace(0,9.5,1000)

Expand All @@ -163,7 +163,7 @@ def test_GICFails(self):
**GIC_fail_dictionary)

GICFailExample.solve()
GICFailExample.unpackcFunc()
GICFailExample.unpack('cFunc')
m = np.linspace(0,5,1000)
c_m = GICFailExample.cFunc[0](m)

Expand All @@ -177,7 +177,7 @@ def test_infinite_horizon(self):
**self.base_params)

baseEx_inf.solve()
baseEx_inf.unpackcFunc()
baseEx_inf.unpack('cFunc')

m1 = np.linspace(1,baseEx_inf.solution[0].mNrmSS,50) # m1 defines the plot range on the left of target m value (e.g. m <= target m)
c_m1 = baseEx_inf.cFunc[0](m1)
Expand Down
6 changes: 3 additions & 3 deletions HARK/ConsumptionSaving/tests/test_modelcomparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ def setUp(self):

InfiniteType.updateIncomeProcess()
InfiniteType.solve()
InfiniteType.unpackcFunc()
InfiniteType.unpack('cFunc')

# Make and solve a perfect foresight consumer type with the same parameters
PerfectForesightType = PerfForesightConsumerType(**test_dictionary)
PerfectForesightType.cycles = 0

PerfectForesightType.solve()
PerfectForesightType.unpackcFunc()
PerfectForesightType.unpack('cFunc')

self.InfiniteType = InfiniteType
self.PerfectForesightType = PerfectForesightType
Expand Down Expand Up @@ -139,7 +139,7 @@ def setUp(self):
unemployed_income_dist]]

MarkovType.solve()
MarkovType.unpackcFunc()
MarkovType.unpack('cFunc')

self.TBSType = TBSType
self.MarkovType = MarkovType
Expand Down
23 changes: 23 additions & 0 deletions HARK/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,29 @@ def delFromTimeInv(self, *params):
if param in self.time_inv:
self.time_inv.remove(param)

def unpack(self, parameter):
'''
Unpacks a parameter from a solution object for easier access.
After the model has been solved, the parameters (like consumption function)
reside in the attributes of each element of `ConsumerType.solution`
(e.g. `cFunc`). This method creates a (time varying) attribute of the given
parameter name that contains a list of functions accessible by `ConsumerType.parameter`.
Parameters
----------
parameter: str
Name of the function to unpack from the solution
Returns
-------
none
'''
setattr(self, parameter, list())
for solution_t in self.solution:
self.__dict__[parameter].append(solution_t.__dict__[parameter])
self.addToTimeVary(parameter)


def solve(self, verbose=False):
'''
Solve the model for this instance of an agent type by backward induction.
Expand Down
181 changes: 68 additions & 113 deletions examples/ConsIndShockModel/IndShockConsumerType.ipynb

Large diffs are not rendered by default.

21 changes: 14 additions & 7 deletions examples/ConsIndShockModel/IndShockConsumerType.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,26 @@
# jupytext:
# cell_metadata_filter: collapsed,code_folding,heading_collapsed,hidden
# formats: ipynb,py:percent
# notebook_metadata_filter: all
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.2'
# jupytext_version: 1.2.4
# jupytext_version: 1.2.3
# kernelspec:
# display_name: Python 3
# language: python
# name: python3
# 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.7.6
# ---

# %% [markdown]
Expand All @@ -21,8 +32,6 @@
# %% {"code_folding": [0]}
# Initial imports and notebook setup, click arrow to show
from HARK.ConsumptionSaving.ConsIndShockModel import IndShockConsumerType
import HARK.logger as logger
logger.verbose()
from HARK.utilities import plotFuncsDer, plotFuncs
from time import clock
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -347,7 +356,7 @@
# %%
print('Consumption functions across the lifecycle:')
mMin = np.min([LifecycleExample.solution[t].mNrmMin for t in range(LifecycleExample.T_cycle)])
LifecycleExample.unpackcFunc() # This makes all of the cFuncs accessible in the attribute cFunc
LifecycleExample.unpack('cFunc') # This makes all of the cFuncs accessible in the attribute cFunc
plotFuncs(LifecycleExample.cFunc,mMin,5)

# %% [markdown]
Expand Down Expand Up @@ -412,12 +421,10 @@
CyclicalExample.cycles = 0 # Make this consumer type have an infinite horizon
CyclicalExample.solve()

CyclicalExample.unpackcFunc()
CyclicalExample.unpack('cFunc')
print('Quarterly consumption functions:')
mMin = min([X.mNrmMin for X in CyclicalExample.solution])
plotFuncs(CyclicalExample.cFunc,mMin,5)

# %% [markdown]
# The very low green consumption function corresponds to the quarter in which the ski instructors make most of their income. They know that they are about to experience a 70% drop in "permanent" income, so they do not consume much *relative to their income this quarter*. In the other three quarters, *normalized* consumption is much higher, as current "permanent" income is low relative to future expectations. In *level*, the consumption chosen in each quarter is much more similar

# %%
63 changes: 55 additions & 8 deletions examples/ConsumptionSaving/example_ConsAggShockModel.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
" \"Consumption function at each aggregate market resources-to-labor ratio gridpoint:\"\n",
" )\n",
" m_grid = np.linspace(0, 10, 200)\n",
" AggShockExample.unpackcFunc()\n",
" AggShockExample.unpack('cFunc')\n",
" for M in AggShockExample.Mgrid.tolist():\n",
" mMin = AggShockExample.solution[0].mNrmMin(M)\n",
" c_at_this_M = AggShockExample.cFunc[0](m_grid + mMin, M * np.ones_like(m_grid))\n",
Expand Down Expand Up @@ -123,9 +123,9 @@
" print(\n",
" \"Consumption function at each aggregate market resources gridpoint (in general equilibrium):\"\n",
" )\n",
" AggShockExample.unpackcFunc()\n",
" AggShockExample.unpack('cFunc')\n",
" m_grid = np.linspace(0, 10, 200)\n",
" AggShockExample.unpackcFunc()\n",
" AggShockExample.unpack('cFunc')\n",
" for M in AggShockExample.Mgrid.tolist():\n",
" mMin = AggShockExample.solution[0].mNrmMin(M)\n",
" c_at_this_M = AggShockExample.cFunc[0](m_grid + mMin, M * np.ones_like(m_grid))\n",
Expand Down Expand Up @@ -181,7 +181,7 @@
"\n",
" print(\"Consumption function at each aggregate market resources-to-labor ratio gridpoint (for each macro state):\")\n",
" m_grid = np.linspace(0, 10, 200)\n",
" AggShockMrkvExample.unpackcFunc()\n",
" AggShockMrkvExample.unpack('cFunc')\n",
" for i in range(2):\n",
" for M in AggShockMrkvExample.Mgrid.tolist():\n",
" mMin = AggShockMrkvExample.solution[0].mNrmMin[i](M)\n",
Expand Down Expand Up @@ -214,7 +214,7 @@
"\n",
" print(\"Consumption function at each aggregate market resources-to-labor ratio gridpoint (for each macro state):\")\n",
" m_grid = np.linspace(0, 10, 200)\n",
" AggShockMrkvExample.unpackcFunc()\n",
" AggShockMrkvExample.unpack('cFunc')\n",
" for i in range(2):\n",
" for M in AggShockMrkvExample.Mgrid.tolist():\n",
" mMin = AggShockMrkvExample.solution[0].mNrmMin[i](M)\n",
Expand All @@ -229,9 +229,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"lines_to_next_cell": 2
},
"metadata": {},
"outputs": [],
"source": [
"if solve_krusell_smith:\n",
Expand Down Expand Up @@ -352,8 +350,57 @@
"metadata": {
"jupytext": {
"cell_metadata_filter": "-all",
"formats": "ipynb,py",
"main_language": "python",
"notebook_metadata_filter": "-all"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"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.7.6"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
"autoclose": false,
"autocomplete": true,
"bibliofile": "biblio.bib",
"cite_by": "apalike",
"current_citInitial": 1,
"eqLabelWithNumbers": true,
"eqNumInitial": 1,
"hotkeys": {
"equation": "Ctrl-E",
"itemize": "Ctrl-I"
},
"labels_anchors": false,
"latex_user_defs": false,
"report_style_numbering": false,
"user_envs_cfg": false
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit 5a3ab2a

Please sign in to comment.