Skip to content

[WIP] Class representing discretized transitions#1548

Open
Mv77 wants to merge 2 commits intoecon-ark:mainfrom
Mv77:transitions
Open

[WIP] Class representing discretized transitions#1548
Mv77 wants to merge 2 commits intoecon-ark:mainfrom
Mv77:transitions

Conversation

@Mv77
Copy link
Collaborator

@Mv77 Mv77 commented Apr 29, 2025

I'm making public versions of a few methods that I have used to work for simulations with discretized/matrix transitions.

The idea is to have a simple class that holds all the ingredients needed to, say, find the steady state distribution of an infinite horizon or life-cycle model, or to iterate a distribution forward a single time period.

Ideally, people will use this and make it more efficient and find useful sparse representations and who knows what else.

  • Tests for new functionality/models or Tests to reproduce the bug-fix in code.
  • Updated documentation of features that add new functionality.
  • Update CHANGELOG.md with major/minor changes.

@Mv77
Copy link
Collaborator Author

Mv77 commented Apr 29, 2025

This is a work in progress, do not merge yet. I need to, for example, add tests.

@mnwhite
Copy link
Contributor

mnwhite commented May 15, 2025

I finally had a chance to look at this. Main comments are related to both prongs of find_steady_state_dstn.

For the infinite horizon version, you don't need to loop on _iterate_dstn_forward_ih until convergence. You can just combine your single living_tmat with a "newborn transition matrix" that has newborn_dstn in every row, with weights surv_prob and 1-surv_prob. That's a "master" transition matrix. Then transpose it and use sp.linalg.eig to get k=1 eigenvectors, and normalize it. The largest eigenvector of (the transpose of) a non-singular, non-degenerate Markov matrix is always 1, and the corresponding (normalized) eigenvector is the steady state distribution. For extra speed, cast the transition matrix to sp.sparse.csr_matrix and use sp.sparse.linalg.eigs instead. Note that this method is used in HARK.ConsumptionSaving.ConsNewKeynesianModel.NewKeynesianConsumerType.find_steady_state(), minus the sparse arrays.

For the lifecycle model, your steady state age distribution is wrong. You can't just take the cumulative survival probabilities and normalize them, because that ignores death and replacement. Instead, make a square array A of "age transitions", with two non-zero elements in each row: A_{i,i+1} = LivPrb_i and A_{i,0} = 1-LivPrb_i. Just like above, take the transpose of A, then find the eigenvector associated with its largest eigenvalue and normalize it. That's the steady state age distribution. Your survival-conditional state distributions are correct. See L168-202 of estimation.py in the DistributionOfWealthMPC REMARK for where this was done in cstwMPC, but note that when I wrote the function there, I didn't know that the largest eigenvalue is always 1 and/or eig wasn't necessarily sorted back then.

EDIT: Ignore that last paragraph, it's wrong.

@mnwhite
Copy link
Contributor

mnwhite commented May 15, 2025

Addendum to the above: The lifecycle method assumes that you want a constant population, with newborns exactly replacing decedents. If you instead want a constant growth rate of the population, the math is slightly different (but you can probably work it out).

@mnwhite
Copy link
Contributor

mnwhite commented May 15, 2025

Hit pause on my comment about the steady state age distribution. Normalized cumulative survival probabilities and the first normalized eigenvector might be equivalent. I'm on a train right now and can't check.

@mnwhite
Copy link
Contributor

mnwhite commented May 15, 2025

Yeah nevermind, the methods are equivalent.

@alanlujan91 alanlujan91 requested a review from Copilot June 18, 2025 20:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces the DiscreteTransitions class for simulating population transitions in discretized state spaces for both life-cycle and infinite-horizon models. Key changes include the addition of a new dataclass with methods to iterate distributions forward, calculate conditional age distributions, and compute steady-state distributions.

)
else:
return _iterate_dstn_forward_ih(
dstn_init[0], self.living_tmat[0], self.surv_prob[0], self.newborn_dstn
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In infinite-horizon mode, the properties 'self.living_tmat' and 'self.surv_prob' are referenced, but the class defines 'living_tmats' and 'surv_probs'. Please update the variable names to ensure consistency.

Suggested change
dstn_init[0], self.living_tmat[0], self.surv_prob[0], self.newborn_dstn
dstn_init[0], self.living_tmats[0], self.surv_probs[0], self.newborn_dstn

Copilot uses AI. Check for mistakes.
The class assumes that:
- Death is exogenous and independent of every state.
- Agents that die are replaced by newborns.
- Newborns draw their state from a distribution that is constatn over time.
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the typo 'constatn' to 'constant'.

Suggested change
- Newborns draw their state from a distribution that is constatn over time.
- Newborns draw their state from a distribution that is constant over time.

Copilot uses AI. Check for mistakes.
@mnwhite mnwhite moved this to In progress in Issues & PRs Jan 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

3 participants