econirl.CCP
- class econirl.CCP(n_states=90, n_actions=2, discount=0.9999, utility=None, se_method='robust', n_bootstrap=400, se_seed=None, verbose=False, num_policy_iterations=1)[source]
Bases:
NFXPSklearn-style CCP estimator for dynamic discrete choice models.
The CCP (Conditional Choice Probability) approach estimates utility parameters using the Hotz-Miller inversion theorem. This is typically faster than NFXP because it avoids the nested fixed-point computation.
With num_policy_iterations=1, this is the classic Hotz-Miller estimator. With num_policy_iterations>1, this becomes the NPL (Nested Pseudo Likelihood) algorithm. A positive value is the maximum number of stages. Set it to -1 to require joint parameter and policy fixed-point convergence.
- Parameters:
n_states (int, default=90) – Number of discrete states (e.g., mileage bins).
n_actions (int, default=2) – Number of discrete actions (e.g., keep/replace).
discount (float, default=0.9999) – Time discount factor (beta).
utility (RewardSpec) – Utility specification as a
RewardSpec. For the classic Rust bus model, userust_bus_reward_spec(n_states)fromeconirl.datasets.se_method (str, default="robust") – Method for computing standard errors.
n_bootstrap (int, default=400) – Number of pairs-cluster bootstrap replications when
se_method="bootstrap".se_seed (int, optional) – Random seed for bootstrap standard errors.
verbose (bool, default=False) – Whether to print progress messages during estimation.
num_policy_iterations (int, default=1) – Number of policy iterations. K=1 is Hotz-Miller, K>1 is NPL. Set to -1 for convergence-based stopping.
- Variables:
params (dict) – Estimated parameters after fitting. Keys are parameter names (e.g., “operating_cost”, “replacement_cost”) and values are point estimates.
se (dict) – Standard errors for each parameter.
coef (numpy.ndarray) – Coefficients as a numpy array (sklearn convention).
log_likelihood (float) – Maximized log-likelihood value.
pvalues (dict) – P-values for each parameter (from Wald t-test).
policy (numpy.ndarray) – Estimated choice probabilities P(a|s) of shape (n_states, n_actions).
value (numpy.ndarray) – Estimated value function V(s) of shape (n_states,).
value_function (numpy.ndarray) – Alias for
value_(backward compatibility).transitions (numpy.ndarray) – Transition probability matrix (n_states x n_states).
transition_tensor (numpy.ndarray) – Action-specific transition probabilities with shape
(n_actions, n_states, n_states).transition_source (str) – Whether transitions were estimated from the fitted panel or supplied.
converged (bool) – Whether the requested CCP run completed successfully.
npl_converged (bool) – Whether both the parameter and policy residuals met the NPL tolerance.
termination_reason (str) – Why the CCP run stopped.
npl_parameter_residual (float) – Final L2 change in the parameter vector.
npl_policy_residual (float) – Final maximum absolute policy fixed-point residual.
reward_spec (RewardSpec) – The reward specification used for estimation.
Examples
>>> from econirl.estimators import CCP >>> import pandas as pd >>> >>> df = pd.DataFrame({ ... "bus_id": [0, 0, 1, 1], ... "mileage": [10, 20, 15, 30], ... "replaced": [0, 0, 0, 1], ... }) >>> >>> # Hotz-Miller (fast, one-step) >>> model = CCP(n_states=90) >>> model.fit(df, state="mileage", action="replaced", id="bus_id") >>> >>> # Fixed-stage NPL >>> model_npl = CCP(n_states=90, num_policy_iterations=10) >>> model_npl.fit(df, state="mileage", action="replaced", id="bus_id")
References
- Hotz, V.J. and Miller, R.A. (1993). “Conditional Choice Probabilities
and the Estimation of Dynamic Models.” RES 60(3), 497-529.
- Aguirregabiria, V. and Mira, P. (2002). “Swapping the Nested Fixed Point
Algorithm.” Econometrica 70(4), 1519-1543.
- __init__(n_states=90, n_actions=2, discount=0.9999, utility=None, se_method='robust', n_bootstrap=400, se_seed=None, verbose=False, num_policy_iterations=1)[source]
Initialize the CCP estimator.
- Parameters:
n_states (int, default=90) – Number of discrete states.
n_actions (int, default=2) – Number of discrete actions.
discount (float, default=0.9999) – Time discount factor (beta).
utility (RewardSpec) – Utility specification as a
RewardSpec. For the classic Rust bus model, userust_bus_reward_spec(n_states)fromeconirl.datasets.se_method (str, default="robust") – Method for computing standard errors.
n_bootstrap (int, default=400) – Number of pairs-cluster bootstrap replications when
se_method="bootstrap".se_seed (int, optional) – Random seed for bootstrap standard errors.
verbose (bool, default=False) – Whether to print progress messages.
num_policy_iterations (int, default=1) – Maximum number of NPL stages (K=1 is Hotz-Miller).
- fit(data, state=None, action=None, id=None, transitions=None, reward=None)[source]
Fit the CCP estimator to data.
- Parameters:
data (pandas.DataFrame or Panel or TrajectoryPanel) – Panel data with observations. When a DataFrame is passed,
state,action, andidcolumn names are required. When a Panel/TrajectoryPanel is passed, column names are ignored.state (str, optional) – Column name for the state variable (required for DataFrame input).
action (str, optional) – Column name for the action variable (required for DataFrame input).
id (str, optional) – Column name for the individual identifier (required for DataFrame input).
transitions (numpy.ndarray, optional) – Pre-estimated transition probabilities. A 2D array of shape
(n_states, n_states)is treated as the keep-action matrix. A 3D array of shape(n_actions, n_states, n_states)is used as the full action-specific transition tensor. If None, transitions are estimated from the data.reward (RewardSpec, optional) – Reward/utility specification. If provided, overrides the
utilityparameter passed at construction time.
- Returns:
self – Returns self for method chaining.
- Return type:
- conf_int(alpha=0.05)
Compute confidence intervals for parameters.
- Parameters:
alpha (float, default=0.05) – Significance level. Returns (1 - alpha) confidence intervals.
- Returns:
{param_name: (lower, upper)}confidence intervals.- Return type:
- Raises:
RuntimeError – If the model has not been fitted yet.
- counterfactual(transitions=None, **param_changes)
Compute outcomes under different parameter values.
Performs counterfactual analysis by solving the dynamic programming problem under alternative parameter values. This enables “what if” questions such as “what would the policy be if replacement cost were 15 instead of 10?”
- Parameters:
transitions (numpy.ndarray, optional) – Alternative transition matrix or action-specific transition tensor. When supplied, reward parameters remain fixed.
**param_changes (float) – Keyword arguments specifying parameter changes. Keys must be valid parameter names, such as
operating_costorreplacement_costforrust_bus_reward_spec. Values are the counterfactual parameter values.
- Returns:
Object containing: - params: Dictionary of all parameter values used - value_function: V(s) under new parameters - policy: P(a|s) under new parameters
- Return type:
CounterfactualResult
- Raises:
RuntimeError – If the model has not been fitted yet.
ValueError – If an unknown parameter name is provided.
Examples
>>> from econirl.datasets import rust_bus_reward_spec >>> model = NFXP(n_states=90, utility=rust_bus_reward_spec(90)) >>> model.fit(data, state="mileage", action="replaced", id="bus_id") >>> >>> # What if replacement cost was higher? >>> cf = model.counterfactual(replacement_cost=15.0) >>> print(f"Original replacement cost: " ... f"{model.params_['replacement_cost']:.2f}") >>> print(f"Counterfactual replacement cost: " ... f"{cf.params['replacement_cost']:.2f}") >>> print(f"P(replace|state=50) changes from " ... f"{model.predict_proba(np.array([50]))[0,1]:.3f} to " ... f"{cf.policy[50,1]:.3f}") >>> >>> # Multiple parameter changes >>> cf2 = model.counterfactual( ... replacement_cost=15.0, ... operating_cost=0.05, ... )
- predict_proba(states)
Predict choice probabilities for given states.
- Parameters:
states (numpy.ndarray) – Array of state indices.
- Returns:
Choice probabilities of shape (len(states), n_actions). Each row sums to 1.
- Return type:
- property reward_matrix_: ndarray | None
Structural reward matrix R(s,a) of shape (n_states, n_actions).
Computes the utility matrix from the fitted parameters and the feature specification. Returns None if the model has not been fitted.
- simulate(n_agents, n_periods, seed=None, init_states=None)
Simulate choices under the estimated policy.
Generates synthetic data by simulating agents making decisions according to the fitted model. Each agent starts from
init_states(state 0 for everyone by default) and evolves according to the estimated transition probabilities and choice probabilities.- Parameters:
n_agents (int) – Number of agents to simulate.
n_periods (int) – Number of time periods per agent.
seed (int, optional) – Random seed for reproducibility.
init_states (numpy.ndarray, optional) – Initial states. None starts every agent at state 0. A length
n_statesvector is treated as a start distribution and sampled. A lengthn_agentsarray sets each agent’s start state directly.
- Returns:
DataFrame with columns: - agent_id: Identifier for each agent (0 to n_agents-1) - period: Time period (0 to n_periods-1) - state: State at the beginning of the period - action: Action taken (sampled from estimated policy)
- Return type:
- Raises:
RuntimeError – If the model has not been fitted yet.
Examples
>>> model = NFXP(n_states=90) >>> model.fit(data, state="mileage", action="replaced", id="bus_id") >>> sim_data = model.simulate(n_agents=100, n_periods=50, seed=42) >>> print(sim_data.head())