### Setup and execution environment Source: https://github.com/opensourceeconomics/pylcm/blob/main/examples/README.md These console commands outline the steps to clone the Pylcm repository, navigate to the examples directory, and launch an interactive IPython shell using pixi for running the example models. ```console $ git clone https://github.com/opensourceeconomics/pylcm.git $ cd lcm/examples $ pixi run ipython ``` -------------------------------- ### Running the long_running example Source: https://github.com/opensourceeconomics/pylcm/blob/main/examples/README.md This snippet demonstrates how to import necessary functions from the pylcm library and execute the 'long_running' example model with provided configurations and parameters. ```python from lcm.entry_point import get_lcm_function from long_running import MODEL_CONFIG, PARAMS solve_model, _ = get_lcm_function(model=MODEL_CONFIG, targets="solve") V_arr_list = solve_model(PARAMS) ``` -------------------------------- ### Install PyLCM Source: https://github.com/opensourceeconomics/pylcm/blob/main/README.md Provides instructions for installing the PyLCM package using pip, both from PyPI for the stable version and from GitHub for the latest development version. ```console pip install pylcm ``` ```console pip install git+https://github.com/OpenSourceEconomics/pylcm.git ``` -------------------------------- ### Develop PyLCM with Pixi Source: https://github.com/opensourceeconomics/pylcm/blob/main/README.md Details on setting up the local development environment for PyLCM using pixi, including running tests and mypy checks, and installing pre-commit hooks. ```console git clone https://github.com/OpenSourceEconomics/pylcm.git pixi run tests ``` ```console pixi run mypy ``` ```console pixi global install pre-commit pre-commit install ``` -------------------------------- ### Initialize Functions Dictionary Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Initializes an empty dictionary to store functions that will be passed to dags.concatenate_functions. This is a common starting point for building complex function compositions. ```python funcs = {} # Step 1: Since there are no discrete state variables the lookup info is empty, and we # do not require any label translator space_info.lookup_info ``` -------------------------------- ### Evaluate Utility and Feasibility on Scalar Values Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Evaluates the utility and feasibility functions on scalar inputs. This example demonstrates a case where the action (consumption) is not feasible due to the borrowing constraint. ```python _u, _f = u_and_f( consumption=100, retirement=0, wealth=50, params=params, ) print(f"Utility: {_u}, feasible: {_f}") ``` -------------------------------- ### Get Function Representation for Interpolation Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Creates a function that can interpolate on a value function array. It takes the space_info and a name for the grid values as input. The resulting function can be called with scalar arguments and requires the grid values as an additional argument. ```python from lcm.function_representation import get_function_representation scalar_value_function = get_function_representation( space_info=space_info, name_of_values_on_grid="V_arr", ) scalar_value_function.__signature__ ``` -------------------------------- ### PyLCM Core Functionality Source: https://github.com/opensourceeconomics/pylcm/blob/main/CHANGES.md Details the core functionalities of the PyLCM project, including model specification, grid approximation, value function interpolation, policy search, and state transitions. ```python Specification of finite-horizon discrete-continuous choice models with an arbitrary number of discrete and continuous states and actions. - Linearly and Log-linearly spaced grids that approximate continuous states and actions. - Linear interpolation and extrapolation of the value function for continuous states. - Grid search (brute-force) for finding the optimal continuous policy. - Stochastic state transitions for discrete states which may depend on other discrete states and actions. ``` -------------------------------- ### PyLCM Function Representation Explanation Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/README.md Explains the function representation used within PyLCM and how it operates. This is intended for developers and requires viewing on nbviewer for correct figure rendering. ```markdown Explanations of what the function representation does and how it works ``` -------------------------------- ### Map Utility and Feasibility Over State-Action Space Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Uses `lcm.dispatchers.productmap` to evaluate the utility and feasibility functions across the entire state-action space. This prepares the data for calculating the value function array. ```python from lcm.dispatchers import productmap u_and_f_mapped = productmap(u_and_f, variables=["wealth", "consumption", "retirement"]) u, f = u_and_f_mapped(**processed_model.grids, params=params) print(f"Length of (wealth, consumption, retirement) grids: {u.shape}") ``` -------------------------------- ### Apply Productmap Decorator for Grid Evaluation Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Applies the productmap decorator to a function, enabling its evaluation on a grid of state variables. This allows for interpolation across different states. ```python value_function = productmap(scalar_value_function, variables=["wealth"]) ``` -------------------------------- ### Create State-Action Space Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Generates a state-action space object containing information about the grid structure, essential for interpolation. ```python from lcm.state_space import create_state_action_space # the space info object contains information on the grid structure etc. space_info = create_state_action_space( model=processed_model, is_last_period=True, )[1] ``` -------------------------------- ### Process Pylcm Model Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Processes the defined Pylcm model to generate JAX grids. This step is crucial for preparing the model for computation and is typically handled internally by the `lcm` library. ```python from lcm.input_processing import process_model processed_model = process_model(model) ``` -------------------------------- ### Compute Utility and Feasibility Functions Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Generates the utility and feasibility functions for the last period of the model. It computes the maximum over all feasible actions, considering the consumption constraint. ```python from lcm.model_functions import get_current_u_and_f u_and_f = get_current_u_and_f(processed_model) u_and_f.__signature__ ``` -------------------------------- ### Lookup Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Emulates indexing into an array via named axes, used for combining auxiliary functions. ```python # We want a function that allows us to perform a lookup like this: V_arr[jnp.array([0, 2, 5])] ``` ```python from lcm.function_representation import _get_lookup_function lookup = _get_lookup_function(array_name="V_arr", axis_names=["wealth_index"]) print(lookup.__signature__) ``` ```python lookup(wealth_index=jnp.array([0, 2, 5]), next_V_arr=V_arr) ``` -------------------------------- ### Wealth Coordinate Finder Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Implements a coordinate finder function for the 'wealth' state variable using `lcm.grid_helpers.get_linspace_coordinate`. This function maps wealth values to grid indices required by the interpolator. It's stored under the '__wealth_coord__' key. ```python # Step 3: (1) First we need to add a coordinate finder for the wealth state variable from lcm.grid_helpers import get_linspace_coordinate def wealth_coordinate_finder(wealth): return get_linspace_coordinate( wealth, start=1, stop=400, n_points=10, ) funcs["__wealth_coord__"] = wealth_coordinate_finder ``` -------------------------------- ### Evaluate Value Function on Concatenated Wealth Grid Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Evaluates the value function on a combined grid of existing wealth points and new wealth points. This demonstrates interpolation by comparing values on new points with pre-calculated values. ```python wealth_grid = processed_model.grids["wealth"] wealth_points_new = jnp.array([10, 25, 75, 210, 300]) wealth_grid_concatenated = jnp.concatenate([wealth_grid, wealth_points_new]) V_via_func = value_function(wealth=wealth_grid_concatenated, next_V_arr=V_arr) ``` -------------------------------- ### Coordinate Finder for Continuous Grids Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Returns the general index for a given value in a continuous grid (linearly or logarithmically spaced), used for interpolation. ```python wealth_grid = LinspaceGrid(start=1, stop=400, n_points=10) print(wealth_grid.to_jax()) ``` ```python from lcm.function_representation import _get_coordinate_finder wealth_coordinate_finder = _get_coordinate_finder( in_name="wealth", grid=wealth_grid, ) print(wealth_coordinate_finder.__signature__) ``` ```python # Example wealth values and their expected general indices: # 1 -> 0 # (1 + 45.333336) / 2 -> 0.5 (midpoint between index 0 and 1) # 390 -> close to 9 (near the end of the grid) wealth_values = jnp.array([1, (1 + 45.333336) / 2, 390]) print(wealth_coordinate_finder(wealth=wealth_values)) ``` -------------------------------- ### Define Deterministic Model in Pylcm Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Defines a deterministic economic model with utility, labor income, and state transition functions. It specifies discrete and continuous grids for actions and states, and sets model parameters. This forms the core of the economic simulation. ```python from dataclasses import dataclass import jax.numpy as jnp from lcm import DiscreteGrid, LinspaceGrid, Model from lcm.typing import ( BoolND, ContinuousAction, ContinuousState, DiscreteAction, FloatND, Int1D, IntND, ) @dataclass class RetirementStatus: working: int = 0 retired: int = 1 def utility( consumption: ContinuousAction, working: IntND, disutility_of_work: float ) -> FloatND: return jnp.log(consumption) - disutility_of_work * working def labor_income(working: DiscreteAction, wage: float | FloatND) -> FloatND: return working * wage def working(retirement: DiscreteAction) -> IntND: return 1 - retirement def wage(age: int | IntND) -> float | FloatND: return 1 + 0.1 * age def age(_period: int | Int1D) -> int | IntND: return _period + 18 def next_wealth( wealth: ContinuousState, consumption: ContinuousAction, labor_income: FloatND, interest_rate: float, ) -> ContinuousState: return (1 + interest_rate) * (wealth - consumption) + labor_income def borrowing_constraint( consumption: ContinuousAction, wealth: ContinuousState ) -> BoolND: return consumption <= wealth model = Model( description=( "Starts from Iskhakov et al. (2017), removes the absorbing retirement " "constraint and the lagged_retirement state, and adds a wage function that " "depends on age." ), n_periods=2, functions={ "utility": utility, "next_wealth": next_wealth, "borrowing_constraint": borrowing_constraint, "labor_income": labor_income, "working": working, "wage": wage, "age": age, }, actions={ "retirement": DiscreteGrid(RetirementStatus), "consumption": LinspaceGrid(start=1, stop=400, n_points=20), }, states={ "wealth": LinspaceGrid(start=1, stop=400, n_points=10), }, ) params = { "beta": 0.95, "utility": {"disutility_of_work": 0.25}, "next_wealth": { "interest_rate": 0.05, }, } ``` -------------------------------- ### Interpolator Function for Value Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Creates an interpolator function using `lcm.ndimage.map_coordinates`. This function takes the interpolation data and wealth coordinate finder as input to interpolate the value function. It's assigned to the '__fval__' key. ```python # Step 3: (2) And second, we need to add an interpolator for the value function that # uses the wealth coordinate finder as an input. from lcm.ndimage import map_coordinates def interpolator(__interpolation_data__, __wealth_coord__): coordinates = jnp.array([__wealth_coord__]) return map_coordinates( __interpolation_data__, coordinates=coordinates, ) funcs["__fval__"] = interpolator ``` -------------------------------- ### Label Translator Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Maps labels of dense discrete grids to their corresponding index. Currently acts as an identity function. ```python from lcm.function_representation import _get_label_translator translator = _get_label_translator(in_name="health") print(translator.__signature__) ``` ```python translator(health=3) ``` -------------------------------- ### Plot Value Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Visualizes the computed value function array against the wealth grid using Plotly. This helps in understanding the model's behavior and the relationship between wealth and value. ```python import plotly.graph_objects as go import plotly.io as pio pio.renderers.default = "notebook_connected" blue, orange = "#4C78A8", "#F58518" fig = go.Figure( data=[ go.Scatter( x=wealth_grid, y=V_arr, mode="markers", marker={"color": blue, "size": 10}, name="Pre-calculated values", ), ], ) fig.update_layout( xaxis_title="Wealth (x)", yaxis_title="V(x)", template="plotly_white", ) fig.show() ``` -------------------------------- ### Compute Value Function Array Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Computes the value function array by taking the maximum utility over all feasible actions. The `where` argument ensures that only feasible actions contribute to the maximum. ```python V_arr = jnp.max(u, axis=(1, 2), where=f, initial=-jnp.inf) V_arr.shape ``` -------------------------------- ### Evaluate Value Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Evaluates the generated `value_function` with provided wealth grid data and next state values (V_arr). The result `V_evaluated` contains the interpolated values. ```python V_evaluated = value_function(wealth=wealth_grid.to_jax(), next_V_arr=V_arr) ``` -------------------------------- ### Concatenate Functions to Create Value Function Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Combines all generated functions using `dags.concatenate_functions` to create the final `value_function`. This function then behaves like an analytical function and its signature can be inspected. ```python # Step 4: Throwing everything into dags from dags import concatenate_functions value_function = concatenate_functions( functions=funcs, targets="__fval__", ) value_function.__signature__ ``` -------------------------------- ### Plotting Value Function Evaluation Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Generates a Plotly figure to visualize the pre-calculated values and the evaluated points of the value function. This helps in understanding the interpolation accuracy. ```python fig = go.Figure( data=[ go.Scatter( x=wealth_grid.to_jax(), y=V_arr, mode="markers", marker={"color": blue, "size": 10}, name="Pre-calculated values", ), go.Scatter( x=wealth_grid.to_jax(), y=V_evaluated, mode="markers", marker={"color": orange, "size": 7}, name="Evaluated Points", ), ], ) fig.update_layout( xaxis_title="Wealth (x)", yaxis_title="V(x)", template="plotly_white", ) fig.show() ``` -------------------------------- ### Visualize Pre-calculated vs. Evaluated Points Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Generates a Plotly scatter plot to visualize pre-calculated values on a grid against values obtained by evaluating the function representation on an expanded set of points. This highlights the interpolation behavior. ```python import plotly.graph_objects as go fig = go.Figure( data=[ go.Scatter( x=wealth_grid, y=V_arr, mode="markers", marker={"color": blue, "size": 10}, name="Pre-calculated values", ), go.Scatter( x=wealth_grid_concatenated, y=V_via_func, mode="markers", marker={"color": orange, "size": 7}, name="Evaluated Points", ), ], ) fig.update_layout( xaxis_title="Wealth (x)", yaxis_title="V(x)", template="plotly_white", ) fig.show() ``` -------------------------------- ### Interpolator for Function Values Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Interpolates values on a grid based on provided coordinates, typically used with the coordinate finder's output. ```python from lcm.function_representation import _get_interpolator value_function_interpolator = _get_interpolator( name_of_values_on_grid="V_arr", axis_names=["wealth_index"], ) print(value_function_interpolator.__signature__) ``` ```python wealth_indices = wealth_coordinate_finder(wealth=wealth_values) V_interpolations = value_function_interpolator( wealth_index=wealth_indices, next_V_arr=V_arr, ) print(V_interpolations) ``` ```python fig = go.Figure( data=[ go.Scatter( x=wealth_grid.to_jax(), y=V_arr, mode="markers", marker={"color": blue, "size": 10}, name="Pre-calculated values", ), go.Scatter( x=wealth_values, y=V_interpolations, mode="markers", marker={"color": orange, "size": 7}, name="Evaluated Points", ), ], ) fig.update_layout( xaxis_title="Wealth (x)", yaxis_title="V(x)", template="plotly_white", ) fig.show() ``` -------------------------------- ### Visualize Linear Interpolation Line Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Creates a Plotly scatter plot showing pre-calculated values as markers, a line representing linear interpolation between these points, and evaluated points from the function representation. This visually confirms that the evaluated points lie on the interpolation line. ```python fig = go.Figure( data=[ go.Scatter( x=wealth_grid, y=V_arr, mode="markers", marker={"color": blue, "size": 10}, name="Pre-calculated values", ), go.Scatter( x=wealth_grid, y=V_arr, mode="lines", line={"color": blue}, name="Linear interpolation", ), go.Scatter( x=wealth_grid_concatenated, y=V_via_func, mode="markers", marker={"color": orange, "size": 7}, name="Evaluated Points", ), ], ) fig.update_layout( xaxis_title="Wealth (x)", yaxis_title="V(x)", template="plotly_white", ) fig.show() ``` -------------------------------- ### Discrete Lookup Function and Interpolation Data Source: https://github.com/opensourceeconomics/pylcm/blob/main/explanations/function_representation.ipynb Defines a discrete lookup function that returns the value function array unchanged, as there are no discrete state variables. This function is then assigned to '__interpolation_data__' in the funcs dictionary, used for interpolation. ```python # Step 2: Since there are no discrete state variables in the model, the discrete # lookup coincides with the identity function. Since there are continuous state # variables in the model, we must interpolate and the data that is returned here is # used as interpolation data. def discrete_lookup(V_arr): return V_arr # if there was no interpolation, the entry in the funcs dictionary would have to be # '__fval__'. funcs["__interpolation_data__"] = discrete_lookup ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.