Skip to content
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

replace AgentType.sim_one_period with a generic Monte Carlo simulator that consumes equations #1295

Open
sbenthall opened this issue Jun 28, 2023 · 9 comments

Comments

@sbenthall
Copy link
Contributor

This can more explicitly take in equations, and be removed to a HARK.simulation.monte_carlo module

https://github.com/econ-ark/HARK/blob/master/HARK/core.py#L432-L479

This will help with the whiteboard problem #889

cf. #1292

@sbenthall
Copy link
Contributor Author

The FrameAgentType was an attempt at this. The problem with it, noted by @mnwhite , is that the configuration of the FrameAgentType is too complex.

https://github.com/econ-ark/HARK/blob/master/examples/FrameAgentType/FrameModels.ipynb

Something simpler, like a dictionary of lambdas, would be easier to read and write.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 28, 2023

Here's the off-the-top-of-my-head draft of a format to specify the mechanics of ConsIndShock:

inter = [aNrm, pLvl]
control = [cNrm]
discrete = []
exog = [psi, theta]
param = [gamma, omega, R, J]

dynamics = [
G = gamma * psi,
Rnrm = R / G,
bNrm = Rnrm * aNrm,
mNrm = bNrm + theta,
cNrm = policy(mNrm),
aNrm = mNrm - cNrm,
die(omega),
old = j >= J,
die(old)
]

auxiliary = [
pLvl = G * pLvl,
mLvl = mNrm * pLvl,
cLvl = cNrm * pLvl,
aLvl = aNrm * pLvl,
MPC = policy.der(mNrm)
]

The simulator should be able to take a statement like this and implement it. The inter variables specify what must exist for an agent when it is initialized. The control variables specify the variables that the simulator should expect to exist, probably named like cNrmFunc or stored in policy['cNrm'].

The discrete variables are those that the code should expect to be whole numbers, not continuous values, which might matter for evaluating policy(d, mNrm) where d is discrete.

The exog variables name variables that come from some process exogenous to the agent-- maybe RVs, maybe chosen by someone else, maybe an aggregate. The code just needs to know to expect to be given some way to get or generate things named in exog, which will not be found within dynamics.

Variables named in param are parameters to be pulled from the agent's data, common to a "type". Whether or not each one is time/age-varying is irrelevant for the mechanics of the model. Each instance of an AgentType using this model can specify its own vary list to indicate how parameters should be looked up. In our standard ConsIndShock lifecycle model, omega and gamma would be in vary, while R and J would not.

Note what's not here: state variables. It might be that we need to name the variables that are used as "states" in the sense of "inputs to a policy function", but it might be enough to have them implicit in the dynamics statement.

The statements in dynamics should be self-explanatory. It's a start to finish description of what happens to each agent in one period. The parameter J is the maximum age beyond which an agent can't live.

The contents of auxiliary are optional variables that can be computed along the way, but don't need to be as a required part of simulating the model. Each of these lines would be executed if and only if the accompanying variable is requested in track, with dependencies automatically generated and handled.

There are some additional complications for things like jointly determined variables, but those don't appear in any of our models so far.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 28, 2023

Oh, and j is used to mean "age". There would also be t for absolute time, if needed.

@sbenthall
Copy link
Contributor Author

Ok, I think it's possible to move incrementally in this direction.

The hardest part is the Python object for equations, I think.

I've got a few aesthetic quibbles but let's start getting the functionality in.

I think I can get part of the way there with #1292 and refactoring the Frame code, as discussed.

@llorracc
Copy link
Collaborator

llorracc commented Jun 29, 2023 via email

@sbenthall
Copy link
Contributor Author

dynamics = [
G = gamma * psi,
Rnrm = R / G,
bNrm = Rnrm * aNrm,
mNrm = bNrm + theta,
cNrm = policy(mNrm),
aNrm = mNrm - cNrm,
die(omega),
old = j >= J,
die(old)
]

As we've discussed, one tricky part about this proposal is the syntax for these sorts of 'equations'.
Without a symbolic library, it's hard to do this very cleanly in Python.

This commit is the most lightweight way I can think of doing this without a symbolic library:
d09eb30

It is possible to use inspect.signature to pull out the parameter names and bind them in simulation.
https://docs.python.org/3/library/inspect.html#inspect.signature

@mnwhite
Copy link
Contributor

mnwhite commented Jun 30, 2023 via email

@sbenthall
Copy link
Contributor Author

Got it. Please see #1296 for an example implementation.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 30, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants