From c234eb3101dfbe60dd0d587cf4b365a1dc15cd08 Mon Sep 17 00:00:00 2001 From: MaxBlesch Date: Wed, 11 Mar 2026 15:18:46 +0100 Subject: [PATCH 1/5] AI instructions --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3bf6256d..60958f22 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,6 @@ jax_max.ipynb # Debugging files should be ignored *.png + +# Local agent notes +AI_instructions/ From 675645ae422587a4691a9f020a5924172ecb695e Mon Sep 17 00:00:00 2001 From: MaxBlesch Date: Wed, 11 Mar 2026 16:13:55 +0100 Subject: [PATCH 2/5] Fixed --- pyproject.toml | 8 ++ .../templates/simplemodel/run_example.ipynb | 109 +++++++++++++++--- .../templates/simplemodel/run_example.py | 17 ++- 3 files changed, 120 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7cf42dae..75cb2531 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ requires-python = ">=3.10" dependencies = [ "numpy", "jax", + "upper-envelope", ] keywords = [ "Economics", @@ -68,9 +69,16 @@ sources = ["src"] [tool.hatch.metadata] allow-direct-references = true + +# ====================================================================================== +# Templates +# ====================================================================================== + [tool.setuptools.package-data] "dcegm" = ["templates/**/*"] +[project.scripts] +dcegm = "dcegm.cli:cli" # ====================================================================================== # Misc configuration diff --git a/src/dcegm/templates/simplemodel/run_example.ipynb b/src/dcegm/templates/simplemodel/run_example.ipynb index 21a17fe3..f6a3d2d4 100644 --- a/src/dcegm/templates/simplemodel/run_example.ipynb +++ b/src/dcegm/templates/simplemodel/run_example.ipynb @@ -18,14 +18,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "846cceb4", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "start_time": "2026-03-11T15:10:22.092241Z" + }, + "jupyter": { + "is_executing": true + } + }, "outputs": [], "source": [ "# packages needed\n", "import jax.numpy as jnp\n", "from jax import config\n", + "import matplotlib.pyplot as plt\n", "\n", "# import model_funcs\n", "from model_funcs import (\n", @@ -50,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "dd55470d", "metadata": {}, "outputs": [], @@ -67,6 +75,7 @@ " \"exp_squared\": -0.0002,\n", " # Shock parameters of income\n", " \"income_shock_std\": 0.35,\n", + " \"income_shock_mean\": 0.0,\n", " \"taste_shock_scale\": 0.2,\n", " \"interest_rate\": 0.05,\n", " \"consumption_floor\": 0.001,\n", @@ -83,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "647868a7", "metadata": {}, "outputs": [], @@ -92,7 +101,7 @@ " \"n_periods\": 25,\n", " \"choices\": [0, 1],\n", " \"continuous_states\": {\n", - " \"wealth\": jnp.linspace(\n", + " \"assets_end_of_period\": jnp.linspace(\n", " 0,\n", " 50,\n", " 500,\n", @@ -112,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "da6096d9", "metadata": {}, "outputs": [], @@ -133,14 +142,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "6aade74d", "metadata": {}, "outputs": [], "source": [ "model_functions = {\n", - " \"utility_functions\": create_final_period_utility_function_dict(),\n", - " \"utility_functions_final_period\": create_utility_function_dict(),\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", "}" @@ -156,10 +165,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "3720f71b", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Update function for state space not given. Assume states only change with an increase of the period and lagged choice.\n", + "Sparsity condition not provided. Assume all states are valid.\n", + "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 3\n", + "Model setup complete.\n", + "\n" + ] + } + ], "source": [ "# Set up the model\n", "model = dcegm.setup_model(\n", @@ -180,13 +208,68 @@ " \"assets_begin_of_period\": jnp.ones(n_agents) * 10,\n", "}\n", "\n", - "model_solved.simulate(states_initial=states_initial, seed=42)" + "sim_df = model_solved.simulate(states_initial=states_initial, seed=42)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3797facd1cb5ae86", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1sAAAHUCAYAAADMRTIhAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQn5JREFUeJzt3Qd4FFXb//E7phBACJ1QDU2UotIeFJFeRBEUFRVQUPRF6V0QlICPICABpQrSFCM+/gVEVEpoghEpggoiNqqAQYSEkgRI9n/d53l332xISIh7NmW/n+uaK7uzs3tmZrNn57fnzBk/h8PhEAAAAACAR93g2ZcDAAAAABC2AAAAAMASWrYAAAAAwALCFgAAAABYQNgCAAAAAAsIWwAAAABgAWELAAAAACwgbAEAAACABYQtAAAAALCAsAUAyND3338vTz/9tFSqVEmCg4PlxhtvlLp168qkSZPk77//di0XFhYm7du399gePXTokPj5+cmiRYu8+i55ejtygk2bNpl9qX89JTw83LwmACBtAenMBwDAmDdvnvTu3VuqV68uw4YNkxo1asjly5dl586dMmfOHPn6669l+fLlVvZWmTJlzOtXqVKFd+Mf0nCs+1LfPwCAdxC2AADp0oPzF154QVq3bi0rVqyQfPnyuR7TeUOGDJHVq1db24Na3p133sk79A9oMNbWp8KFC7MvAcDL6EYIAEjX+PHjzYH63Llz3YKWU1BQkHTo0OGq+RrAtCUlf/78csstt8iCBQuuWmbv3r3SsWNHKVq0qOmaeMcdd8jixYsz1Y3wp59+kieeeEJKly5t1qtixYry1FNPSWJiomuZkydPSq9evaR8+fJmPbUL5NixY+XKlSuZfse1xe62224z61e5cmV56623XI+dP39eihQpYspITdfb399fJk+enO5rO7dNu2K+9tprZhu0nPr168v69euvWv6XX36RLl26SKlSpcw233rrrTJz5sw0uwq+9957JgiXK1fOLPvrr7+m241w5cqVctddd0mBAgWkUKFCJkRryE7ts88+M++Rvp7uyzfeeCPT+xEAfJYDAIA0XLlyxVGgQAFHw4YNM71/brrpJkf58uUdNWrUcLz77ruONWvWOB599FGHft1s3rzZtdxPP/3kKFSokKNKlSpmuc8++8zxxBNPmOUmTpzoWu7gwYNm3sKFC13z9uzZ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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sim_df.groupby(\"period\").choice.value_counts().unstack().plot(\n", + " kind=\"bar\",\n", + " stacked=True,\n", + " title=\"Choice by period\",\n", + " xlabel=\"Period\",\n", + " ylabel=\"Count\",\n", + " figsize=(10, 5),\n", + " rot=0,\n", + ")\n", + "# label choices work and retire in legend\n", + "plt.legend([\"Work\", \"Retire\"])" ] } ], "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "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, diff --git a/src/dcegm/templates/simplemodel/run_example.py b/src/dcegm/templates/simplemodel/run_example.py index fdab209a..c8e77a92 100644 --- a/src/dcegm/templates/simplemodel/run_example.py +++ b/src/dcegm/templates/simplemodel/run_example.py @@ -1,5 +1,6 @@ # packages needed import jax.numpy as jnp +import matplotlib.pyplot as plt from jax import config # import model_funcs @@ -27,6 +28,7 @@ "exp_squared": -0.0002, # Shock parameters of income "income_shock_std": 0.35, + "income_shock_mean": 0.0, "taste_shock_scale": 0.2, "interest_rate": 0.05, "consumption_floor": 0.001, @@ -73,4 +75,17 @@ "assets_begin_of_period": jnp.ones(n_agents) * 10, } -model_solved.simulate(states_initial=states_initial, seed=42) +sim_df = model_solved.simulate(states_initial=states_initial, seed=42) + +sim_df.groupby("period").choice.value_counts().unstack().plot( + kind="bar", + stacked=True, + title="Choice by period", + xlabel="Period", + ylabel="Count", + figsize=(10, 5), + rot=0, +) +# label choices work and retire in legend +plt.legend(["Work", "Retire"]) +plt.show() From 36586f299f70e8f7fc5485036a350108497abdd1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:14:54 +0100 Subject: [PATCH 3/5] [pre-commit.ci] pre-commit autoupdate (#193) --- .pre-commit-config.yaml | 6 +-- src/dcegm/interfaces/inspect_solution.py | 2 +- .../pre_processing/check_model_config.py | 6 +-- src/dcegm/solve_single_period.py | 2 +- .../sandbox/jax_timeit_large_toy_model.ipynb | 1 - tests/sandbox/time_functions_jax.ipynb | 37 ++++++++++--------- tests/test_sparse_stochastic_and_batch_sep.py | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 80e662a7..a4b9c958 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-useless-excludes # - id: identity # Prints all files passed to pre-commits. Debugging. - repo: https://github.com/adrienverge/yamllint.git - rev: v1.37.1 + rev: v1.38.0 hooks: - id: yamllint - repo: https://github.com/lyz-code/yamlfix @@ -48,7 +48,7 @@ repos: # args: # - --py37-plus - repo: https://github.com/pycqa/isort - rev: 7.0.0 + rev: 8.0.1 hooks: - id: isort name: isort @@ -59,7 +59,7 @@ repos: # hooks: # - id: setup-cfg-fmt - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.12.0 + rev: 26.1.0 hooks: - id: black language_version: python3.13 diff --git a/src/dcegm/interfaces/inspect_solution.py b/src/dcegm/interfaces/inspect_solution.py index 0bac8b28..52c9ad5f 100644 --- a/src/dcegm/interfaces/inspect_solution.py +++ b/src/dcegm/interfaces/inspect_solution.py @@ -70,7 +70,7 @@ def partially_solve( n_assets_end_of_period = model_config["continuous_states_info"][ "assets_grid_end_of_period" ].shape[0] - (value_candidates, policy_candidates, endog_grid_candidates) = ( + value_candidates, policy_candidates, endog_grid_candidates = ( create_solution_container( continuous_states_info=model_config["continuous_states_info"], n_total_wealth_grid=n_assets_end_of_period, diff --git a/src/dcegm/pre_processing/check_model_config.py b/src/dcegm/pre_processing/check_model_config.py index 47083118..718a9133 100644 --- a/src/dcegm/pre_processing/check_model_config.py +++ b/src/dcegm/pre_processing/check_model_config.py @@ -131,14 +131,12 @@ def check_model_config_and_process(model_config): n_assets_end_of_period * (1 + tuning_params["extra_wealth_grid_factor"]) < n_assets_end_of_period + tuning_params["n_constrained_points_to_add"] ): - raise ValueError( - f"""\n\n + raise ValueError(f"""\n\n When preparing the tuning parameters for the upper envelope, we found the following contradicting parameters: \n The extra wealth grid factor of {tuning_params["extra_wealth_grid_factor"]} is too small to cover the {tuning_params["n_constrained_points_to_add"]} wealth points which are added in - the credit constrained part of the wealth grid. \n\n""" - ) + the credit constrained part of the wealth grid. \n\n""") tuning_params["n_total_wealth_grid"] = int( n_assets_end_of_period * (1 + tuning_params["extra_wealth_grid_factor"]) ) diff --git a/src/dcegm/solve_single_period.py b/src/dcegm/solve_single_period.py index 1ee2be5c..7cf40435 100644 --- a/src/dcegm/solve_single_period.py +++ b/src/dcegm/solve_single_period.py @@ -18,7 +18,7 @@ def solve_single_period( debug_info, ): """Solve a single period of the model using DCEGM.""" - (value_solved, policy_solved, endog_grid_solved) = carry + value_solved, policy_solved, endog_grid_solved = carry ( state_choices_idxs, diff --git a/tests/sandbox/jax_timeit_large_toy_model.ipynb b/tests/sandbox/jax_timeit_large_toy_model.ipynb index 447338d6..10f0f1ff 100644 --- a/tests/sandbox/jax_timeit_large_toy_model.ipynb +++ b/tests/sandbox/jax_timeit_large_toy_model.ipynb @@ -25,7 +25,6 @@ "import numpy as np\n", "import time\n", "\n", - "\n", "TEST_RESOURCES_DIR = \"../resources/\"" ] }, diff --git a/tests/sandbox/time_functions_jax.ipynb b/tests/sandbox/time_functions_jax.ipynb index c642478d..74b72134 100644 --- a/tests/sandbox/time_functions_jax.ipynb +++ b/tests/sandbox/time_functions_jax.ipynb @@ -28,6 +28,7 @@ "def func_a(x, y):\n", " return x + y\n", "\n", + "\n", "jax.vmap(func_a, in_axes=(0, None))(np.array([2]), 3)" ], "id": "83f45f46db8be341", @@ -53,7 +54,9 @@ } }, "cell_type": "code", - "source": "isinstance(np.array(2), np.ndarray)", + "source": [ + "isinstance(np.array(2), np.ndarray)" + ], "id": "d2b3690f1f318672", "outputs": [ { @@ -122,10 +125,10 @@ "evalue": "No module named 'tests'", "output_type": "error", "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mModuleNotFoundError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[8]\u001B[39m\u001B[32m, line 9\u001B[39m\n\u001B[32m 7\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mjax\u001B[39;00m\u001B[34;01m.\u001B[39;00m\u001B[34;01mnumpy\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mjnp\u001B[39;00m\n\u001B[32m 8\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mnumpy\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mnp\u001B[39;00m\n\u001B[32m----> \u001B[39m\u001B[32m9\u001B[39m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mtests\u001B[39;00m\u001B[34;01m.\u001B[39;00m\u001B[34;01mutils\u001B[39;00m\u001B[34;01m.\u001B[39;00m\u001B[34;01mmarkov_simulator\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m markov_simulator\n", - "\u001B[31mModuleNotFoundError\u001B[39m: No module named 'tests'" + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mModuleNotFoundError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 9\u001b[39m\n\u001b[32m 7\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mjax\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mnumpy\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mjnp\u001b[39;00m\n\u001b[32m 8\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mnumpy\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mnp\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m9\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mtests\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mutils\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mmarkov_simulator\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m markov_simulator\n", + "\u001b[31mModuleNotFoundError\u001b[39m: No module named 'tests'" ] } ], @@ -305,19 +308,19 @@ "evalue": "len() of unsized object", "output_type": "error", "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mIndexError\u001B[39m Traceback (most recent call last)", - "\u001B[36mFile \u001B[39m\u001B[32m~/micromamba/envs/dcegm/lib/python3.11/site-packages/jax/_src/core.py:1896\u001B[39m, in \u001B[36mShapedArray._len\u001B[39m\u001B[34m(self, ignored_tracer)\u001B[39m\n\u001B[32m 1895\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1896\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mshape\u001B[49m\u001B[43m[\u001B[49m\u001B[32;43m0\u001B[39;49m\u001B[43m]\u001B[49m\n\u001B[32m 1897\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mIndexError\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m err:\n", - "\u001B[31mIndexError\u001B[39m: tuple index out of range", + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mIndexError\u001b[39m Traceback (most recent call last)", + "\u001b[36mFile \u001b[39m\u001b[32m~/micromamba/envs/dcegm/lib/python3.11/site-packages/jax/_src/core.py:1896\u001b[39m, in \u001b[36mShapedArray._len\u001b[39m\u001b[34m(self, ignored_tracer)\u001b[39m\n\u001b[32m 1895\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m-> \u001b[39m\u001b[32m1896\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mshape\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m0\u001b[39;49m\u001b[43m]\u001b[49m\n\u001b[32m 1897\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n", + "\u001b[31mIndexError\u001b[39m: tuple index out of range", "\nThe above exception was the direct cause of the following exception:\n", - "\u001B[31mTypeError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[14]\u001B[39m\u001B[32m, line 3\u001B[39m\n\u001B[32m 1\u001B[39m jit_g = jit(\u001B[38;5;28;01mlambda\u001B[39;00m x, y: g(f, x, y))\n\u001B[32m 2\u001B[39m jit_g_aux = jit(\u001B[38;5;28;01mlambda\u001B[39;00m x, y: g(f_aux, x, y))\n\u001B[32m----> \u001B[39m\u001B[32m3\u001B[39m \u001B[43mjit_g\u001B[49m\u001B[43m(\u001B[49m\u001B[43mtest_a\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtest_b\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 4\u001B[39m jit_g_aux(test_a, test_b)\n", - " \u001B[31m[... skipping hidden 13 frame]\u001B[39m\n", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[14]\u001B[39m\u001B[32m, line 1\u001B[39m, in \u001B[36m\u001B[39m\u001B[34m(x, y)\u001B[39m\n\u001B[32m----> \u001B[39m\u001B[32m1\u001B[39m jit_g = jit(\u001B[38;5;28;01mlambda\u001B[39;00m x, y: \u001B[43mg\u001B[49m\u001B[43m(\u001B[49m\u001B[43mf\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mx\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43my\u001B[49m\u001B[43m)\u001B[49m)\n\u001B[32m 2\u001B[39m jit_g_aux = jit(\u001B[38;5;28;01mlambda\u001B[39;00m x, y: g(f_aux, x, y))\n\u001B[32m 3\u001B[39m jit_g(test_a, test_b)\n", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[4]\u001B[39m\u001B[32m, line 10\u001B[39m, in \u001B[36mg\u001B[39m\u001B[34m(func, x, y)\u001B[39m\n\u001B[32m 8\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34mg\u001B[39m(func, x, y):\n\u001B[32m 9\u001B[39m func_val = func(x, y)\n\u001B[32m---> \u001B[39m\u001B[32m10\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28;43mlen\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mfunc_val\u001B[49m\u001B[43m)\u001B[49m == \u001B[32m2\u001B[39m:\n\u001B[32m 11\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m func_val[\u001B[32m0\u001B[39m]\n\u001B[32m 12\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n", - " \u001B[31m[... skipping hidden 1 frame]\u001B[39m\n", - "\u001B[36mFile \u001B[39m\u001B[32m~/micromamba/envs/dcegm/lib/python3.11/site-packages/jax/_src/core.py:1898\u001B[39m, in \u001B[36mShapedArray._len\u001B[39m\u001B[34m(self, ignored_tracer)\u001B[39m\n\u001B[32m 1896\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m.shape[\u001B[32m0\u001B[39m]\n\u001B[32m 1897\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mIndexError\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m err:\n\u001B[32m-> \u001B[39m\u001B[32m1898\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mTypeError\u001B[39;00m(\u001B[33m\"\u001B[39m\u001B[33mlen() of unsized object\u001B[39m\u001B[33m\"\u001B[39m) \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01merr\u001B[39;00m\n", - "\u001B[31mTypeError\u001B[39m: len() of unsized object" + "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[14]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m jit_g = jit(\u001b[38;5;28;01mlambda\u001b[39;00m x, y: g(f, x, y))\n\u001b[32m 2\u001b[39m jit_g_aux = jit(\u001b[38;5;28;01mlambda\u001b[39;00m x, y: g(f_aux, x, y))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[43mjit_g\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtest_a\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtest_b\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 4\u001b[39m jit_g_aux(test_a, test_b)\n", + " \u001b[31m[... skipping hidden 13 frame]\u001b[39m\n", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[14]\u001b[39m\u001b[32m, line 1\u001b[39m, in \u001b[36m\u001b[39m\u001b[34m(x, y)\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m jit_g = jit(\u001b[38;5;28;01mlambda\u001b[39;00m x, y: \u001b[43mg\u001b[49m\u001b[43m(\u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43my\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[32m 2\u001b[39m jit_g_aux = jit(\u001b[38;5;28;01mlambda\u001b[39;00m x, y: g(f_aux, x, y))\n\u001b[32m 3\u001b[39m jit_g(test_a, test_b)\n", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 10\u001b[39m, in \u001b[36mg\u001b[39m\u001b[34m(func, x, y)\u001b[39m\n\u001b[32m 8\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mg\u001b[39m(func, x, y):\n\u001b[32m 9\u001b[39m func_val = func(x, y)\n\u001b[32m---> \u001b[39m\u001b[32m10\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mfunc_val\u001b[49m\u001b[43m)\u001b[49m == \u001b[32m2\u001b[39m:\n\u001b[32m 11\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m func_val[\u001b[32m0\u001b[39m]\n\u001b[32m 12\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + " \u001b[31m[... skipping hidden 1 frame]\u001b[39m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/micromamba/envs/dcegm/lib/python3.11/site-packages/jax/_src/core.py:1898\u001b[39m, in \u001b[36mShapedArray._len\u001b[39m\u001b[34m(self, ignored_tracer)\u001b[39m\n\u001b[32m 1896\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.shape[\u001b[32m0\u001b[39m]\n\u001b[32m 1897\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[32m-> \u001b[39m\u001b[32m1898\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mlen() of unsized object\u001b[39m\u001b[33m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01merr\u001b[39;00m\n", + "\u001b[31mTypeError\u001b[39m: len() of unsized object" ] } ], diff --git a/tests/test_sparse_stochastic_and_batch_sep.py b/tests/test_sparse_stochastic_and_batch_sep.py index ba9707c0..4a2d4d22 100644 --- a/tests/test_sparse_stochastic_and_batch_sep.py +++ b/tests/test_sparse_stochastic_and_batch_sep.py @@ -125,7 +125,7 @@ def test_benchmark_models(): state: state_choices_sparse[:, id] for id, state in enumerate(discrete_states_names + ["choice"]) } - (endog_grid_full, policy_full, value_full) = ( + endog_grid_full, policy_full, value_full = ( model_solved_full.get_solution_for_discrete_state_choice( states=states_dict, choices=state_choices_sparse[:, -1] ) From f107a2d194d880bdac8370ecd5b46c2c47834c09 Mon Sep 17 00:00:00 2001 From: MaxBlesch Date: Wed, 11 Mar 2026 20:03:06 +0100 Subject: [PATCH 4/5] DOne --- pyproject.toml | 2 +- .../pre_processing/model_functions/upper_evelope_wrapper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 75cb2531..04135d72 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ authors = [ { name = "Max Blesch, Sebastian Gsell", email = "gsell.sebastian@gmail.com" } ] maintainers = [ - { name = "Max Blesch, Sebastian Gsell", email = "maximilian.blesch@hu-berlin.de" } + { name = "Max Blesch, Sebastian Gsell", email = "maxblesch@gmail.com" } ] [project.readme] 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 a8b0ab35..ebac54bd 100644 --- a/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py +++ b/src/dcegm/pre_processing/model_functions/upper_evelope_wrapper.py @@ -1,5 +1,5 @@ from jax import numpy as jnp -from upper_envelope import fues_jax +from upper_envelope.jax import fues_jax def create_upper_envelope_function(model_config, continuous_state=None): From 68efb64f5ce54be150fb670a6c99da85c25ba1ea Mon Sep 17 00:00:00 2001 From: Sebastian Gsell Date: Wed, 11 Mar 2026 20:25:06 +0100 Subject: [PATCH 5/5] Update pyproject toml --- pyproject.toml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 04135d72..f054c6b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,12 +4,11 @@ [project] name = "dcegm" description = "Python package for solving and simulating finite-horizon stochastic discrete-continuous dynamic choice models using the DC-EGM algorithm from Iskhakov, Jørgensen, Rust, and Schjerning (QE, 2017)." -version = "0.1.0.dev0" +dynamic = ["version"] requires-python = ">=3.10" dependencies = [ "numpy", "jax", - "upper-envelope", ] keywords = [ "Economics", @@ -37,7 +36,7 @@ authors = [ { name = "Max Blesch, Sebastian Gsell", email = "gsell.sebastian@gmail.com" } ] maintainers = [ - { name = "Max Blesch, Sebastian Gsell", email = "maxblesch@gmail.com" } + { name = "Max Blesch, Sebastian Gsell", email = "maximilian.blesch@hu-berlin.de" } ] [project.readme] @@ -55,9 +54,12 @@ Github = "https://github.com/OpenSourceEconomics/dcegm" # Build system configuration # ====================================================================================== [build-system] -requires = ["hatchling"] +requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" +[tool.hatch.build.hooks.vcs] +version-file = "src/dcegm/_version.py" + [tool.hatch.build.targets.sdist] exclude = ["tests"] only-packages = true @@ -66,20 +68,13 @@ only-packages = true only-include = ["src"] sources = ["src"] +[tool.hatch.version] +source = "vcs" + [tool.hatch.metadata] allow-direct-references = true -# ====================================================================================== -# Templates -# ====================================================================================== - -[tool.setuptools.package-data] -"dcegm" = ["templates/**/*"] - -[project.scripts] -dcegm = "dcegm.cli:cli" - # ====================================================================================== # Misc configuration # ======================================================================================