-
-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Transition matrices (general, life-cycle) #1286
Conversation
great ideas! @AMonninger and I just came back from NBER ssj workshop and are blown away by their tools. Anything we can do to more tightly integrate with their framework will be very beneficial |
The main idea that the PR works off of is that once you have solved a model, the only things that you need to produce a transition matrix that represents it are:
I have used the State transition equation: Shock-distribution engine: |
Once we have the transition equation, shock distribution, and the grids we want to use for the state-space, we can use the tools that
to produce the transition matrix. It's easy!: |
So, in principle, this means that if you write a |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #1286 +/- ##
==========================================
+ Coverage 72.64% 73.12% +0.48%
==========================================
Files 78 78
Lines 13028 13302 +274
==========================================
+ Hits 9464 9727 +263
- Misses 3564 3575 +11
☔ View full report in Codecov by Sentry. |
You can tell the methods what "states" to keep track off. This is important because:
Here are tests that show that the method can accommodate both versions of the portfolio model. |
This will benefit from some ongoing work:
|
@alanlujan91 has pointed me to some work that might help with the cleaning up of stochastic transition equations using I think what I want might be possible using Lines 1237 to 1238 in 37134b9
|
def state_to_state_trans(self, shocks_next, solution, state, PermGroFac, Rfree): | ||
# Consumption | ||
cNrm = solution.cFunc(state["mNrm"], state["Share"], state["Adjust"]) | ||
# Savings | ||
aNrm = state["mNrm"] - cNrm | ||
# Share | ||
Share_next = solution.ShareFunc(state["mNrm"], state["Share"], state["Adjust"]) | ||
# Shock transition | ||
state_next = post_state_transition( | ||
shocks_next, | ||
state["PLvl"], | ||
aNrm, | ||
Share_next, | ||
PermGroFac, | ||
Rfree, | ||
) | ||
|
||
return state_next |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just updated the methods to use xarrays
and labeled distributions. They now take more expressive transition equations like these.
def test_compare_will_mateo(self): | ||
# No deaths for now in Mateo's method | ||
# but Will's requires LivPrb < 1 | ||
params = deepcopy(dict_harmenberg) | ||
params["LivPrb"] = [0.999] | ||
|
||
# Create and solve agent | ||
agent = IndShockConsumerType(**params) | ||
agent.cycles = 0 | ||
agent.solve() | ||
# Activate harmenberg | ||
agent.neutral_measure = True | ||
agent.update_income_process() | ||
|
||
m_grid = np.linspace(0, 20, 10) | ||
|
||
# Will's methods | ||
agent.define_distribution_grid(dist_mGrid=m_grid) | ||
agent.calc_transition_matrix() | ||
tm_will = agent.tran_matrix | ||
|
||
# Mateo's methods | ||
agent.make_state_grid(mNrmGrid=m_grid) | ||
agent.full_shock_dstns = agent.IncShkDstn | ||
agent.find_transition_matrices() | ||
tm_mateo = agent.trans_mats[0] | ||
|
||
# Compare | ||
self.assertTrue(np.allclose(tm_will, tm_mateo.T, atol=5e-3)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just added a test that compares the tools I am working on with @wdu9 's methods for IndShockConsumerType
.
We are getting the same! (except I am not dealing with death/newborns yet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cool feature that my tools are adding is that, to get this, I only had to define the model's state-to-state transition function.
def state_to_state_trans(self, shocks_next, solution, state, PermGroFac, Rfree):
# Consumption
cNrm = solution.cFunc(state["mNrm"])
# Savings
aNrm = state["mNrm"] - cNrm
# Shock realization
PermGroShk = shocks_next["PermShk"] * PermGroFac
PLvl_next = state["PLvl"] * PermGroShk
mNrm_next = aNrm * Rfree / PermGroShk + shocks_next["TranShk"]
return {
"PLvl": PLvl_next,
"mNrm": mNrm_next,
}
This equation is now pretty expressive and could be used to simulate the model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just added a way to handle newborns and the methods exactly match.
Check that the newborn distn is the same
Just to make sure it's on your radar.... I see you're contributing this as additions to the ConsIndShock and ConsPortfolio models, and that this involves yet another representation of the model equations to be hard coded into the model. Transition matrix methods are awesome, but it would be even more awesome if they were implemented generically, so that model-specific information could be passed to them. What I've been working on in #1296 is a standalone engine for the Monte Carlo simulation that is currently bundled in AgentType. The idea is you pass it the equations and shock definitions you want, and it does the work. Can something similar be done for transition matrices? |
Hey @sbenthall, Yeah, one of the main points of this PR is to have the methods work for any model, receiving their transition equation as a parameter. The method It moves us away from model-speficit methods like Lines 653 to 655 in b123b0e
There is not a current transition equation definition that is used across models in HARK, so I came up with my own placeholder and showed that it can be defined for multiple models easily. Once there is an agreed-upon representation, this code will be easy to modify to take that one and not the one I am using. We agree with the goal of having a consistent representation of models that general methods can receive and work with. I am coding with that in mind. |
To be clear, notice that the main work is being done in But there is no current representation of transitions that is common to But yeah, if you check out the methods, they don't assume much about the model. They work in n-dimensions, you can tell them what subset of states to consider, they work in infinite horizon and life-cycle versions ... they just need a consistent representation for models. I know you are working towards that and I'll be happy to use it once it is agreed upon and merged in. |
Super, @Mv77 . @mnwhite I wonder if you ultimately want this sort of thing to be in I don't mean for this to block the PR, which obviously does a lot of good as is. |
One generic comment on all of this is to remember that we ultimately want to be specifying our models at a higher level of abstraction in which, for example, in the case of mapping a continuous space into a continuous space, the "transition equation" is described symbolically and with abstract information like the range of of the initial states and the domain of the post-states. Using that as an input, a specific solution of the model would then take that generic description and specialize it. For example, in the solution stage if using a transition matrix method, the specialization would need to invoke the transition matrix representation, and specify the details of the transition matrix being constructed (including, for example, the method of assigning probability weights to future gridpoints). Then in the simulation stage we could choose ueither to use the already-computed transition matrix (guaranteeing compatibility with the solution numerics), or to say use a Monte Carlo, or whether to construct a different "simulation" transition matrix than was used at the solution stage. Point is to think ahead about this eventuality as we implement these more specialized things here. |
|
||
# Construct transition matrix from the object above | ||
tmat = np.zeros((mesh_size, mesh_size)) | ||
for i in range(mesh_size): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Vectorize
I believe I have achieved what I wanted out of this PR in terms of scope. I now need to document things and clean up. The PR uses representations of transition equations, which I know are in the works. I've introduced my own placeholder for two models. I'd like to decide if I should wait for the canonical representation of transition equations that I know is in the works, or push towards merging this in with the placeholder representations. @sbenthall @alanlujan91 @llorracc , could you offer any thoughts or updates? |
My opinion is that you should go ahead with the clean up and we should merge this in as soon as it's ready. This PR is good progress, and we can always do the work of aligning it with new transition equation representations later. If you don't mind, I might go to you first to ask you to adapt this code once the new way of doing equations is settled. But in any case, this is important work to get into HARK! |
I agree with Seb, that you should go ahead, and we should merge when it is ready. My point is just to always have people thinking about the longer-term goal so that we do as much as we can to avoid building things in a way that, if we had only done it slightly differently, it would be much easier to upgrade to the new paradigm. |
This PR contains preliminary work that seeks to construct state-transition matrices for any model in HARK, including life-cycle versions.
I am making the raw code public now because I expect to collaborate around these ideas with @wdu9, and in case other people are interested in contributing.
I think this is an important piece of functionality in our goal of communicating with the sequence-space-jacobian methods and tools.
Even though the two examples that I have included are infinite-horizon, the method works for LC parametrizations. It creates a list of transition matrices. One for every age
There are many things to be done:
init_portfolio_lifecyle
param set).And here are the ususal to-dos.