Skip to content

standalone model configuration file with model, approximation, solution, and simulation parameters#1463

Open
sbenthall wants to merge 8 commits intoecon-ark:mainfrom
sbenthall:i857
Open

standalone model configuration file with model, approximation, solution, and simulation parameters#1463
sbenthall wants to merge 8 commits intoecon-ark:mainfrom
sbenthall:i857

Conversation

@sbenthall
Copy link
Contributor

@sbenthall sbenthall commented Jun 22, 2024

The goal of this PR is to implement a working example of a HARK configuration file, in Python, as per #857. (Note the ticket originates from 2020).

Such a configuration should include information:

  • about "true" model dynamics (stages, blocks,etc.), in
  • approximations adopted for computational reasons
  • instructions about how to solve the model
  • parameters for simulating the model (with the given solution)

While this is functionality that's similar to the HARK 0.x models, this PR aims to implement model configuration subject to several constraints:

  • There's a single source of truth for any information about the model's structural equations
  • The configuration is a data structure, not a program, in the sense that it relies only on basic data types without cross-referencing between sections. This requirement is there because the next step after this PR is to implement a parser that will transform a YAML file into this kind of configuration object.
  • As much as possible, it actually operates with other not-model-specific components in HARK.

This work is informed by work in late 2023 on the HARK 2.0 model specification language.

Some tricky parts remaining to implement include:

  • Constructing shocks using mathematical expressions for input parameters from configuration objects DONE
  • Settling on a syntax for aspects of the configuration which are really more like 'workflows' than like model details
  • n/a 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.

@sbenthall
Copy link
Contributor Author

This PR builds on #1427 which should be merged first.

@sbenthall sbenthall added the Status: In Progress In Progress and NOT-OK to be merged. label Jun 25, 2024
@sbenthall sbenthall added Status: Review Needed and removed Status: In Progress In Progress and NOT-OK to be merged. labels Nov 14, 2024
@sbenthall
Copy link
Contributor Author

This is now ready for review again.

Since it is mainly about notation, not functionality, there are no new tests to be added.
A next step is to implement a solver that uses the algorithm in #1438 on the multi-stage problem defined here, with the given approximations.

The API for this solution algorithm is going to be the main constraint on what the workflow syntax looks like.

I'll be happy to write up some documentation for this, but it probably should get eyeballs and an OK from somebody else on the team, before expending effort on those docs.

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 a worked example of a HARK-style model configuration in both Python and YAML, and slightly refactors existing simple model files to make calibration the single source of truth. It also documents the new example in the changelog.

Changes:

  • Adds examples/ModelConfiguration/consumer_example.py, a Python model configuration illustrating agents, calibration, blocks, and approximations.
  • Adds examples/ModelConfiguration/consumer_example.yaml, a YAML counterpart meant to be parsed into a configuration object using the new parser utilities.
  • Refactors perfect_foresight, perfect_foresight_normalized, and fisher models to pull parameters directly from their calibration dicts instead of module-level globals, and updates the changelog to mention the new example.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
examples/ModelConfiguration/consumer_example.yaml Provides a YAML example of a full model configuration (agents, calibration, blocks, approximation, strategy, simulation), intended for use with harklang_loader and the expression/shock constructors.
examples/ModelConfiguration/consumer_example.py Defines a Python model_config dict mirroring the conceptual structure of the YAML configuration and existing HARK.models.consumer blocks.
HARK/models/perfect_foresight_normalized.py Removes global parameter variables, inlines them into calibration, and wires shocks and reward to reference the calibration dictionary directly.
HARK/models/perfect_foresight.py Same calibration cleanup as the normalized version, using calibration["LivPrb"] for the survival Bernoulli shock and the standard CRRA reward signature.
HARK/models/fisher.py Aligns the Fisher example’s CRRA handling with other models by keeping it in calibration and using the (c, CRRA) reward signature.
Documentation/CHANGELOG.md Adds a changelog entry describing the new ModelConfiguration example and its purpose.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +7 to +13
# - DiscFac: 0.96 put this in the solution section
- CRRA: 2.0
- R: 1.03 # note: this can be overriden by the portfolio dynamics
- Rfree: 1.03
- EqP: 0.02
- PermGroFac: 1.01
- TranShkStd: 0.1
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

In this YAML example, calibration is defined as a sequence of one-key mappings (a list of parameters) rather than a mapping from parameter names to values. The Python configuration and the rest of the codebase treat calibration as a dictionary, so this structure will not match the expected shape and will be harder to consume; it should instead be a single mapping with keys like CRRA, R, etc.

Suggested change
# - DiscFac: 0.96 put this in the solution section
- CRRA: 2.0
- R: 1.03 # note: this can be overriden by the portfolio dynamics
- Rfree: 1.03
- EqP: 0.02
- PermGroFac: 1.01
- TranShkStd: 0.1
# DiscFac: 0.96 put this in the solution section
CRRA: 2.0
R: 1.03 # note: this can be overriden by the portfolio dynamics
Rfree: 1.03
EqP: 0.02
PermGroFac: 1.01
TranShkStd: 0.1

Copilot uses AI. Check for mistakes.
std: 0.1

dynamics:
stigma: Control(["a"]),
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Here stigma is set to the literal text Control(["a"]), rather than using the !Control YAML tag as in the c variable above. With the current harklang_loader (see HARK/parser.py:48-67), this value will be treated as a plain string instead of a control token, and the trailing comma also makes it invalid as a mathematical expression; this should be rewritten to use the !Control tag without the extra comma.

Suggested change
stigma: Control(["a"]),
stigma: !Control
inset: a

Copilot uses AI. Check for mistakes.
risky_return:
N: 5
method: gauss-hermite
m: !Linspace # grid over continuous state space
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The !Linspace tag used here is not registered in the current YAML loader (harklang_loader only adds constructors for !Bernoulli, !MeanOneLogNormal, !Lognormal, and !Control in HARK/parser.py:48-65). As written, attempting to load this YAML with harklang_loader will raise a constructor error; either the tag needs a corresponding constructor, or this should be expressed using supported tags/structures.

Suggested change
m: !Linspace # grid over continuous state space
m: # grid over continuous state space

Copilot uses AI. Check for mistakes.
approximation: *approx
discount: 0.98 # A discount factor applied at each tick

simulation: !MonteCarlo
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The !MonteCarlo tag used for the simulation block is not registered in harklang_loader (see HARK/parser.py:48-67), so loading this YAML with that loader will fail with an unknown tag error. To make this example loadable, a constructor for !MonteCarlo needs to be added or the tag should be removed/changed to a supported construct.

Suggested change
simulation: !MonteCarlo
simulation:

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +38
"shocks": {
"live": [Bernoulli, {"p": "LivPrb"}],
"theta": [MeanOneLogNormal, {"sigma": "TranShkStd"}],
},
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

In this Python configuration, the shocks entries are specified as lists like [Bernoulli, {"p": "LivPrb"}], but construct_shocks and DBlock expect either Distribution instances or tuples of (DistributionClass, args_dict) (see HARK/model.py:81-129 and 196-215). Using lists here means this configuration cannot be passed directly into DBlock/construct_shocks as intended; these should be tuples to match the established convention and behavior.

Copilot uses AI. Check for mistakes.

(c) additional parameters needed to solve and simulate the model.

This file shows the model configuraiton in Python.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

"configuraiton" is misspelled in this docstring; this should be corrected to "configuration" for clarity and consistency with the rest of the documentation.

Suggested change
This file shows the model configuraiton in Python.
This file shows the model configuration in Python.

Copilot uses AI. Check for mistakes.

dynamics:
b: k * R / PermGroFac
m: b + theta,
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The value m: b + theta, includes a trailing comma in the mathematical expression. Given that expressions are parsed via SymPy (see HARK/parser.py:39-45), this extra comma will cause a parse error and should be removed so the expression is valid (e.g., b + theta).

Suggested change
m: b + theta,
m: b + theta

Copilot uses AI. Check for mistakes.
- c < m
a: m - c
reward:
u: c ** (1 - CRRA) / (1 - CRRA)}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The reward expression u: c ** (1 - CRRA) / (1 - CRRA)} has an extra closing brace at the end. Because reward expressions are parsed as mathematical text (see HARK/parser.py:39-45 and HARK/model.py:262-264), this stray } will make the YAML example invalid or unparseable; it should be removed so the expression is valid.

Suggested change
u: c ** (1 - CRRA) / (1 - CRRA)}
u: c ** (1 - CRRA) / (1 - CRRA)

Copilot uses AI. Check for mistakes.
- twist: # shorthand fo renaming a variable
m: k
- tick # pass discrete time step
# defaults to infinite horizion problem
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The comment # defaults to infinite horizion problem contains a typo in "horizion"; it should be "horizon" for clarity.

Suggested change
# defaults to infinite horizion problem
# defaults to infinite horizon problem

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,84 @@
from HARK.distribution import Bernoulli, Lognormal, MeanOneLogNormal
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The import path here uses HARK.distribution, but the rest of the codebase (e.g., HARK/models/consumer.py:1) consistently imports from HARK.distributions. Using the singular module name will raise an ImportError; this should be switched to HARK.distributions to match the existing package structure.

Suggested change
from HARK.distribution import Bernoulli, Lognormal, MeanOneLogNormal
from HARK.distributions import Bernoulli, Lognormal, MeanOneLogNormal

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

2 participants