Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Documentation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Release Date: TBD
- Expands functionality of Cobb-Douglas aggregator for CRRA utility. [#1363](https://github.com/econ-ark/HARK/pull/1363)
- Adds a new function for using Tauchen's method to approximate an AR1 process. [#1521](https://github.com/econ-ark/HARK/pull/1521)
- Adds additional functionality to the CubicHermiteInterp class, imported from scipy.interpolate. [#1020](https://github.com/econ-ark/HARK/pull/1020/)
- Adds an example, ModelConfiguration, which demonstrates how a consumption saving "true" model, approximations, solution paramaters, and simulation parameters can be defined in one YAML file. [1463](https://github.com/econ-ark/HARK/pull/1463)
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.

"paramaters" is misspelled here; it should be "parameters". While updating this line, consider also adding a # before the PR number so the link formatting matches adjacent entries (e.g., [#1463](...)).

Suggested change
- Adds an example, ModelConfiguration, which demonstrates how a consumption saving "true" model, approximations, solution paramaters, and simulation parameters can be defined in one YAML file. [1463](https://github.com/econ-ark/HARK/pull/1463)
- Adds an example, ModelConfiguration, which demonstrates how a consumption saving "true" model, approximations, solution parameters, and simulation parameters can be defined in one YAML file. [#1463](https://github.com/econ-ark/HARK/pull/1463)

Copilot uses AI. Check for mistakes.

### 0.15.1

Expand Down
8 changes: 2 additions & 6 deletions HARK/models/fisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@

from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
CRRA = (2.0,)

calibration = {
"DiscFac": 0.96,
"CRRA": CRRA,
"CRRA": (2.0,),
"Rfree": 1.03,
"y": [1.0, 1.0],
"BoroCnstArt": None,
Expand All @@ -25,6 +21,6 @@
"c": Control(["m"]),
"a": lambda m, c: m - c,
},
"reward": {"u": lambda c: c ** (1 - CRRA) / (1 - CRRA)},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
}
)
9 changes: 2 additions & 7 deletions HARK/models/perfect_foresight.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
from HARK.distributions import Bernoulli
from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
LivPrb = 0.98

calibration = {
"DiscFac": 0.96,
"CRRA": 2.0,
"Rfree": 1.03,
"LivPrb": LivPrb,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
}
Expand All @@ -19,7 +14,7 @@
**{
"name": "consumption",
"shocks": {
"live": Bernoulli(p=LivPrb),
"live": Bernoulli(p=calibration["LivPrb"]),
},
"dynamics": {
"y": lambda p: p,
Expand Down
14 changes: 4 additions & 10 deletions HARK/models/perfect_foresight_normalized.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
from HARK.distributions import Bernoulli
from HARK.model import Control, DBlock

# This way of distributing parameters across the scope is clunky
# Can be handled better if parsed from a YAML file, probably
# But it would be better to have a more graceful Python version as well.
CRRA = (2.0,)
LivPrb = 0.98

calibration = {
"DiscFac": 0.96,
"CRRA": CRRA,
"CRRA": (2.0,),
"Rfree": 1.03,
"LivPrb": LivPrb,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
}

block = DBlock(
**{
"shocks": {
"live": Bernoulli(p=LivPrb),
"live": Bernoulli(p=calibration["LivPrb"]),
},
"dynamics": {
"p": lambda PermGroFac, p: PermGroFac * p,
Expand All @@ -29,6 +23,6 @@
"c_nrm": Control(["m_nrm"]),
"a_nrm": lambda m_nrm, c_nrm: m_nrm - c_nrm,
},
"reward": {"u": lambda c: c ** (1 - CRRA) / (1 - CRRA)},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
}
)
84 changes: 84 additions & 0 deletions examples/ModelConfiguration/consumer_example.py
Original file line number Diff line number Diff line change
@@ -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.
from HARK.model import Control

"""
This is an example of what a full configuration looks like for:

(a) a true model

(b) approximations made to it to enable efficient computation

(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.

Another file will show a model configuration in YAML, which gets parsed into
a data structure much like this one.
"""

model_config = {
"agents": {"consumer": {"count": 10}},
"calibration": {
"DiscFac": 0.96,
"CRRA": 2.0,
"R": 1.03, # note: this can be overriden by the portfolio dynamics
"Rfree": 1.03,
"EqP": 0.02,
"LivPrb": 0.98,
"PermGroFac": 1.01,
"BoroCnstArt": None,
"TranShkStd": 0.1,
},
"blocks": [
{
"name": "consumption normalized",
"shocks": {
"live": [Bernoulli, {"p": "LivPrb"}],
"theta": [MeanOneLogNormal, {"sigma": "TranShkStd"}],
},
Comment on lines +35 to +38
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.
"dynamics": {
"b": lambda k, R, PermGroFac: k * R / PermGroFac,
"m": lambda b, theta: b + theta,
"c": Control(["m"]),
"a": lambda m, c: m - c,
},
"reward": {"u": lambda c, CRRA: c ** (1 - CRRA) / (1 - CRRA)},
},
{
"name": "portfolio",
"shocks": {
"risky_return": [
Lognormal.from_mean_std,
{"mean": "Rfree + EqP", "std": 0.1},
]
Comment on lines +50 to +53
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.

Similarly, the risky_return shock is defined as a list [Lognormal.from_mean_std, {"mean": "Rfree + EqP", "std": 0.1}]. To be compatible with construct_shocks and the existing block definitions (e.g., HARK/models/consumer.py:59-64), this should be a tuple rather than a list so it is recognized as a constructor-plus-args pair.

Suggested change
"risky_return": [
Lognormal.from_mean_std,
{"mean": "Rfree + EqP", "std": 0.1},
]
"risky_return": (
Lognormal.from_mean_std,
{"mean": "Rfree + EqP", "std": 0.1},
)

Copilot uses AI. Check for mistakes.
},
"dynamics": {
"stigma": Control(["a"]),
"R": lambda stigma, Rfree, risky_return: Rfree
+ (risky_return - Rfree) * stigma,
},
},
{
"name": "tick",
"dynamics": {
"k": lambda a: a,
},
},
],
"approximation": {
"theta": {"N": 5},
"risky_return": {"N": 5},
},
# "workflows": [
# {"action": "solve", "algorithm": "vbi"},
# {
# "action": "simulate",
# "initialization": { # initial values # type: ignore
# "k": Lognormal(-6, 0),
# "R": 1.03,
# },
# "population": 10, # ten agents
# "T": 20, # total number of simulated periods
# },
# ],
}
90 changes: 90 additions & 0 deletions examples/ModelConfiguration/consumer_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
model: &consumer_portfolio
agents:
consumer:
count: 100 # a model with 100 consumers

calibration:
# - 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
Comment on lines +7 to +13
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.

blocks:
- &cons # block definition begins with name of the block. Alias
name: consumption_normalized
agent: consumer
shocks:
theta: !MeanOneLogNormal
sigma: TranShkStd

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: !Control
inset: m
constraints:
- 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.

- &port
name: portfolio
agent: consumer
shocks:
risky_return: !Lognormal
mean: Rfree + EqP
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.
R: Rfree + (risky_return - Rfree) * stigma

structure: # the sequence of blocks
- *cons
- *port
- 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.

approximation: &approx # right syntax?
theta: # to discretize a continuous probability distribution
N : 5
method: equiprobable
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.
start: 0
stop: 10
num: 25


strategy: # these configure constructors/solvers of decision rules
# for model control variables
- &test_policy_profile
model: *consumer_portfolio
method: hard_rule
rules:
- c : m / 2
- stigma : a / (5 + a)

- &approx_best_policy_profile
model: *consumer_portfolio
method: policy_iteration
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.
initialization:
k: !Lognormal
mean: 1
sigma: 0
R: 1.03
approximation: *approx # use the same shock discretization
policy_profile: *approx_best_policy_profile
periods: 100
Loading