diff --git a/docs/source/background/literature.rst b/docs/source/background/literature.rst index bad74e05..c410ce2f 100644 --- a/docs/source/background/literature.rst +++ b/docs/source/background/literature.rst @@ -10,3 +10,5 @@ Below you find related literature to provide a background of the `dc-egm` algori - Iskhakov, Jørgensen, Rust, & Schjerning (2017). `The Endogenous Grid Method for Discrete-Continuous Dynamic Choice Models with (or without) Taste Shocks `_. *Quantitative Economics* - Loretti I. Dobrescu & Akshay Shanker (2022). `Fast Upper-Envelope Scan for Discrete-Continuous Dynamic Programming `_. + +- Fedor Iskhakov & Michael Keane (2021). `Effects of Taxes and Safety Net Pensions on Life-Cycle Labor Supply, Savings and Human Capital: The Case of Australia `_. *Journal of Econometrics*. See :ref:`replications` for a `dcegm` replication. diff --git a/docs/source/index.rst b/docs/source/index.rst index e0e6874e..6c224b5d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -37,6 +37,14 @@ Check out our :ref:`guides` to find information on getting sta +.. toctree:: + :maxdepth: 1 + :caption: Replications + :hidden: + + replications/index + + .. toctree:: :maxdepth: 2 :caption: Background diff --git a/docs/source/replications/index.rst b/docs/source/replications/index.rst new file mode 100644 index 00000000..8abe8a50 --- /dev/null +++ b/docs/source/replications/index.rst @@ -0,0 +1,22 @@ +.. _replications: + +Replications +============ + +This section walks through published studies re-implemented with `dcegm`. Unlike +the :doc:`guides <../guides/practitioner_guide>`, which teach the interface +through small worked examples, replications show the package applied to a +full-scale, published life-cycle model. + +A replication in these docs is a **calibrated structural replication**: we +implement the paper's model faithfully and use its published parameter +estimates, but we do not re-run the paper's own estimation procedure (which +typically requires restricted-access microdata we don't have). The goal is +to demonstrate that `dcegm` reproduces the paper's *mechanism* and +*qualitative* implications, not to match its estimated moments point for +point. Each notebook states its simplifications explicitly. + +.. toctree:: + :maxdepth: 1 + + iskhakov_keane_2021.ipynb diff --git a/docs/source/replications/iskhakov_keane_2021.ipynb b/docs/source/replications/iskhakov_keane_2021.ipynb new file mode 100644 index 00000000..a48cb66e --- /dev/null +++ b/docs/source/replications/iskhakov_keane_2021.ipynb @@ -0,0 +1,1343 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a53d6dec", + "metadata": {}, + "source": [ + "# Replicating Iskhakov & Keane (2021) with `dcegm`\n", + "\n", + "This notebook builds the life-cycle labor supply model from\n", + "Iskhakov, F. & Keane, M. (2021), *\"Effects of Taxes and Safety Net Pensions\n", + "on Life-Cycle Labor Supply, Savings and Human Capital: The Case of\n", + "Australia\"*, Journal of Econometrics, using `dcegm`. It is a good first\n", + "replication example for these docs because the package's continuous\n", + "experience state was built with this paper in mind (see\n", + "[Limitations](../background/limitations.rst)).\n", + "\n", + "**We replicate the model, not the estimation.** Throughout this notebook:\n", + "\n", + "- We plug in the paper's **published point estimates** (Tables 5-7 of the\n", + " supplementary material) directly into the model. We do **not** re-run the\n", + " paper's method-of-simulated-moments estimation, which requires the\n", + " restricted-access HILDA microdata we don't have.\n", + "- Every number that appears in a `dcegm` object here — every $\\beta$, $\\eta$,\n", + " tax bracket, pension parameter — is copied from the paper's own tables.\n", + " Nothing in this notebook is fit to data.\n", + "- Consequently, don't expect the simulated *levels* (aggregate wealth,\n", + " average hours) to reproduce the paper's Figures 5-9 point for point — those\n", + " are targets of an estimation we are not running. What we *do* expect to\n", + " reproduce is the model's **mechanism**: the kinked policy functions DC-EGM\n", + " is built to solve, the qualitative shape of life-cycle profiles, the\n", + " direction of the paper's policy experiment, and — new in this version — a\n", + " genuine **quantitative** check against a structural object the paper\n", + " reports (Section 5).\n", + "- We fix the **post-2010 Age Pension regime** throughout, rather than\n", + " tracking the calendar-time policy changes the paper's estimation sample\n", + " (2001-2016) passed through, and we truncate the horizon at the\n", + " **compulsory retirement age of 85** instead of 100 (see Section 4 for what\n", + " this changes). Both are simplifications for tractability, not attempts to\n", + " match the paper's fit.\n", + "\n", + "All calibration values live in [`params.yaml`](params.yaml) next to this\n", + "notebook, transcribed directly from the paper's tables — see Section 1.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "84235d81", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:24.641941Z", + "iopub.status.busy": "2026-08-29T15:06:24.641727Z", + "iopub.status.idle": "2026-08-29T15:06:26.380936Z", + "shell.execute_reply": "2026-08-29T15:06:26.380387Z" + } + }, + "outputs": [], + "source": [ + "import yaml\n", + "import jax\n", + "import jax.numpy as jnp\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import dcegm\n", + "\n", + "jax.config.update(\"jax_enable_x64\", True)\n", + "plt.rcParams[\"figure.dpi\"] = 55 # keep this notebook's committed size small" + ] + }, + { + "cell_type": "markdown", + "id": "899d6893", + "metadata": {}, + "source": [ + "## 1. Calibration\n", + "\n", + "Hours are discrete, $H = \\{0, 1000, 2000, 2250, 2500, 3000\\}$ (eq. 1). All\n", + "monetary values are in \\$1000 AUD, matching the paper.\n", + "\n", + "`params.yaml` transcribes Tables 5 (preferences), 6 (human capital) and 7\n", + "(misc.) of the supplementary material, plus the tax function (eq. 27 of the\n", + "main paper) and the pension and survival functions (eqs. 2-3 of the\n", + "supplement) — every number in it is a value **published in the paper**, not\n", + "something we chose or fit. `build_params`/`build_model_specs` below just\n", + "reshape that file into the flat dictionaries `dcegm` expects; education\n", + "groups are indexed 0=dropout, 1=highschool, 2=college throughout.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7307227b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:26.382371Z", + "iopub.status.busy": "2026-08-29T15:06:26.382256Z", + "iopub.status.idle": "2026-08-29T15:06:26.392163Z", + "shell.execute_reply": "2026-08-29T15:06:26.391652Z" + } + }, + "outputs": [], + "source": [ + "with open(\"params.yaml\") as f:\n", + " CAL = yaml.safe_load(f)\n", + "\n", + "EDUCATION_GROUPS = CAL[\"education_groups\"]\n", + "COLLEGE_INDEX = EDUCATION_GROUPS.index(\"college\")\n", + "HOURS_BY_CHOICE = jnp.array(CAL[\"hours_by_choice\"])\n", + "T0 = CAL[\"t0\"]\n", + "T_RETIRE = CAL[\"t_retire\"]\n", + "# One dummy period beyond T_RETIRE -- see Section 3 for why.\n", + "N_PERIODS = T_RETIRE - T0 + 2\n", + "LAST_WORKING_PERIOD = T_RETIRE - T0\n", + "COLLEGE_START_PERIOD = CAL[\"college_start_age\"] - T0\n", + "\n", + "\n", + "def _edu_array(d):\n", + " # Turn a {education_name: value} mapping from the yaml into an array\n", + " # ordered to match EDUCATION_GROUPS, so it can be indexed by the\n", + " # `education` state directly (jnp.array(...)[education]).\n", + " return jnp.array([d[e] for e in EDUCATION_GROUPS])\n", + "\n", + "\n", + "def build_params():\n", + " pref, hc, misc = CAL[\"preferences\"], CAL[\"human_capital\"], CAL[\"misc\"]\n", + " p = {\n", + " \"taste_shock_scale\": pref[\"taste_shock_scale\"],\n", + " \"zeta\": pref[\"zeta\"],\n", + " \"gamma\": jnp.array(pref[\"gamma\"]),\n", + " \"kappa_1\": pref[\"kappa_1\"],\n", + " \"kappa_2\": pref[\"kappa_2\"],\n", + " \"kappa_3\": pref[\"kappa_3\"],\n", + " \"xi\": pref[\"xi\"],\n", + " \"b_scale\": pref[\"b_scale\"],\n", + " \"beta_by_education\": _edu_array(pref[\"beta_by_education\"]),\n", + " \"eta0_edu\": _edu_array(hc[\"eta0_by_education\"]),\n", + " \"eta0_high_type\": hc[\"eta0_high_type\"],\n", + " \"eta1_edu\": _edu_array(hc[\"eta1_by_education\"]),\n", + " \"eta2_edu\": _edu_array(hc[\"eta2_by_education\"]),\n", + " \"eta3\": hc[\"eta3\"],\n", + " \"eta4\": hc[\"eta4\"],\n", + " \"sigma0\": misc[\"sigma0\"],\n", + " \"sigma1\": misc[\"sigma1\"],\n", + " \"tr\": misc[\"tr\"],\n", + " \"rho_super_edu\": _edu_array(misc[\"rho_super_by_education\"]),\n", + " }\n", + " p.update(CAL[\"tax\"])\n", + " p.update(CAL[\"pension\"])\n", + " p.update(CAL[\"survival\"])\n", + " p.update(CAL[\"fixed\"])\n", + " p[\"income_shock_mean\"] = 0.0\n", + " p[\"income_shock_std\"] = 1.0\n", + " p[\"pension_scale\"] = 1.0 # policy-experiment toggle, Section 6\n", + " p[\"wage_scale\"] = 1.0 # elasticity-experiment toggle, Section 7\n", + " return p\n", + "\n", + "\n", + "def build_model_specs():\n", + " return {\n", + " \"t0\": T0,\n", + " \"n_periods\": N_PERIODS,\n", + " \"last_working_period\": LAST_WORKING_PERIOD,\n", + " \"hours_by_choice\": HOURS_BY_CHOICE,\n", + " \"n_choices\": len(HOURS_BY_CHOICE),\n", + " \"college_index\": COLLEGE_INDEX,\n", + " \"college_start_period\": COLLEGE_START_PERIOD,\n", + " }" + ] + }, + { + "cell_type": "markdown", + "id": "3c2c3aca", + "metadata": {}, + "source": [ + "## 2. Preferences and the budget constraint\n", + "\n", + "**Utility (eq. 7-10).** Flow utility is CRRA consumption minus a\n", + "disutility of work that depends on the discrete hours level, age, and the\n", + "unobserved (\"high\"/\"low\") type:\n", + "\n", + "$$u(c_t) = \\frac{c_t^{1-\\zeta}-1}{1-\\zeta}, \\qquad\n", + "v_t(h_t) = \\mathbb{1}\\{h_t>0\\}\\,\\kappa_{\\text{type}}\\,\\kappa_{\\text{age}}(t)\\,\\gamma(h_t).$$\n", + "\n", + "**Bequest (eq. 11-12).** dcegm's terminal-period solver assumes consumption\n", + "equals the full wealth at that state, so we implement the bequest function\n", + "directly as the *terminal-period* utility, applied to the full terminal\n", + "wealth $b = M$:\n", + "\n", + "$$B(b) = b_{scale}\\frac{(b+a_0)^{1-\\xi}-a_0^{1-\\xi}}{1-\\xi}.$$\n", + "\n", + "Eq. (12) of the paper leaves this term **undiscounted**\n", + "($(1-\\delta_t)B(\\cdot)$, no $\\beta$), but dcegm automatically discounts\n", + "*every* value returned by the terminal-period solver by one more $\\beta$\n", + "when the calling period aggregates it. We cancel this by dividing the\n", + "bequest utility (and its marginal utility) by education's $\\beta$\n", + "unconditionally at the dummy terminal period, matching eq. (12) for a death\n", + "at any age, and treating a natural end-of-horizon the same way (the dummy\n", + "period has no economic content of its own either way).\n", + "\n", + "$M$ here is also now the paper's exact $b_t = M_t - c_t$ (eq. 11): the\n", + "budget constraint below returns the *raw* end-of-previous-period assets,\n", + "with no interest, wages, pension or superannuation, for **any** state at\n", + "the dummy period — reached by death at any age (routed there by\n", + "`sparsity_condition`'s proxy, Section 3) or by surviving naturally to 86 —\n", + "rather than the ordinary next-period wealth.\n", + "\n", + "*Numerical caveat.* This period-conditional budget constraint is more\n", + "fragile than the rest of the model: a small share of simulated wealth\n", + "trajectories land in regions where interpolation across this discontinuity\n", + "is unstable and produce implausible outliers, the same failure mode we\n", + "first saw in the Section 6 policy experiment. We did not fully root-cause\n", + "this — it did not resolve across several different ways of structuring the\n", + "branch, which suggests something in how dcegm's terminal-period solver\n", + "handles a discontinuous incoming-wealth mapping, worth a dedicated\n", + "dcegm-level investigation rather than a notebook-level fix. Every profile\n", + "below is reported as a **median** (or, in Section 7, at representative\n", + "non-extreme states) specifically because it is robust to this.\n", + "\n", + "**Budget constraint (eqs. 2, 4-6, 27).** dcegm calls the budget constraint\n", + "with *this* (child) state's own fields — its own `period`, `lagged_choice`\n", + "(the choice made last period, which earned this period's income) and\n", + "`experience` (already updated for this period, see Section 3). Human\n", + "capital, and thus the wage, is evaluated at the state's own\n", + "`(period, experience)`, following the DC-EGM algorithm's steps 2(a)-(b) in\n", + "the paper (compute $E_{t+1}$, *then* $K_{t+1}$ from it) rather than the\n", + "closed-form subscript in eq. (4). Tax, the means-tested Age Pension, the\n", + "one-off superannuation lump sum at 65, and the parental transfer up to age\n", + "23 are all applied to the resulting income stream. `params[\"wage_scale\"]`\n", + "multiplies the wage level uniformly; it is 1.0 everywhere except the\n", + "Section 7 elasticity experiment.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f695f023", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:26.393306Z", + "iopub.status.busy": "2026-08-29T15:06:26.393242Z", + "iopub.status.idle": "2026-08-29T15:06:26.396251Z", + "shell.execute_reply": "2026-08-29T15:06:26.395930Z" + } + }, + "outputs": [], + "source": [ + "def bequest_utility(wealth, education, params):\n", + " # Eq. (11): value of the bequest itself, b_scale*((b+a0)^(1-xi)-a0^(1-xi))/(1-xi).\n", + " # dcegm discounts every terminal-period value by one more factor of beta\n", + " # when the calling (earlier) period aggregates it, but eq. (12) leaves\n", + " # the bequest term (1-delta_t)*B(.) undiscounted. The dummy period\n", + " # (Section 3) has no economic content of its own -- everyone who\n", + " # reaches it, whether by dying at any age (via sparsity_condition's\n", + " # proxy) or by surviving naturally to age 86, is just settling the\n", + " # estate with whatever is left, so we don't distinguish by `survival`\n", + " # here: dividing by beta unconditionally cancels dcegm's extra\n", + " # discounting for both cases alike.\n", + " a0 = params[\"credit_constraint\"]\n", + " xi = params[\"xi\"]\n", + " beta = params[\"beta_by_education\"][education]\n", + " bequest_value = ((wealth + a0) ** (1 - xi) - a0 ** (1 - xi)) / (1 - xi)\n", + " return params[\"b_scale\"] * bequest_value / beta\n", + "\n", + "\n", + "def bequest_marginal_utility(wealth, education, params):\n", + " a0 = params[\"credit_constraint\"]\n", + " xi = params[\"xi\"]\n", + " beta = params[\"beta_by_education\"][education]\n", + " return params[\"b_scale\"] * (wealth + a0) ** (-xi) / beta\n", + "\n", + "\n", + "def utility(\n", + " consumption, choice, period, high_type, survival, education, params, model_specs\n", + "):\n", + " zeta = params[\"zeta\"]\n", + " consumption_utility = (consumption ** (1 - zeta) - 1) / (1 - zeta)\n", + "\n", + " age = model_specs[\"t0\"] + period\n", + " works = choice > 0\n", + " kappa_type = 1.0 + params[\"kappa_1\"] * (high_type == 0)\n", + " kappa_age = (\n", + " 1.0\n", + " + params[\"kappa_2\"] * (age - 40.0) ** 2 * (age > 40)\n", + " + params[\"kappa_3\"] * (age - 25.0) * (age < 25)\n", + " )\n", + " disutility = works * kappa_type * kappa_age * params[\"gamma\"][choice]\n", + " utility_alive = consumption_utility - disutility\n", + "\n", + " # Defensive: sparsity_condition's proxy should mean this state is never\n", + " # actually reached with survival==0 (that always routes to the dummy\n", + " # terminal period instead, using bequest_utility above), but we check\n", + " # here too rather than assume `consumption` is meaningful in that case.\n", + " utility_dead = bequest_utility(\n", + " wealth=consumption, education=education, params=params\n", + " )\n", + " return jnp.where(survival == 0, utility_dead, utility_alive)\n", + "\n", + "\n", + "def marginal_utility(\n", + " consumption, choice, period, high_type, survival, education, params, model_specs\n", + "):\n", + " marginal_utility_alive = consumption ** (-params[\"zeta\"])\n", + " marginal_utility_dead = bequest_marginal_utility(\n", + " wealth=consumption, education=education, params=params\n", + " )\n", + " return jnp.where(survival == 0, marginal_utility_dead, marginal_utility_alive)\n", + "\n", + "\n", + "def inverse_marginal_utility(\n", + " marginal_utility, choice, period, high_type, params, model_specs\n", + "):\n", + " return marginal_utility ** (-1.0 / params[\"zeta\"])\n", + "\n", + "\n", + "def create_utility_function_dict():\n", + " return {\n", + " \"utility\": utility,\n", + " \"marginal_utility\": marginal_utility,\n", + " \"inverse_marginal_utility\": inverse_marginal_utility,\n", + " }\n", + "\n", + "\n", + "def create_final_period_utility_function_dict():\n", + " return {\"utility\": bequest_utility, \"marginal_utility\": bequest_marginal_utility}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0538a32d", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:26.397358Z", + "iopub.status.busy": "2026-08-29T15:06:26.397293Z", + "iopub.status.idle": "2026-08-29T15:06:26.400446Z", + "shell.execute_reply": "2026-08-29T15:06:26.400100Z" + } + }, + "outputs": [], + "source": [ + "def budget_constraint(\n", + " period,\n", + " lagged_choice,\n", + " experience,\n", + " high_type,\n", + " education,\n", + " survival,\n", + " asset_end_of_previous_period,\n", + " income_shock_previous_period,\n", + " params,\n", + " model_specs,\n", + "):\n", + " hours_by_choice = model_specs[\"hours_by_choice\"]\n", + " hours_prev = hours_by_choice[lagged_choice]\n", + " age = model_specs[\"t0\"] + period\n", + "\n", + " # --- human capital & wage, eq. (2) & (4) ---\n", + " cum_exp_years = period * experience\n", + " log_hc = (\n", + " params[\"eta0_edu\"][education]\n", + " + params[\"eta0_high_type\"] * high_type\n", + " + params[\"eta1_edu\"][education] * cum_exp_years\n", + " + params[\"eta2_edu\"][education] * cum_exp_years**2\n", + " + params[\"eta3\"] * period\n", + " + params[\"eta4\"] * period**2\n", + " )\n", + " sigma_age = params[\"sigma0\"] + params[\"sigma1\"] * age\n", + " wage_per_hour = params[\"wage_scale\"] * jnp.exp(\n", + " log_hc + sigma_age * income_shock_previous_period\n", + " )\n", + " labor_income = hours_prev * wage_per_hour / 1000.0 # dollars -> $1000s\n", + "\n", + " # --- income tax, eq. (27) ---\n", + " # NB: we use the continuity-preserving constant rate1*(thld2-thld1); the\n", + " # printed equation's constant (rate1*thld1) creates a small downward\n", + " # jump in tax liability at the second threshold, see notebook.\n", + " tax = jnp.where(\n", + " labor_income < params[\"thld1\"],\n", + " 0.0,\n", + " jnp.where(\n", + " labor_income < params[\"thld2\"],\n", + " params[\"rate1\"] * (labor_income - params[\"thld1\"]),\n", + " params[\"rate2\"] * (labor_income - params[\"thld2\"])\n", + " + params[\"rate1\"] * (params[\"thld2\"] - params[\"thld1\"]),\n", + " ),\n", + " )\n", + " after_tax_labor_income = labor_income - tax\n", + "\n", + " # --- Age Pension, supplementary eq. (3) ---\n", + " wealth_for_test = asset_end_of_previous_period * (1 + params[\"interest_rate\"])\n", + " means_test = jnp.maximum(\n", + " jnp.maximum(\n", + " params[\"income_taper\"] * labor_income,\n", + " params[\"asset_taper\"] * (wealth_for_test - params[\"asset_threshold\"]),\n", + " ),\n", + " 0.0,\n", + " )\n", + " pension = jnp.maximum(params[\"benefit_max\"] - means_test, 0.0)\n", + " pension = jnp.where(age >= params[\"pension_age\"], pension, 0.0)\n", + " pension = pension * params[\"pension_scale\"]\n", + "\n", + " # --- superannuation lump sum, eq. (6), paid once at age 65 ---\n", + " human_capital_level = params[\"wage_scale\"] * jnp.exp(log_hc)\n", + " super_payment = jnp.where(\n", + " age == params[\"superannuation_age\"],\n", + " params[\"rho_super_edu\"][education] * human_capital_level,\n", + " 0.0,\n", + " )\n", + "\n", + " # --- parental transfer, ages t0 to 23 ---\n", + " transfer = jnp.where(age <= 23, params[\"tr\"], 0.0)\n", + "\n", + " wealth_begin_of_period_normal = (\n", + " asset_end_of_previous_period * (1 + params[\"interest_rate\"])\n", + " + after_tax_labor_income\n", + " + pension\n", + " + super_payment\n", + " + transfer\n", + " )\n", + " wealth_begin_of_period_normal = jnp.maximum(\n", + " wealth_begin_of_period_normal, params[\"consumption_floor\"]\n", + " )\n", + "\n", + " # Eq. (11): the bequest is b_t = M_t - c_t -- raw unconsumed savings,\n", + " # no next-period interest or income. sparsity_condition's proxy already\n", + " # redirects every death, at any age, to the canonical dummy period\n", + " # (Section 3), so checking `period` alone should be sufficient -- but we\n", + " # check `survival == 0` too, redundantly, so this state's own fields are\n", + " # sufficient to identify it as a bequest state even if some (period,\n", + " # survival) combination were ever reachable outside that proxy. Not\n", + " # floored at consumption_floor (that floor is meant for positive\n", + " # consumption): the assets grid's own lower bound is exactly -a0, and\n", + " # at wealth == -a0 the bequest marginal utility (wealth+a0)^(-xi)\n", + " # divides by zero, so we use a tiny margin above -a0 instead.\n", + " wealth_begin_of_period_bequest = jnp.maximum(\n", + " asset_end_of_previous_period, -params[\"credit_constraint\"] + 1e-6\n", + " )\n", + "\n", + " is_bequest_period = (period >= model_specs[\"n_periods\"] - 1) | (survival == 0)\n", + " return jnp.where(\n", + " is_bequest_period, wealth_begin_of_period_bequest, wealth_begin_of_period_normal\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "1e8623ba", + "metadata": {}, + "source": [ + "## 3. State space, timing, and one solve for everyone\n", + "\n", + "- **Experience** $E_t \\in [0,1]$ is a *continuous* state (eq. 3), the\n", + " recursive average of hours worked so far.\n", + "- **Education** (3 groups) and **unobserved type** (\"high\"/\"low\", Table 7)\n", + " are time-invariant `deterministic_states`. College students are\n", + " choice-restricted to $h=0$ (in school) until age 23 via\n", + " `state_specific_choice_set`.\n", + "- **Discount factor.** Education groups have different $\\beta$ (Table 5:\n", + " 0.968/0.967/0.970). Rather than solving three separate models with a\n", + " pooled/approximate $\\beta$, we use `dcegm`'s `discount_factor_per_state`\n", + " hook (`shock_functions={\"discount_factor_per_state\": ...}`) to read the\n", + " *exact* $\\beta$ for each state's own `education` value, inside a single\n", + " `setup_model`/`solve()` call spanning all three education groups and both\n", + " types at once. This is a genuinely exact replication of the paper's\n", + " education-specific discount factors, not an approximation.\n", + "- **Mortality and the bequest motive.** `survival` is a stochastic state\n", + " with age-varying probability $\\delta_t$ (eq. 28); any realized death is\n", + " routed by `sparsity_condition` to a single canonical terminal state, then\n", + " solved with the bequest function from Section 2 (dcegm's standard survival\n", + " pattern, see `tests/sparse_death`) — see Section 2 for how we cancel\n", + " dcegm's automatic discounting on that branch to match eq. (12) exactly,\n", + " and for the one part of the bequest we could not fix.\n", + "- **Compulsory retirement, and a dummy terminal period.** Only $h=0$ is\n", + " feasible from age 85 onward. We give the model **one extra period beyond\n", + " age 85** (`N_PERIODS = T_RETIRE - T0 + 2`) purely so dcegm's terminal-period\n", + " solver — which hardcodes consumption equal to full wealth, and which we\n", + " override with the bequest function — lands on that *dummy* age-86 period\n", + " instead of on age 85 itself. Age 85 then becomes an ordinary EGM-solved\n", + " period: agents choose $c_{85}$ via the normal Euler equation, trading off\n", + " $u(c_{85})$ against $\\beta \\cdot B(M_{86})$, which is exactly eq. (21-22)'s\n", + " consumption/bequest trade-off — rather than the 100%-bequest corner\n", + " solution a literal terminal age 85 would force. This costs nothing beyond\n", + " one extra (trivial, single-choice) period to solve.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2e0eab28", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:26.401485Z", + "iopub.status.busy": "2026-08-29T15:06:26.401422Z", + "iopub.status.idle": "2026-08-29T15:06:26.404361Z", + "shell.execute_reply": "2026-08-29T15:06:26.404006Z" + } + }, + "outputs": [], + "source": [ + "def state_specific_choice_set(period, education, model_specs):\n", + " # Compulsory retirement at T_RETIRE, one period before dcegm's own\n", + " # (dummy) terminal period -- see the discussion above.\n", + " if period >= model_specs[\"last_working_period\"]:\n", + " return [0]\n", + " if (education == model_specs[\"college_index\"]) and (\n", + " period < model_specs[\"college_start_period\"]\n", + " ):\n", + " return [0]\n", + " return list(range(model_specs[\"n_choices\"]))\n", + "\n", + "\n", + "def next_period_deterministic_state(period, choice, high_type, education):\n", + " return {\n", + " \"period\": period + 1,\n", + " \"lagged_choice\": choice,\n", + " \"high_type\": high_type,\n", + " \"education\": education,\n", + " }\n", + "\n", + "\n", + "def next_period_continuous_state(period, lagged_choice, experience, model_specs):\n", + " hours_by_choice = model_specs[\"hours_by_choice\"]\n", + " hmax = hours_by_choice[-1]\n", + " frac_worked = hours_by_choice[lagged_choice] / hmax\n", + " return {\n", + " \"experience\": jnp.where(\n", + " period == 1,\n", + " frac_worked,\n", + " (1.0 / period) * ((period - 1) * experience + frac_worked),\n", + " )\n", + " }\n", + "\n", + "\n", + "def sparsity_condition(\n", + " period, lagged_choice, high_type, education, survival, model_specs\n", + "):\n", + " # College students cannot have worked before their career starts, so any\n", + " # state with a nonzero lagged_choice while still \"in school\" is unreachable.\n", + " if (\n", + " (education == model_specs[\"college_index\"])\n", + " and (period <= model_specs[\"college_start_period\"])\n", + " and (lagged_choice != 0)\n", + " ):\n", + " return False\n", + "\n", + " last_period = model_specs[\"n_periods\"] - 1\n", + " period_out = last_period if survival == 0 else period\n", + " return {\n", + " \"period\": period_out,\n", + " \"lagged_choice\": lagged_choice,\n", + " \"high_type\": high_type,\n", + " \"education\": education,\n", + " \"survival\": survival,\n", + " }\n", + "\n", + "\n", + "def create_state_space_function_dict():\n", + " return {\n", + " \"state_specific_choice_set\": state_specific_choice_set,\n", + " \"next_period_deterministic_state\": next_period_deterministic_state,\n", + " \"next_period_continuous_state\": next_period_continuous_state,\n", + " \"sparsity_condition\": sparsity_condition,\n", + " }\n", + "\n", + "\n", + "def prob_survival(period, params, model_specs):\n", + " # Eq. (2)/(28): age-dependent survival probability delta_t.\n", + " age = model_specs[\"t0\"] + period\n", + " delta = jnp.where(\n", + " age < params[\"age_threshold\"],\n", + " 1.0,\n", + " 1.0\n", + " - params[\"a\"] * (jnp.exp(params[\"b\"] * (age - params[\"age_threshold\"])) - 1.0),\n", + " )\n", + " delta = jnp.clip(delta, 0.0, 1.0)\n", + " return jnp.array([1.0 - delta, delta]) # [P(survival=0), P(survival=1)]\n", + "\n", + "\n", + "def discount_factor_per_state(education, params):\n", + " # Exact education-specific beta (Table 5), read per state -- see the\n", + " # dcegm feature note above.\n", + " return params[\"beta_by_education\"][education]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b0fd64e6", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:26.405389Z", + "iopub.status.busy": "2026-08-29T15:06:26.405332Z", + "iopub.status.idle": "2026-08-29T15:06:34.845859Z", + "shell.execute_reply": "2026-08-29T15:06:34.845293Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting state space creation\n", + "State space created.\n", + "\n", + "Starting state-choice space creation and child state mapping.\n", + "State, state-choice and child state mapping created.\n", + "\n", + "Start creating batches for the model.\n", + "The batch size of the backwards induction is 216\n", + "The batch size of the backwards induction is 211\n", + "The batch size of the backwards induction is 206\n", + "The batch size of the backwards induction is 201\n", + "The batch size of the backwards induction is 196\n", + "The batch size of the backwards induction is 192\n", + "The batch size of the backwards induction is 188\n", + "The batch size of the backwards induction is 184\n", + "The batch size of the backwards induction is 180\n", + "The batch size of the backwards induction is 176\n", + "The batch size of the backwards induction is 172\n", + "The batch size of the backwards induction is 168\n", + "The batch size of the backwards induction is 164\n", + "The batch size of the backwards induction is 160\n", + "The batch size of the backwards induction is 156\n", + "The batch size of the backwards induction is 152\n", + "The batch size of the backwards induction is 148\n", + "The batch size of the backwards induction is 145\n", + "The batch size of the backwards induction is 142\n", + "The batch size of the backwards induction is 139\n", + "The batch size of the backwards induction is 136\n", + "The batch size of the backwards induction is 133\n", + "The batch size of the backwards induction is 130\n", + "The batch size of the backwards induction is 127\n", + "The batch size of the backwards induction is 124\n", + "The batch size of the backwards induction is 121\n", + "Model setup complete.\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/maxblesch/Uni/dcegm/dcegm/src/dcegm/pre_processing/model_structure/state_choice_space.py:298: UserWarning: \n", + "\n", + "\n", + "\n", + " Some states are not child states of any state-choice combination or stochastic transition. Please revisit the sparsity condition. \n", + " \n", + "An example of a state that is not a child state is: \n", + " \n", + "{'period': np.uint8(67), 'lagged_choice': np.uint8(1), 'high_type': np.uint8(0), 'education': np.uint8(0), 'survival': np.uint8(1)} \n", + " \n", + "\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "ASSETS_GRID = jnp.concatenate(\n", + " [\n", + " jnp.linspace(-20.0, 50.0, 25),\n", + " jnp.array(np.geomspace(50.0, 3_000_000.0, 80))[1:],\n", + " ]\n", + ")\n", + "EXPERIENCE_GRID = jnp.linspace(0.0, 1.0, 8)\n", + "N_QUAD_POINTS = 5\n", + "\n", + "model_specs = build_model_specs()\n", + "model_config = {\n", + " \"n_periods\": model_specs[\"n_periods\"],\n", + " \"choices\": np.arange(model_specs[\"n_choices\"], dtype=int),\n", + " \"deterministic_states\": {\n", + " \"high_type\": np.arange(2, dtype=int),\n", + " \"education\": np.arange(3, dtype=int),\n", + " },\n", + " \"continuous_states\": {\n", + " \"assets_end_of_period\": ASSETS_GRID,\n", + " \"experience\": EXPERIENCE_GRID,\n", + " },\n", + " \"stochastic_states\": {\"survival\": [0, 1]},\n", + " \"n_quad_points\": N_QUAD_POINTS,\n", + "}\n", + "\n", + "model = dcegm.setup_model(\n", + " model_config=model_config,\n", + " model_specs=model_specs,\n", + " utility_functions=create_utility_function_dict(),\n", + " utility_functions_final_period=create_final_period_utility_function_dict(),\n", + " state_space_functions=create_state_space_function_dict(),\n", + " budget_constraint=budget_constraint,\n", + " stochastic_states_transitions={\"survival\": prob_survival},\n", + " shock_functions={\"discount_factor_per_state\": discount_factor_per_state},\n", + ")\n", + "\n", + "params_baseline = build_params()\n", + "model_solved = model.solve(params_baseline)" + ] + }, + { + "cell_type": "markdown", + "id": "ae919b76", + "metadata": {}, + "source": [ + "## 4. DC-EGM in action: kinked policy and value functions\n", + "\n", + "Section 4 of the paper describes exactly why DC-EGM is needed here: combining\n", + "a discrete hours choice with a continuous savings choice creates kinks in the\n", + "value function and discontinuities in the policy function, which first-order\n", + "conditions alone cannot characterize. The plot below reproduces that\n", + "signature directly from our solved model, for a mid-career, high-type\n", + "worker.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "34ba4cd5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:34.847201Z", + "iopub.status.busy": "2026-08-29T15:06:34.847123Z", + "iopub.status.idle": "2026-08-29T15:06:35.965793Z", + "shell.execute_reply": "2026-08-29T15:06:35.965485Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "period_to_plot = 20\n", + "wealth_grid = jnp.linspace(0.1, 150.0, 300)\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(9.5, 3.6))\n", + "for choice in range(model_specs[\"n_choices\"]):\n", + " states = {\n", + " \"period\": jnp.full_like(wealth_grid, period_to_plot, dtype=int),\n", + " \"lagged_choice\": jnp.zeros_like(wealth_grid, dtype=int),\n", + " \"high_type\": jnp.ones_like(wealth_grid, dtype=int),\n", + " \"education\": jnp.ones_like(wealth_grid, dtype=int), # highschool\n", + " \"survival\": jnp.ones_like(wealth_grid, dtype=int),\n", + " \"experience\": jnp.full_like(wealth_grid, 0.5),\n", + " \"assets_begin_of_period\": wealth_grid,\n", + " }\n", + " choices = jnp.full_like(wealth_grid, choice, dtype=int)\n", + " policy, value = model_solved.policy_and_value_for_states_and_choices(\n", + " states=states, choices=choices\n", + " )\n", + " hours = int(model_specs[\"hours_by_choice\"][choice])\n", + " axes[0].plot(wealth_grid, policy, label=f\"h={hours}\", lw=1.3)\n", + " axes[1].plot(wealth_grid, value, label=f\"h={hours}\", lw=1.3)\n", + "\n", + "axes[0].set_xlabel(\"Wealth $M_t$ ($1000)\")\n", + "axes[0].set_ylabel(\"Consumption policy $c_t$\")\n", + "axes[0].set_title(\"Consumption policy\")\n", + "axes[1].set_xlabel(\"Wealth $M_t$ ($1000)\")\n", + "axes[1].set_ylabel(\"Value $W_t$\")\n", + "axes[1].set_title(\"Value function\")\n", + "axes[0].legend(fontsize=7)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "61472c48", + "metadata": {}, + "source": [ + "## 5. Simulating the population\n", + "\n", + "We simulate all education groups and both types in one call, drawing the\n", + "unobserved type for each agent from the paper's estimated type shares\n", + "(Table 7). We are calibrating, not re-estimating, so we compare shapes\n", + "against the paper's Figures 5-8, not levels — the paper's own Figure 8 shows\n", + "wealth around \\$1M (college), \\$500k (high school) and \\$400k (dropout) at\n", + "age 70, using moments fit to HILDA that we do not target here.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "50fc6f82", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:35.967131Z", + "iopub.status.busy": "2026-08-29T15:06:35.967058Z", + "iopub.status.idle": "2026-08-29T15:06:37.566941Z", + "shell.execute_reply": "2026-08-29T15:06:37.566441Z" + } + }, + "outputs": [], + "source": [ + "N_AGENTS = 6000\n", + "rng = np.random.default_rng(0)\n", + "education_draw = rng.integers(0, 3, N_AGENTS)\n", + "high_type_shares = np.array(\n", + " [CAL[\"misc\"][\"high_type_share_by_education\"][e] for e in EDUCATION_GROUPS]\n", + ")\n", + "high_type_draw = rng.binomial(1, high_type_shares[education_draw])\n", + "\n", + "states_initial = {\n", + " \"period\": jnp.zeros(N_AGENTS, dtype=int),\n", + " \"lagged_choice\": jnp.zeros(N_AGENTS, dtype=int),\n", + " \"high_type\": jnp.array(high_type_draw, dtype=int),\n", + " \"education\": jnp.array(education_draw, dtype=int),\n", + " \"survival\": jnp.ones(N_AGENTS, dtype=int),\n", + " \"experience\": jnp.zeros(N_AGENTS),\n", + " \"assets_begin_of_period\": jnp.ones(N_AGENTS) * 2.0,\n", + "}\n", + "sim_baseline = model_solved.simulate(states_initial=states_initial, seed=1)\n", + "sim_baseline = sim_baseline.reset_index()\n", + "sim_baseline[\"age\"] = model_specs[\"t0\"] + sim_baseline[\"period\"]\n", + "sim_baseline[\"hours\"] = np.array(model_specs[\"hours_by_choice\"])[\n", + " sim_baseline[\"choice\"].to_numpy()\n", + "]\n", + "sim_baseline[\"education_label\"] = np.array(EDUCATION_GROUPS)[\n", + " sim_baseline[\"education\"].to_numpy()\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "bd244336", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:37.568289Z", + "iopub.status.busy": "2026-08-29T15:06:37.568215Z", + "iopub.status.idle": "2026-08-29T15:06:37.729136Z", + "shell.execute_reply": "2026-08-29T15:06:37.728611Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 3, figsize=(12, 3.6))\n", + "colors = {\"dropout\": \"tab:green\", \"highschool\": \"tab:red\", \"college\": \"tab:blue\"}\n", + "\n", + "for edu, g in sim_baseline.groupby(\"education_label\"):\n", + " prof = g.groupby(\"age\").agg(\n", + " frac_working=(\"hours\", lambda s: (s > 0).mean()),\n", + " mean_hours=(\"hours\", \"mean\"),\n", + " median_wealth=(\"assets_begin_of_period\", \"median\"),\n", + " )\n", + " axes[0].plot(prof.index, prof[\"frac_working\"], label=edu, color=colors[edu])\n", + " axes[1].plot(prof.index, prof[\"mean_hours\"], label=edu, color=colors[edu])\n", + " axes[2].plot(\n", + " prof.index[:-1], prof[\"median_wealth\"][:-1], label=edu, color=colors[edu]\n", + " )\n", + "\n", + "axes[0].set_title(\"Labor force participation\")\n", + "axes[0].set_xlabel(\"Age\")\n", + "axes[1].set_title(\"Mean annual hours\")\n", + "axes[1].set_xlabel(\"Age\")\n", + "axes[2].set_title(\"Median wealth ($1000)\")\n", + "axes[2].set_xlabel(\"Age\")\n", + "for ax in axes:\n", + " ax.legend(fontsize=7)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "ff3d9e2c", + "metadata": {}, + "source": [ + "## 6. Policy experiment: eliminating the Age Pension\n", + "\n", + "Section 9 of the paper studies what happens if the Age Pension is removed\n", + "entirely. We replicate the qualitative direction of that experiment using\n", + "the `pension_scale` toggle built into the budget constraint: without the\n", + "means-tested safety net, agents have a stronger incentive to self-insure\n", + "through private saving near and after 65.\n", + "\n", + "*Note:* we report **median** wealth. A small share of simulated paths under\n", + "the no-pension counterfactual land in the sparsely-gridded tail of the\n", + "assets grid, where linear interpolation is numerically unstable and\n", + "produces implausible outliers; the median is robust to this.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e5846efd", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:37.730441Z", + "iopub.status.busy": "2026-08-29T15:06:37.730347Z", + "iopub.status.idle": "2026-08-29T15:06:45.015585Z", + "shell.execute_reply": "2026-08-29T15:06:45.015147Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "params_no_pension = build_params()\n", + "params_no_pension[\"pension_scale\"] = 0.0\n", + "model_no_pension = model.solve(params_no_pension)\n", + "sim_no_pension = model_no_pension.simulate(states_initial=states_initial, seed=1)\n", + "sim_no_pension = sim_no_pension.reset_index()\n", + "sim_no_pension[\"age\"] = model_specs[\"t0\"] + sim_no_pension[\"period\"]\n", + "sim_no_pension[\"hours\"] = np.array(model_specs[\"hours_by_choice\"])[\n", + " sim_no_pension[\"choice\"].to_numpy()\n", + "]\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(9.5, 3.6))\n", + "for label, df in [(\"baseline\", sim_baseline), (\"no age pension\", sim_no_pension)]:\n", + " prof = df.groupby(\"age\").agg(\n", + " frac_working=(\"hours\", lambda s: (s > 0).mean()),\n", + " median_wealth=(\"assets_begin_of_period\", \"median\"),\n", + " )\n", + " axes[0].plot(prof.index, prof[\"frac_working\"], label=label)\n", + " axes[1].plot(prof.index[:-1], prof[\"median_wealth\"][:-1], label=label)\n", + "\n", + "axes[0].set_xlim(55, 85)\n", + "axes[0].set_title(\"Labor force participation\")\n", + "axes[0].set_xlabel(\"Age\")\n", + "axes[0].legend(fontsize=8)\n", + "axes[1].set_xlim(55, 85)\n", + "axes[1].set_title(\"Median wealth ($1000)\")\n", + "axes[1].set_xlabel(\"Age\")\n", + "axes[1].legend(fontsize=8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "886c45db", + "metadata": {}, + "source": [ + "## 7. A quantitative check: the labor supply elasticity to a permanent wage change\n", + "\n", + "Everything so far compares *shapes*. Here we compare a **number** the paper\n", + "itself reports as a structural implication of its estimated model — not a\n", + "data-fit target, but a property of the solved policy functions, which makes\n", + "it exactly the kind of object we can check independently: if our\n", + "implementation is faithful, evaluating the same experiment on our solved\n", + "model should give a broadly similar answer.\n", + "\n", + "The paper reports (Section 1) that, from an **unanticipated, permanent**\n", + "wage change, \"Marshallian elasticities are very small prior to age 45, but\n", + "grow to about 0.80 at age 60, and 1.75 at age 65.\" We compute the analogous\n", + "object: solve the model twice — once at the baseline wage, once with every\n", + "wage permanently 1% higher (`params[\"wage_scale\"] = 1.01`, an unanticipated\n", + "shift since the agent solves as if it were always true) — and compare the\n", + "**expected hours** $E[h] = \\sum_k P(h_t = h^{(k)})\\,h^{(k)}$ implied by the\n", + "solved choice-specific value functions and the paper's own logit formula\n", + "(eq. 17), $P(h^{(k)}) \\propto \\exp(W(h^{(k)})/\\lambda)$, at a representative\n", + "state for each age and education group (median simulated assets and\n", + "experience from the baseline population in Section 5).\n", + "\n", + "**Why this won't match exactly.** Holding assets and experience fixed at one\n", + "representative point isolates the *intensive margin* — how much someone\n", + "already near the middle of the distribution adjusts their hours. Evaluated\n", + "across the full simulated cross-section instead, the comparison becomes\n", + "numerically delicate: DC-EGM policy functions are genuinely kinked, so two\n", + "separately-solved models can place a kink at slightly different wealth\n", + "levels, and a handful of simulated wealth points landing near one of those\n", + "kinks can swing a population average by an order of magnitude — an artifact\n", + "of point evaluation near a kink, not a real behavioral response. The paper's\n", + "large, sharply rising elasticities at 60-65 are most plausibly driven\n", + "substantially by the *extensive margin* — a wage rise tipping people who are\n", + "near the margin of retiring into staying employed, given Age Pension\n", + "eligibility at 65 — which a single representative (non-marginal) state\n", + "cannot capture by construction. So we expect our numbers to be smaller and\n", + "flatter across age than the paper's, and they are; what we're checking is\n", + "that the sign and rough order of magnitude are sane, not that the point\n", + "estimates match.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "76fd14aa", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-29T15:06:45.016921Z", + "iopub.status.busy": "2026-08-29T15:06:45.016832Z", + "iopub.status.idle": "2026-08-29T15:06:52.947500Z", + "shell.execute_reply": "2026-08-29T15:06:52.947163Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
educationageE[hours] baseE[hours] +1% wageelasticitypaper (all groups, approx.)
0dropout302279.3782280.2440.038~0
1dropout452312.5992316.5330.170~0
2dropout602269.0812272.9580.171~0.80
3dropout652150.6352158.0600.345~1.75
4highschool302260.1742263.0140.126~0
5highschool452320.4922325.1210.199~0
6highschool602268.9742272.9140.174~0.80
7highschool652232.9762238.8800.264~1.75
8college302323.3832326.4760.133~0
9college452357.6532362.2770.196~0
10college602304.8582309.5890.205~0.80
11college652307.8992312.9990.221~1.75
\n", + "
" + ], + "text/plain": [ + " education age E[hours] base E[hours] +1% wage elasticity \\\n", + "0 dropout 30 2279.378 2280.244 0.038 \n", + "1 dropout 45 2312.599 2316.533 0.170 \n", + "2 dropout 60 2269.081 2272.958 0.171 \n", + "3 dropout 65 2150.635 2158.060 0.345 \n", + "4 highschool 30 2260.174 2263.014 0.126 \n", + "5 highschool 45 2320.492 2325.121 0.199 \n", + "6 highschool 60 2268.974 2272.914 0.174 \n", + "7 highschool 65 2232.976 2238.880 0.264 \n", + "8 college 30 2323.383 2326.476 0.133 \n", + "9 college 45 2357.653 2362.277 0.196 \n", + "10 college 60 2304.858 2309.589 0.205 \n", + "11 college 65 2307.899 2312.999 0.221 \n", + "\n", + " paper (all groups, approx.) \n", + "0 ~0 \n", + "1 ~0 \n", + "2 ~0.80 \n", + "3 ~1.75 \n", + "4 ~0 \n", + "5 ~0 \n", + "6 ~0.80 \n", + "7 ~1.75 \n", + "8 ~0 \n", + "9 ~0 \n", + "10 ~0.80 \n", + "11 ~1.75 " + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "params_wage_shock = build_params()\n", + "params_wage_shock[\"wage_scale\"] = 1.01\n", + "model_wage_shock = model.solve(params_wage_shock)\n", + "\n", + "\n", + "def expected_hours(\n", + " model_solved, params, period, education, high_type, experience, assets\n", + "):\n", + " # E[hours] via the logit CCP formula (eq. 17) applied to the solved\n", + " # choice-specific value functions at one state.\n", + " n_choices = model_specs[\"n_choices\"]\n", + " states = {\n", + " \"period\": jnp.full((n_choices,), period, dtype=int),\n", + " \"lagged_choice\": jnp.zeros((n_choices,), dtype=int),\n", + " \"high_type\": jnp.full((n_choices,), high_type, dtype=int),\n", + " \"education\": jnp.full((n_choices,), education, dtype=int),\n", + " \"survival\": jnp.ones((n_choices,), dtype=int),\n", + " \"experience\": jnp.full((n_choices,), experience),\n", + " \"assets_begin_of_period\": jnp.full((n_choices,), assets),\n", + " }\n", + " choices = jnp.arange(n_choices)\n", + " _, values = model_solved.policy_and_value_for_states_and_choices(\n", + " states=states, choices=choices\n", + " )\n", + " ccp = jax.nn.softmax(values / params[\"taste_shock_scale\"])\n", + " return float(jnp.sum(ccp * HOURS_BY_CHOICE))\n", + "\n", + "\n", + "rows = []\n", + "for edu in EDUCATION_GROUPS:\n", + " edu_idx = EDUCATION_GROUPS.index(edu)\n", + " for age in [30, 45, 60, 65]:\n", + " period = age - model_specs[\"t0\"]\n", + " sub = sim_baseline[\n", + " (sim_baseline[\"education_label\"] == edu) & (sim_baseline[\"age\"] == age)\n", + " ]\n", + " if len(sub) == 0:\n", + " continue\n", + " rep_assets = float(sub[\"assets_begin_of_period\"].median())\n", + " rep_experience = float(sub[\"experience\"].median())\n", + " rep_type = int(sub[\"high_type\"].mode().iloc[0])\n", + "\n", + " h_base = expected_hours(\n", + " model_solved,\n", + " params_baseline,\n", + " period,\n", + " edu_idx,\n", + " rep_type,\n", + " rep_experience,\n", + " rep_assets,\n", + " )\n", + " h_shock = expected_hours(\n", + " model_wage_shock,\n", + " params_wage_shock,\n", + " period,\n", + " edu_idx,\n", + " rep_type,\n", + " rep_experience,\n", + " rep_assets,\n", + " )\n", + " elasticity = (\n", + " (h_shock - h_base) / h_base / (params_wage_shock[\"wage_scale\"] - 1.0)\n", + " )\n", + " rows.append(\n", + " {\n", + " \"education\": edu,\n", + " \"age\": age,\n", + " \"E[hours] base\": h_base,\n", + " \"E[hours] +1% wage\": h_shock,\n", + " \"elasticity\": elasticity,\n", + " }\n", + " )\n", + "\n", + "elasticity_table = pd.DataFrame(rows)\n", + "paper_marshallian = {30: \"~0\", 45: \"~0\", 60: \"~0.80\", 65: \"~1.75\"}\n", + "elasticity_table[\"paper (all groups, approx.)\"] = elasticity_table[\"age\"].map(\n", + " paper_marshallian\n", + ")\n", + "elasticity_table.round(3)" + ] + }, + { + "cell_type": "markdown", + "id": "e7bcdcc2", + "metadata": {}, + "source": [ + "## 8. Where this differs from the paper, and how to extend it\n", + "\n", + "This notebook favors a fast, readable pass over an exact reproduction. Once\n", + "more: **we replicate the model, not the estimation** — everything below is a\n", + "simplification of the *mechanism*, not a data-fitting choice. The most\n", + "consequential ones, all noted where they occur above, are:\n", + "\n", + "1. **Calibrated, not estimated.** We use the paper's published point\n", + " estimates directly; no MSM estimation against HILDA is performed.\n", + "2. **Stationary policy regime.** The Age Pension and tax rules are held at\n", + " their post-2010 values for the whole simulated cohort.\n", + "3. **Bequest numerical stability.** The bequest is now evaluated on eq. (11)'s\n", + " exact $b_t = M_t - c_t$ (Section 2), but the discontinuous,\n", + " period-conditional budget constraint this requires is numerically\n", + " fragile: a small share of simulated trajectories land in unstable\n", + " interpolation regions and produce implausible outliers. We report\n", + " medians (and representative-state evaluations in Section 7)\n", + " specifically to be robust to this; see Section 2 for what we tried.\n", + "4. **Modest grids.** `ASSETS_GRID`/`EXPERIENCE_GRID` above are sized to keep\n", + " this notebook fast; a finer grid (particularly in the far tail of\n", + " assets) would tighten the life-cycle profiles in Section 5 and the\n", + " elasticity estimates in Section 7.\n", + "5. **Elasticity, not Frisch.** Section 7 computes a Marshallian-type\n", + " (permanent, unanticipated) elasticity at a single representative state\n", + " per age/education; it is not a rigorous replication of the paper's\n", + " Frisch elasticity (a temporary-shock, marginal-utility-of-wealth-held-\n", + " fixed object), which would require a different experimental design.\n", + "\n", + "What *isn't* a simplification any more: the discount factor is the paper's\n", + "exact education-specific $\\beta$ (Section 3, via `discount_factor_per_state`),\n", + "the bequest term is exactly undiscounted and evaluated on raw savings as\n", + "eq. (11)-(12) require (Section 2, modulo the numerical caveat above), age 85\n", + "now faces a genuine consumption/bequest trade-off rather than a\n", + "100%-bequest corner solution (Section 3's dummy terminal period), and every\n", + "parameter value in `params.yaml` is copied verbatim from the paper's own\n", + "tables. None of the above changes the qualitative mechanism: a discrete\n", + "hours choice combined with continuous savings under a means-tested pension\n", + "produces exactly the kind of kinked, non-concave choice-specific value\n", + "functions DC-EGM was built to solve (Section 4), and removing the pension\n", + "safety net raises private saving, as the paper's own policy experiment\n", + "finds (Section 6).\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/replications/params.yaml b/docs/source/replications/params.yaml new file mode 100644 index 00000000..2ded6bd2 --- /dev/null +++ b/docs/source/replications/params.yaml @@ -0,0 +1,107 @@ +--- +# Calibration for the Iskhakov & Keane (2021) replication notebook. +# +# All monetary values are in $1000 AUD, matching the paper. Values are the +# paper's own published point estimates (not re-estimated here): +# - Table 5 (preference parameters), Table 6 (human capital), Table 7 (misc) +# of the supplementary material. +# - Eq. (27) tax function, main paper page 20. +# - Eq. (2)/(3) survival + pension function, supplementary material page 15-16 +# (we use the post-2010 pension regime constant throughout; see notebook). +# - Table 1 (main paper) bottom panel for fixed/calibrated constants. +# +# Education groups are indexed 0=dropout, 1=highschool, 2=college throughout +# the notebook, matching the key order below. +education_groups: + - dropout + - highschool + - college +hours_by_choice: + - 0.0 + - 1000.0 + - 2000.0 + - 2250.0 + - 2500.0 + - 3000.0 +t0: 19 # model period 0 = age 19 for everyone; college students are +# choice-restricted to h=0 (in school) until age 23, see notebook. +t_retire: 85 # compulsory retirement age (last period agents may work) +college_start_age: 23 +# --- Table 5: preference parameters --- +preferences: + zeta: 0.79488 # CRRA coefficient in consumption + gamma: # disutility by hours level (gamma_0=0, unused) + - 0.0 + - 1.4139 + - 2.0088 + - 2.9213 + - 2.8639 + - 3.8775 + kappa_1: 0.50321 # low-type disutility correction + kappa_2: 0.00008 # quadratic age term (older workers) + kappa_3: 0.05083 # linear age term (younger workers) + xi: 0.48834 # CRRA coefficient of bequest + b_scale: 0.68659 # bequest scale + taste_shock_scale: 0.29950 # lambda + beta_by_education: + dropout: 0.96806 + highschool: 0.96732 + college: 0.96963 +# --- Table 6: human capital production function, eq. (4) --- +human_capital: + eta0_high_type: 0.39311 + eta3: 0.02676 + eta4: -0.00076 + eta0_by_education: + dropout: 2.45647 + highschool: 2.56761 + college: 2.78766 + eta1_by_education: + dropout: 0.01974 + highschool: 0.02164 + college: 0.03041 + eta2_by_education: + dropout: 0.00000 + highschool: -0.00002 + college: -0.00017 +# --- Table 7: misc structural parameters --- +misc: + sigma0: 0.24485 # wage shock std: constant + sigma1: 0.00421 # wage shock std: age slope + tr: 5.51308 # parental transfer ($1000/year, up to age 23) + rho_super_by_education: + dropout: 6.47838 + highschool: 5.43473 + college: 6.30347 + high_type_share_by_education: # only used to draw simulated agents' types + dropout: 0.69306 + highschool: 0.80130 + college: 0.90089 +# --- Eq. (27): income tax. NB the printed additive constant for the top +# bracket (rate1*thld1) creates a small downward jump in tax liability right +# at the second threshold; we use the continuity-preserving constant +# rate1*(thld2-thld1) instead, as is standard for bracket-style tax rules. --- +tax: + thld1: 17.39184 + thld2: 73.17661 + rate1: 0.29907 + rate2: 0.37930 +# --- Supplementary eq. (3): pension function. We fix the post-2010 regime +# constant throughout (see notebook scope discussion). --- +pension: + benefit_max: 12.60665 # 10.75973 + 1.84692 + income_taper: 0.27794 + asset_taper: 0.00499 + asset_threshold: 117.08260 + pension_age: 65 +# --- Supplementary eq. (2): survival function --- +survival: + age_threshold: 40 + a: 0.0006569 + b: 0.1078507 +# --- Table 1 bottom panel: fixed/calibrated --- +fixed: + credit_constraint: 20.0 # a0, in $1000 + interest_rate: 0.04 + consumption_floor: 0.05 # numerical safety floor, not in the paper + superannuation_age: 65 diff --git a/src/dcegm/egm/interpolate_marginal_utility.py b/src/dcegm/egm/interpolate_marginal_utility.py index 078714dd..eee10b7c 100644 --- a/src/dcegm/egm/interpolate_marginal_utility.py +++ b/src/dcegm/egm/interpolate_marginal_utility.py @@ -64,7 +64,13 @@ def interpolate_value_and_marg_util( ] compute_marginal_utility = model_funcs["compute_marginal_utility"] compute_utility = model_funcs["compute_utility"] - discount_factor = model_funcs["read_funcs"]["discount_factor"](params) + # `state_choice_vec` here is the *full batch*, not a single state-choice + # (each branch below only reduces it to scalar via its own internal + # vmap), so we pass the (unevaluated) read function through and let it + # be resolved deep inside each branch, at the point state_choice_vec is + # actually scalar/consumed -- see interp1d.py, interp1d_dj.py, + # interp2d_irregular.py and interpnd_regular.py. + read_discount_factor = model_funcs["read_funcs"]["discount_factor"] # Check if interpolation needs to be multidimensional and irregular multi_dim = continuous_grids_info["has_additional_continuous_state"] @@ -83,7 +89,7 @@ def interpolate_value_and_marg_util( policy_child_state_choice=policy_child_state_choice, value_child_state_choice=value_child_state_choice, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) elif multi_dim & (not irregular): @@ -99,7 +105,7 @@ def interpolate_value_and_marg_util( policy_child_state_choice=policy_child_state_choice, value_child_state_choice=value_child_state_choice, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) else: # Selects inside if jorgensen_druedahl or fues (different treatment of budget constraint) @@ -117,7 +123,7 @@ def interpolate_value_and_marg_util( policy_child_state_choice, value_child_state_choice, params, - discount_factor, + read_discount_factor, upper_envelope_method == "druedahl_jorgensen", ) @@ -131,7 +137,7 @@ def interp1d_value_and_marg_util_for_state_choice( policy_child_state_choice: jnp.ndarray, value_child_state_choice: jnp.ndarray, params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, use_dj_interpolation: bool, ) -> Tuple[jnp.ndarray, jnp.ndarray]: """Interpolate value and policy for given child state and compute marginal utility. @@ -182,7 +188,7 @@ def interp_on_single_wealth_point(wealth_point): compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) else: policy_interp, value_interp = interp1d_policy_and_value_on_wealth( @@ -193,7 +199,7 @@ def interp_on_single_wealth_point(wealth_point): compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) marg_util_interp = compute_marginal_utility( consumption=policy_interp, params=params, **state_choice_vec @@ -229,7 +235,7 @@ def _interpolate_value_and_marg_util_2d_irregular( policy_child_state_choice: jnp.ndarray, value_child_state_choice: jnp.ndarray, params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> Tuple[jnp.ndarray, jnp.ndarray]: """Interpolate value and marginal utility on the irregular FUES 2D grid. @@ -276,7 +282,7 @@ def _interpolate_value_and_marg_util_2d_irregular( policy_child_state_choice, value_child_state_choice, params, - discount_factor, + read_discount_factor, ) @@ -292,7 +298,7 @@ def _interpolate_value_and_marg_util_nd_regular( policy_child_state_choice: jnp.ndarray, value_child_state_choice: jnp.ndarray, params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> Tuple[jnp.ndarray, jnp.ndarray]: """Interpolate value and marginal utility on the regular n-D grid. @@ -320,7 +326,7 @@ def _interpolate_value_and_marg_util_nd_regular( state_choice_child_states=state_choice_vec, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) ) @@ -405,7 +411,7 @@ def interp2d_value_and_marg_util_for_state_choice( policy_child_state_choice: jnp.ndarray, value_child_state_choice: jnp.ndarray, params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> Tuple[jnp.ndarray, jnp.ndarray]: """Interpolate value and policy for given child state and compute marginal utility. @@ -458,7 +464,7 @@ def interp_on_single_wealth_point(wealth_point, second_cont_grid_point): compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) ) marg_util_interp = compute_marginal_utility( diff --git a/src/dcegm/egm/solve_euler_equation.py b/src/dcegm/egm/solve_euler_equation.py index a3f859ab..b8d985c9 100644 --- a/src/dcegm/egm/solve_euler_equation.py +++ b/src/dcegm/egm/solve_euler_equation.py @@ -95,7 +95,9 @@ def compute_optimal_policy_and_value( compute_utility = model_funcs["compute_utility"] compute_stochastic_transition_vec = model_funcs["compute_stochastic_transition_vec"] - discount_factor = model_funcs["read_funcs"]["discount_factor"](params) + discount_factor = model_funcs["read_funcs"]["discount_factor"]( + params=params, **state_choice_vec + ) interest_rate = model_funcs["read_funcs"]["interest_rate"](params) policy, expected_value = solve_euler_equation( diff --git a/src/dcegm/interpolation/interp1d.py b/src/dcegm/interpolation/interp1d.py index 0c40039e..b0ebec40 100644 --- a/src/dcegm/interpolation/interp1d.py +++ b/src/dcegm/interpolation/interp1d.py @@ -49,7 +49,7 @@ def interp1d_policy_and_value_on_wealth( compute_utility: Callable, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor, + read_discount_factor: Callable, ) -> Tuple[float, float]: """Interpolate policy and value function given a single wealth grid point. @@ -90,7 +90,7 @@ def interp1d_policy_and_value_on_wealth( value_at_zero_wealth=value_grid[0], state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy_interp, value_interp @@ -103,7 +103,7 @@ def interp_value_on_wealth( compute_utility: Callable, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray | float: """Interpolate value function on a single wealth point. @@ -131,7 +131,7 @@ def interp_value_on_wealth( value_at_zero_wealth=value[0], state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return value_interp @@ -179,7 +179,7 @@ def interp_value_and_check_creditconstraint( value_at_zero_wealth: float | jnp.ndarray, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> float | jnp.ndarray: """Calculate the interpolated value with accounting for a possible credit constrained solution. @@ -223,6 +223,7 @@ def interp_value_and_check_creditconstraint( params=params, **state_choice_vec, ) + discount_factor = read_discount_factor(params=params, **state_choice_vec) value_interp_closed_form = utility + discount_factor * value_at_zero_wealth # Check if we are in the credit constrained region diff --git a/src/dcegm/interpolation/interp1d_dj.py b/src/dcegm/interpolation/interp1d_dj.py index 7dc75249..4e34b3b9 100644 --- a/src/dcegm/interpolation/interp1d_dj.py +++ b/src/dcegm/interpolation/interp1d_dj.py @@ -16,7 +16,7 @@ def interp1d_policy_and_value_on_wealth_dj( compute_utility: Callable, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> Tuple[jnp.ndarray | float, jnp.ndarray | float]: """1D interpolation for DJ with consume-all overwrite for policy and value.""" ind_high, ind_low = get_index_high_and_low(x=wealth_grid, x_new=wealth) @@ -42,7 +42,7 @@ def interp1d_policy_and_value_on_wealth_dj( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) overwrite_mask = consume_all_value > value_interp_on_grid policy = jnp.where(overwrite_mask, wealth, policy_interp) @@ -57,7 +57,7 @@ def interp1d_value_on_wealth_dj( compute_utility: Callable, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray | float: """1D value interpolation for DJ with consume-all overwrite.""" _, value = interp1d_policy_and_value_on_wealth_dj( @@ -68,7 +68,7 @@ def interp1d_value_on_wealth_dj( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return value @@ -79,9 +79,10 @@ def _consume_all_value( compute_utility: Callable, state_choice_vec: Dict[str, int], params: Dict[str, float], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray: util = compute_utility(consumption=wealth, params=params, **state_choice_vec) if isinstance(util, tuple): util = util[0] + discount_factor = read_discount_factor(params=params, **state_choice_vec) return jnp.asarray(util) + discount_factor * value_at_zero_wealth diff --git a/src/dcegm/interpolation/interp2d_irregular.py b/src/dcegm/interpolation/interp2d_irregular.py index 66e580ed..3a8891f7 100644 --- a/src/dcegm/interpolation/interp2d_irregular.py +++ b/src/dcegm/interpolation/interp2d_irregular.py @@ -27,7 +27,7 @@ def interp2d_policy_and_value_on_wealth_and_regular_grid( compute_utility: Callable, state_choice_vec: Dict[str, int], params: dict, - discount_factor, + read_discount_factor: Callable, ): """Linear 2D interpolation on two grids where wealth has irregular spacing. @@ -94,7 +94,7 @@ def interp2d_policy_and_value_on_wealth_and_regular_grid( state_choice_vec=state_choice_vec, cont_state_name=cont_state_name, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy_interp, value_interp @@ -109,7 +109,7 @@ def interp2d_value_on_wealth_and_regular_grid( compute_utility: Callable, state_choice_vec: Dict[str, int], params: dict, - discount_factor, + read_discount_factor: Callable, cont_state_name: str = "continuous_state", ): """Interpolate the value function on a 2D grid. @@ -162,7 +162,7 @@ def interp2d_value_on_wealth_and_regular_grid( state_choice_vec=state_choice_vec, cont_state_name=cont_state_name, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return value_interp @@ -278,7 +278,7 @@ def interp2d_value_and_check_creditconstraint( state_choice_vec, cont_state_name, params, - discount_factor, + read_discount_factor, ): """Interpolate the value function on a 2D grid and check for credit constraints. @@ -322,6 +322,8 @@ def interp2d_value_and_check_creditconstraint( **state_choice_vec, cont_state_name: regular_point_to_interp, } + discount_factor = read_discount_factor(params=params, **state_choice_vec) + # Now recalculate the closed-form value of consuming all wealth value_calc_left = ( compute_utility( diff --git a/src/dcegm/interpolation/interp_interfaces.py b/src/dcegm/interpolation/interp_interfaces.py index a9249b79..948e76ed 100644 --- a/src/dcegm/interpolation/interp_interfaces.py +++ b/src/dcegm/interpolation/interp_interfaces.py @@ -29,7 +29,7 @@ def interpolate_value_for_state_and_choice( """Interpolate the value for a state and choice given the respective grids.""" continuous_states_info = model_config["continuous_states_info"] upper_envelope_method = model_config["upper_envelope"]["method"] - discount_factor = model_funcs["read_funcs"]["discount_factor"](params) + read_discount_factor = model_funcs["read_funcs"]["discount_factor"] compute_utility = model_funcs["compute_utility"] @@ -53,7 +53,7 @@ def interpolate_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) elif (upper_envelope_method == "druedahl_jorgensen") & multidim: @@ -71,7 +71,7 @@ def interpolate_value_for_state_and_choice( ], compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) elif upper_envelope_method == "druedahl_jorgensen": value = interp1d_value_on_wealth_dj( @@ -81,7 +81,7 @@ def interpolate_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) else: value = interp_value_on_wealth( @@ -91,7 +91,7 @@ def interpolate_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return value @@ -127,7 +127,7 @@ def interpolate_policy_for_state_and_choice( compute_utility=lambda consumption, params, **kwargs: consumption, state_choice_vec=state_choice_vec, params={}, - discount_factor=0.0, + read_discount_factor=lambda params, **kwargs: 0.0, ) elif (upper_envelope_method == "druedahl_jorgensen") & multidim: policy, _ = interpolate_policy_and_value_for_state_and_choice( @@ -149,7 +149,7 @@ def interpolate_policy_for_state_and_choice( compute_utility=model_funcs["compute_utility"], state_choice_vec=state_choice_vec, params=params, - discount_factor=model_funcs["read_funcs"]["discount_factor"](params), + read_discount_factor=model_funcs["read_funcs"]["discount_factor"], ) else: policy = interp_policy_on_wealth( @@ -175,7 +175,7 @@ def interpolate_policy_and_value_for_state_and_choice( upper_envelope_method = model_config["upper_envelope"]["method"] compute_utility = model_funcs["compute_utility"] - discount_factor = model_funcs["read_funcs"]["discount_factor"](params) + read_discount_factor = model_funcs["read_funcs"]["discount_factor"] continuous_state_space = model_structure["continuous_state_space"] multidim = continuous_states_info["has_additional_continuous_state"] @@ -195,7 +195,7 @@ def interpolate_policy_and_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) elif (upper_envelope_method == "druedahl_jorgensen") & multidim: policy, value = _interp_policy_and_value_multidim_dj_for_state_choice( @@ -212,7 +212,7 @@ def interpolate_policy_and_value_for_state_and_choice( ], compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) elif upper_envelope_method == "druedahl_jorgensen": policy, value = interp1d_policy_and_value_on_wealth_dj( @@ -223,7 +223,7 @@ def interpolate_policy_and_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) else: policy, value = interp1d_policy_and_value_on_wealth( @@ -234,7 +234,7 @@ def interpolate_policy_and_value_for_state_and_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy, value @@ -250,7 +250,7 @@ def _interp_policy_and_value_multidim_dj_for_state_choice( continuous_state_names, compute_utility, params, - discount_factor, + read_discount_factor, ): continuous_state_child_states = { name: jnp.asarray(state_choice_vec[name])[None, None] @@ -273,7 +273,7 @@ def _interp_policy_and_value_multidim_dj_for_state_choice( state_choice_child_states=state_choice_child_states, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) policy_nd = policy_nd[0, 0, 0, 0] value_nd = value_nd[0, 0, 0, 0] @@ -295,7 +295,7 @@ def _interp_policy_and_value_multidim_dj_for_state_choice( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) policy = jnp.where(has_exact_combo, policy_exact, policy_nd) diff --git a/src/dcegm/interpolation/interpnd_regular.py b/src/dcegm/interpolation/interpnd_regular.py index f870a650..e70968a7 100644 --- a/src/dcegm/interpolation/interpnd_regular.py +++ b/src/dcegm/interpolation/interpnd_regular.py @@ -31,7 +31,7 @@ def interpnd_policy_for_child_states_on_regular_grids( state_choice_child_states: Dict[str, Any], compute_utility: Callable, params: Dict[str, Any], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray: """Interpolate policy, using value-based overwrite logic. @@ -49,7 +49,7 @@ def interpnd_policy_for_child_states_on_regular_grids( state_choice_child_states=state_choice_child_states, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy @@ -64,7 +64,7 @@ def interpnd_policy_and_value_for_child_states_on_regular_grids( state_choice_child_states: Dict[str, Any], compute_utility: Callable, params: Dict[str, Any], - discount_factor: float, + read_discount_factor: Callable, ) -> tuple[jnp.ndarray, jnp.ndarray]: """Interpolate policy/value and apply consume-all overwrite. @@ -155,7 +155,7 @@ def _interp_one_child_state( continuous_state_child_states=continuous_state_child_states, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) overwrite_mask = consume_all_value > value_interp @@ -173,7 +173,7 @@ def interpnd_value_for_child_states_on_regular_grids( state_choice_child_states: Dict[str, Any], compute_utility: Callable, params: Dict[str, Any], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray: """Interpolate value and apply consume-all overwrite. @@ -269,7 +269,7 @@ def _interp_one_comb( continuous_state_child_states=continuous_state_child_states, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return jnp.asarray( @@ -284,8 +284,20 @@ def _compute_consume_all_value( continuous_state_child_states: Dict[str, jnp.ndarray], compute_utility: Callable, params: Dict[str, Any], - discount_factor: float, + read_discount_factor: Callable, ) -> jnp.ndarray: + # `state_choice_child_states` only varies along the leading + # (child-state-choice) axis -- see the `in_axes` below, where it is + # `None` (broadcast) for every other vmapped axis. So a discount factor + # read from it varies along that same axis only, and we resolve it with + # a single vmap over that axis rather than inside `_utility_at_point` + # (which runs *after* `state_choice_child_states` has been consumed and + # is no longer available point-by-point). + discount_factor = vmap( + lambda state_choice_point: read_discount_factor( + params=params, **state_choice_point + ) + )(state_choice_child_states) def _utility_at_point( consumption_point: jnp.ndarray, @@ -319,7 +331,10 @@ def _utility_at_point( ) expected_value_zero_savings = expected_value_zero_savings[:, :, None, None] - return consume_all_utility + discount_factor * expected_value_zero_savings + return ( + consume_all_utility + + discount_factor[:, None, None, None] * expected_value_zero_savings + ) def _interp_policy_and_value_one_comb( diff --git a/src/dcegm/interpolation/simulation_interp.py b/src/dcegm/interpolation/simulation_interp.py index 6ff72bae..c7cf9846 100644 --- a/src/dcegm/interpolation/simulation_interp.py +++ b/src/dcegm/interpolation/simulation_interp.py @@ -28,7 +28,7 @@ def interpolate_policy_and_value_for_all_agents( additional_continuous_state_grids, upper_envelope_method, has_additional_continuous_state, - discount_factor, + read_discount_factor, ): # 1D interpolation path is independent of upper-envelope method and only @@ -90,7 +90,7 @@ def interpolate_policy_and_value_for_all_agents( choice_range, params, compute_utility, - discount_factor, + read_discount_factor, upper_envelope_method == "druedahl_jorgensen", ) @@ -176,7 +176,7 @@ def interpolate_policy_and_value_for_all_agents( continuous_state_name, params, compute_utility, - discount_factor, + read_discount_factor, ) return policy_agent, value_agent @@ -261,7 +261,7 @@ def interpolate_policy_and_value_for_all_agents( additional_continuous_state_names, params, compute_utility, - discount_factor, + read_discount_factor, ) return policy_agent, value_agent @@ -280,7 +280,7 @@ def interp1d_policy_and_value_function( choice, params, compute_utility, - discount_factor, + read_discount_factor, use_dj_interpolation, ): state_choice_vec = {**state, "choice": choice} @@ -294,7 +294,7 @@ def interp1d_policy_and_value_function( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) else: policy_interp, value_interp = interp1d_policy_and_value_on_wealth( @@ -305,7 +305,7 @@ def interp1d_policy_and_value_function( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy_interp, value_interp @@ -323,7 +323,7 @@ def interp2d_policy_and_value_function( continuous_state_name, params, compute_utility, - discount_factor, + read_discount_factor, ): state_choice_vec = {**state, "choice": choice} @@ -339,7 +339,7 @@ def interp2d_policy_and_value_function( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) return policy_interp, value_interp @@ -358,7 +358,7 @@ def interpnd_policy_and_value_function( additional_continuous_state_names, params, compute_utility, - discount_factor, + read_discount_factor, ): state_choice_vec = {**state, "choice": choice} @@ -381,7 +381,7 @@ def interpnd_policy_and_value_function( state_choice_child_states=state_choice_child_states, compute_utility=compute_utility, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) ) @@ -401,7 +401,7 @@ def interpnd_policy_and_value_function( compute_utility=compute_utility, state_choice_vec=state_choice_vec, params=params, - discount_factor=discount_factor, + read_discount_factor=read_discount_factor, ) policy = jnp.where(has_exact_combo, policy_exact, policy_interp[0, 0, 0, 0]) diff --git a/src/dcegm/pre_processing/check_model_specs.py b/src/dcegm/pre_processing/check_model_specs.py index 098b49df..22477118 100644 --- a/src/dcegm/pre_processing/check_model_specs.py +++ b/src/dcegm/pre_processing/check_model_specs.py @@ -9,13 +9,17 @@ def extract_model_specs_info(model_specs): if not isinstance(model_specs, dict): raise ValueError("model_specs must be a dictionary.") - # discount_factor processing + # discount_factor processing. Accepts and ignores extra state-choice + # kwargs so the same read function can be called uniformly whether or + # not a `discount_factor_per_state` function is registered (see + # dcegm.pre_processing.setup_model, which may override this read + # function with a state-dependent one). if "discount_factor" in model_specs: discount_factor = jnp.asarray(model_specs["discount_factor"]) - read_func_discount_factor = lambda params: discount_factor + read_func_discount_factor = lambda params, **kwargs: discount_factor discount_factor_in_params = False else: - read_func_discount_factor = lambda params: params["discount_factor"] + read_func_discount_factor = lambda params, **kwargs: params["discount_factor"] discount_factor_in_params = True # interest_rate processing diff --git a/src/dcegm/pre_processing/check_params.py b/src/dcegm/pre_processing/check_params.py index 75759424..92146155 100644 --- a/src/dcegm/pre_processing/check_params.py +++ b/src/dcegm/pre_processing/check_params.py @@ -26,7 +26,12 @@ def process_params(params, params_check_info) -> Dict[str, float]: "not an element of model_specs or params." ) - if params_check_info["discount_factor_in_params"]: + if params_check_info.get("discount_factor_is_per_state", False): + # discount_factor is computed by a user-supplied + # `discount_factor_per_state` function instead of a single scalar; + # no fixed "discount_factor" key is expected in params or model_specs. + pass + elif params_check_info["discount_factor_in_params"]: if "discount_factor" not in params.keys(): raise ValueError( "discount_factor must be provided in model_specs or params." diff --git a/src/dcegm/pre_processing/model_functions/discount_factor_function.py b/src/dcegm/pre_processing/model_functions/discount_factor_function.py new file mode 100644 index 00000000..009f508d --- /dev/null +++ b/src/dcegm/pre_processing/model_functions/discount_factor_function.py @@ -0,0 +1,39 @@ +from dcegm.pre_processing.shared import ( + determine_function_arguments_and_partial_model_specs, +) + + +def process_discount_factor_function( + shock_functions, model_specs, additional_continuous_state_names +): + """Process a user-supplied state-choice-dependent discount factor. + + If `shock_functions["discount_factor_per_state"]` is provided, it is wrapped + the same way as every other user function (utility, budget constraint, ...), + so it can be called with `params` and whichever state-choice variables it + declares in its signature. Otherwise, discount_factor stays the default + single scalar read from `model_specs` or `params` (see + `dcegm.pre_processing.check_model_specs.extract_model_specs_info`). + + """ + shock_functions = {} if shock_functions is None else shock_functions + + if "discount_factor_per_state" not in shock_functions: + return None + + not_allowed_states = ["assets_begin_of_period"] + if additional_continuous_state_names is not None: + not_allowed_states += additional_continuous_state_names + + discount_factor_per_state_func = ( + determine_function_arguments_and_partial_model_specs( + func=shock_functions["discount_factor_per_state"], + model_specs=model_specs, + not_allowed_state_choices=not_allowed_states, + ) + ) + + def read_func_discount_factor(params, **state_choice_vec): + return discount_factor_per_state_func(params=params, **state_choice_vec) + + return read_func_discount_factor diff --git a/src/dcegm/pre_processing/model_functions/process_model_functions.py b/src/dcegm/pre_processing/model_functions/process_model_functions.py index 75e5d8d5..5787a3ad 100644 --- a/src/dcegm/pre_processing/model_functions/process_model_functions.py +++ b/src/dcegm/pre_processing/model_functions/process_model_functions.py @@ -3,6 +3,9 @@ import jax import jax.numpy as jnp +from dcegm.pre_processing.model_functions.discount_factor_function import ( + process_discount_factor_function, +) from dcegm.pre_processing.model_functions.taste_shock_function import ( process_shock_functions, ) @@ -163,6 +166,17 @@ def process_model_functions_and_extract_info( additional_continuous_state_names=additional_continuous_state_names, ) ) + + # State-choice-dependent discount factor (optional). Returns None if the + # user did not supply `shock_functions["discount_factor_per_state"]`, in + # which case the default single-scalar discount_factor is used instead + # (set up later in `extract_model_specs_info`). + discount_factor_per_state_func = process_discount_factor_function( + shock_functions=shock_functions, + model_specs=model_specs_jax, + additional_continuous_state_names=additional_continuous_state_names, + ) + model_config_processed = model_config model_config_processed["params_check_info"] = { "taste_shock_scale_in_params": taste_shock_scale_in_params @@ -180,6 +194,7 @@ def process_model_functions_and_extract_info( "next_period_deterministic_state": next_period_deterministic_state, "compute_upper_envelope": compute_upper_envelope, "taste_shock_function": taste_shock_function_processed, + "discount_factor_per_state_func": discount_factor_per_state_func, } return model_funcs, model_config_processed diff --git a/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py b/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py index 1833d1d2..c4bdc694 100644 --- a/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py +++ b/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py @@ -20,9 +20,10 @@ def compute_upper_envelope( state_choice_dict, utility_function, params, - discount_factor, + read_discount_factor, ): state_choice_vars = {**state_choice_dict, **continuous_state_dict} + discount_factor = read_discount_factor(params=params, **state_choice_vars) value_kwargs = { "expected_value_zero_assets": expected_value_zero_assets, diff --git a/src/dcegm/pre_processing/setup_model.py b/src/dcegm/pre_processing/setup_model.py index b8c54547..41dbd8d5 100644 --- a/src/dcegm/pre_processing/setup_model.py +++ b/src/dcegm/pre_processing/setup_model.py @@ -84,6 +84,14 @@ def create_model_dict( ) specs_read_funcs, specs_params_info = extract_model_specs_info(model_specs) + if model_funcs["discount_factor_per_state_func"] is not None: + specs_read_funcs["discount_factor"] = model_funcs[ + "discount_factor_per_state_func" + ] + specs_params_info["discount_factor_in_params"] = False + specs_params_info["discount_factor_is_per_state"] = True + else: + specs_params_info["discount_factor_is_per_state"] = False model_funcs["read_funcs"] = specs_read_funcs model_config_processed["params_check_info"] = { @@ -220,6 +228,14 @@ def load_model_dict( ) specs_read_funcs, specs_params_info = extract_model_specs_info(model_specs) + if model["model_funcs"]["discount_factor_per_state_func"] is not None: + specs_read_funcs["discount_factor"] = model["model_funcs"][ + "discount_factor_per_state_func" + ] + specs_params_info["discount_factor_in_params"] = False + specs_params_info["discount_factor_is_per_state"] = True + else: + specs_params_info["discount_factor_is_per_state"] = False model["model_funcs"]["read_funcs"] = specs_read_funcs model["model_config"]["params_check_info"] = { diff --git a/src/dcegm/simulation/simulate.py b/src/dcegm/simulation/simulate.py index c3b199bf..11b792f8 100644 --- a/src/dcegm/simulation/simulate.py +++ b/src/dcegm/simulation/simulate.py @@ -171,8 +171,10 @@ def simulate_single_period( choice_range = model_structure_sol["choice_range"] - discount_factor = read_funcs["discount_factor"](params) - # Interpolate policy and value function for all agents. + # Interpolate policy and value function for all agents. `discount_factor` + # may be state-choice dependent, so we pass the (unevaluated) read + # function through and let it be resolved per-agent, using each agent's + # own state, deep inside the interpolation vmap. policy, values_pre_taste_shock = interpolate_policy_and_value_for_all_agents( discrete_states_beginning_of_period=discrete_states_beginning_of_period, continuous_state_beginning_of_period=continuous_state_beginning_of_period, @@ -193,7 +195,7 @@ def simulate_single_period( ], upper_envelope_method=model_config["upper_envelope"]["method"], has_additional_continuous_state=has_additional_continuous_state, - discount_factor=discount_factor, + read_discount_factor=read_funcs["discount_factor"], ) # Draw taste shocks and calculate final value. diff --git a/src/dcegm/solve_single_period.py b/src/dcegm/solve_single_period.py index 8eab9bda..d5376ec2 100644 --- a/src/dcegm/solve_single_period.py +++ b/src/dcegm/solve_single_period.py @@ -158,10 +158,12 @@ def solve_for_interpolated_values( params=params, ) - discount_factor = model_funcs["read_funcs"]["discount_factor"](params) - # Run upper envelope over all state-choice combinations to remove suboptimal - # candidates + # candidates. `discount_factor` may be state-choice dependent, so we pass + # the (unevaluated) read function through and call it inside + # `compute_upper_envelope_for_state_choice`, where it already has access + # to a single state-choice's own values -- exactly like `compute_utility` + # and `params`, which are also broadcast (not mapped) into that vmap. ( endog_grid_state_choice, policy_state_choice, @@ -175,7 +177,7 @@ def solve_for_interpolated_values( state_choice_mat=state_choice_mat, compute_utility=model_funcs["compute_utility"], params=params, - discount_factor=discount_factor, + read_discount_factor=model_funcs["read_funcs"]["discount_factor"], compute_upper_envelope_for_state_choice=model_funcs["compute_upper_envelope"], ) out_dict = { @@ -203,12 +205,15 @@ def run_upper_envelope( state_choice_mat, compute_utility, params, - discount_factor, + read_discount_factor, compute_upper_envelope_for_state_choice, ): """Run upper envelope to remove suboptimal candidates. - Vectorized over all state-choice combinations. + Vectorized over all state-choice combinations. `read_discount_factor` is broadcast + (not mapped) like `compute_utility` and `params`; it is called inside + `compute_upper_envelope_for_state_choice` with that call's own state-choice values, + which is where a state-choice-dependent discount factor is actually evaluated. """ return vmap( @@ -246,5 +251,5 @@ def run_upper_envelope( state_choice_mat, compute_utility, params, - discount_factor, + read_discount_factor, ) diff --git a/tests/test_discount_factor_per_state.py b/tests/test_discount_factor_per_state.py new file mode 100644 index 00000000..e02585b8 --- /dev/null +++ b/tests/test_discount_factor_per_state.py @@ -0,0 +1,129 @@ +"""Test that a state-dependent discount factor matches looping over scalar solves. + +We add a `type` deterministic state to the simple dcegm-paper retirement model that +affects *only* the discount factor (nothing else -- not utility, not the budget +constraint, not the choice set). We then compare two ways of solving it: + +(i) one joint solve, with `discount_factor_per_state` reading `beta_by_type[type]` from +`params`, and (ii) looping over each type value and solving the (type-less) base model +with the corresponding scalar `discount_factor`. + +Since `type` has no effect other than through the discount factor, and it never +transitions, the two approaches should be exactly equivalent: solving jointly with a +per-type discount factor cannot differ from solving each type separately with the +matching scalar. We check this by comparing interpolated policy and value functions on a +wealth grid, for every period/lagged_choice/type combination. + +""" + +import jax.numpy as jnp +import numpy as np +import pytest +from numpy.testing import assert_array_almost_equal as aaae + +import dcegm +import dcegm.toy_models as toy_models + +BETA_BY_TYPE = jnp.array([0.90, 0.98]) + + +def discount_factor_per_type(type, params): + return params["beta_by_type"][type] + + +def next_period_deterministic_state(period, choice, type): + return {"period": period + 1, "lagged_choice": choice, "type": type} + + +@pytest.fixture() +def base_ingredients(): + model_funcs = toy_models.load_example_model_functions("dcegm_paper") + params, model_specs, model_config = ( + toy_models.load_example_params_model_specs_and_config( + "dcegm_paper_retirement_with_shocks" + ) + ) + # A handful of periods and a coarse wealth grid keep this test fast; the + # equivalence being tested does not depend on their size. + model_config["n_periods"] = 6 + return model_funcs, params, model_specs, model_config + + +def test_discount_factor_per_state_matches_scalar_loop(base_ingredients): + model_funcs, params_base, model_specs, model_config = base_ingredients + + # --- (i) one joint solve, type as a state, discount factor read per state --- + model_config_joint = { + **model_config, + "deterministic_states": {"type": np.arange(2, dtype=int)}, + } + state_space_functions_joint = { + **model_funcs["state_space_functions"], + "next_period_deterministic_state": next_period_deterministic_state, + } + params_joint = {**params_base, "beta_by_type": BETA_BY_TYPE} + del params_joint["discount_factor"] + + model_joint = dcegm.setup_model( + model_config=model_config_joint, + model_specs=model_specs, + utility_functions=model_funcs["utility_functions"], + utility_functions_final_period=model_funcs["utility_functions_final_period"], + budget_constraint=model_funcs["budget_constraint"], + state_space_functions=state_space_functions_joint, + shock_functions={"discount_factor_per_state": discount_factor_per_type}, + ) + model_joint_solved = model_joint.solve(params_joint) + + wealth_grid = jnp.linspace(1.0, 40.0, 50) + + for type_value in (0, 1): + # --- (ii) loop: plain (type-less) model, scalar discount factor --- + params_loop = { + **params_base, + "discount_factor": float(BETA_BY_TYPE[type_value]), + } + model_loop = dcegm.setup_model( + model_config=model_config, + model_specs=model_specs, + **model_funcs, + ) + model_loop_solved = model_loop.solve(params_loop) + + for period in range(model_config["n_periods"] - 1): + for lagged_choice in (0, 1): + for choice in (0, 1): + if lagged_choice == 1 and choice == 0: + # retirement is absorbing; this state-choice does not exist + continue + + states_joint = { + "period": jnp.full_like(wealth_grid, period, dtype=int), + "lagged_choice": jnp.full_like( + wealth_grid, lagged_choice, dtype=int + ), + "type": jnp.full_like(wealth_grid, type_value, dtype=int), + "assets_begin_of_period": wealth_grid, + } + states_loop = { + "period": jnp.full_like(wealth_grid, period, dtype=int), + "lagged_choice": jnp.full_like( + wealth_grid, lagged_choice, dtype=int + ), + "assets_begin_of_period": wealth_grid, + } + choices = jnp.full_like(wealth_grid, choice, dtype=int) + + policy_joint, value_joint = ( + model_joint_solved.policy_and_value_for_states_and_choices( + states=states_joint, choices=choices + ) + ) + policy_loop, value_loop = ( + model_loop_solved.policy_and_value_for_states_and_choices( + states=states_loop, choices=choices + ) + ) + + aaae(policy_joint, policy_loop, decimal=6) + aaae(value_joint, value_loop, decimal=6) diff --git a/tests/test_interpnd_regular.py b/tests/test_interpnd_regular.py index d95c7f95..3a92e4d9 100644 --- a/tests/test_interpnd_regular.py +++ b/tests/test_interpnd_regular.py @@ -95,7 +95,7 @@ def _run_interpnd(policy_grid_child_states, value_grid_child_states, inputs): }, compute_utility=_compute_utility, params={"u_scale": 2.0}, - discount_factor=0.95, + read_discount_factor=lambda params, **kwargs: 0.95, ) @@ -178,7 +178,7 @@ def _run_interpnd_policy_value( }, compute_utility=_compute_utility, params={"u_scale": 2.0}, - discount_factor=0.95, + read_discount_factor=lambda params, **kwargs: 0.95, ) @@ -202,7 +202,7 @@ def _run_interpnd_value_only(value_grid_child_states, inputs): }, compute_utility=_compute_utility, params={"u_scale": 2.0}, - discount_factor=0.95, + read_discount_factor=lambda params, **kwargs: 0.95, ) diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 90ad52c6..a496ce0d 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -266,7 +266,7 @@ def test_interp2d_against_custom(test_cases, test_id): compute_utility=compute_utility, state_choice_vec={"choice": 0}, params=PARAMS, - discount_factor=PARAMS["discount_factor"], + read_discount_factor=lambda params, **kwargs: PARAMS["discount_factor"], ) ) diff --git a/tests/test_utility_second_continuous.py b/tests/test_utility_second_continuous.py index 0a0013c4..24ee32d6 100644 --- a/tests/test_utility_second_continuous.py +++ b/tests/test_utility_second_continuous.py @@ -373,7 +373,9 @@ def test_replication_discrete_versus_continuous_experience( compute_utility=model_cont.model_funcs["compute_utility"], state_choice_vec=state_choice_cont_dict, params=PARAMS, - discount_factor=PARAMS["discount_factor"], + read_discount_factor=lambda params, **kwargs: PARAMS[ + "discount_factor" + ], ) ) @@ -385,7 +387,7 @@ def test_replication_discrete_versus_continuous_experience( compute_utility=model_disc.model_funcs["compute_utility"], state_choice_vec=state_choice_disc_dict, params=PARAMS, - discount_factor=PARAMS["discount_factor"], + read_discount_factor=lambda params, **kwargs: PARAMS["discount_factor"], ) aaae(value_cont_interp, value_disc_interp, decimal=3)