econirl.RustBusEnvironment

class econirl.RustBusEnvironment(operating_cost=0.001, replacement_cost=3.0, num_mileage_bins=90, mileage_transition_probs=(0.3919, 0.5953, 0.0128), discount_factor=0.9999, scale_parameter=1.0, seed=None, cost_type='linear', operating_cost_params=None)[source]

Bases: DDCEnvironment

Rust (1987) bus engine replacement environment.

Harold Zurcher’s decision problem: Each period, observe bus mileage and decide whether to keep the current engine or replace it.

State space:

Mileage discretized into bins {0, 1, …, num_mileage_bins - 1} Each bin represents approximately 5,000 miles.

Action space:

0 = Keep: Continue with current engine 1 = Replace: Install new engine (mileage resets to 0)

Utility specification (depends on cost_type):

linear: U(s, keep) = -theta_1 * s quadratic: U(s, keep) = -theta_1 * s - theta_2 * s^2 cubic: U(s, keep) = -theta_1 * s - theta_2 * s^2 - theta_3 * s^3 sqrt: U(s, keep) = -theta_1 * sqrt(s) hyperbolic: U(s, keep) = -theta_1 / (N+1 - s)

U(s, replace) = -replacement_cost + ε_replace

where ε are i.i.d. Type I Extreme Value (Gumbel) shocks.

Transition dynamics:

If keep: mileage increases by {0, 1, 2} with probabilities (θ_0, θ_1, θ_2) If replace: mileage resets to 0

Example

>>> env = RustBusEnvironment(
...     operating_cost=0.001,
...     replacement_cost=3.0,
...     discount_factor=0.9999,
... )
>>> obs, info = env.reset()
>>> print(f"Initial mileage bin: {obs}")
>>> env_quad = RustBusEnvironment(
...     cost_type="quadratic",
...     operating_cost_params=(0.001, 0.00001),
...     replacement_cost=3.0,
... )
Parameters:
KEEP = 0
REPLACE = 1
__init__(operating_cost=0.001, replacement_cost=3.0, num_mileage_bins=90, mileage_transition_probs=(0.3919, 0.5953, 0.0128), discount_factor=0.9999, scale_parameter=1.0, seed=None, cost_type='linear', operating_cost_params=None)[source]

Initialize the Rust bus environment.

Parameters:
  • operating_cost (float) – Cost per unit mileage for operating (θ_1 in Rust). Used as the single operating cost coefficient for linear, sqrt, and hyperbolic cost types. Ignored when operating_cost_params is provided for quadratic or cubic types.

  • replacement_cost (float) – Fixed cost of engine replacement (RC in Rust)

  • num_mileage_bins (int) – Number of mileage discretization bins (default 90)

  • mileage_transition_probs (tuple[float, float, float]) – Probabilities of mileage increase (0, 1, or 2 bins) Must sum to 1. Default from Rust (1987) estimates.

  • discount_factor (float) – Time discount factor β

  • scale_parameter (float) – Logit scale parameter σ

  • seed (int | None) – Random seed for reproducibility

  • cost_type (Literal['linear', 'quadratic', 'cubic', 'sqrt', 'hyperbolic']) – Functional form of operating cost. One of “linear”, “quadratic”, “cubic”, “sqrt”, “hyperbolic”.

  • operating_cost_params (tuple[float, ...] | None) – Tuple of operating cost coefficients for multi-parameter cost types (quadratic, cubic). For quadratic, provide (theta_1, theta_2). For cubic, provide (theta_1, theta_2, theta_3). If None, uses operating_cost as the single coefficient.

property num_states: int

Number of discrete states in the environment.

property num_actions: int

Number of discrete actions available.

property transition_matrices: Array

Return transition probability matrices.

Returns:

Tensor of shape (num_actions, num_states, num_states) where result[a, s, s’] = P(s’ | s, a)

property feature_matrix: Array

Return feature matrix for utility computation.

Features are the observable characteristics that enter the utility function: U(s,a;θ) = θ · φ(s,a)

Returns:

Tensor of shape (num_states, num_actions, num_features)

property cost_type: str

Return the operating cost function type.

property true_parameters: dict[str, float]

Return the true utility parameters (for simulation studies).

Returns:

Dictionary mapping parameter names to values

property parameter_names: list[str]

Return names of utility parameters in order.

property mileage_transition_probs: ndarray

Return the mileage transition probabilities.

mileage_to_state(mileage, bin_size=5000.0)[source]

Convert actual mileage to state index.

Parameters:
  • mileage (float) – Actual odometer reading

  • bin_size (float) – Size of each mileage bin (default 5000 miles)

Returns:

State index (capped at num_mileage_bins - 1)

Return type:

int

state_to_mileage(state, bin_size=5000.0)[source]

Convert state index to midpoint mileage.

Parameters:
  • state (int) – State index

  • bin_size (float) – Size of each mileage bin

Returns:

Midpoint mileage for this bin

Return type:

float

compute_utility_matrix(parameters=None)

Compute the full utility matrix for all state-action pairs.

Parameters:

parameters (Array | None) – Optional parameter vector. If None, uses true_parameters.

Returns:

Tensor of shape (num_states, num_actions) with flow utilities

Return type:

Array

property current_state: int | None

Return the current state index.

describe()[source]

Return a human-readable description of the environment.

Return type:

str

encode_states(states)

Encode flat state indices to continuous features.

Default: normalized scalar s/(S-1) with shape (batch, 1). Override for multi-dimensional environments.

Parameters:

states (Array)

Return type:

Array

generate_panel(n_individuals=1000, n_periods=100, seed=42, as_dataframe=False)

Generate synthetic panel data from this environment.

Computes the optimal policy from the true parameters and simulates trajectories for multiple individuals.

Parameters:
  • n_individuals (int) – Number of individuals to simulate.

  • n_periods (int) – Number of time periods per individual.

  • seed (int) – Random seed for reproducibility.

  • as_dataframe (bool) – If True, return a DataFrame with human-readable columns via _state_to_record().

Returns:

Panel object, or DataFrame if as_dataframe=True.

Return type:

TrajectoryPanel | DataFrame

get_true_parameter_vector()

Return true parameters as a tensor in canonical order.

Return type:

Array

classmethod info()

Return metadata about this environment.

Subclasses should override this to provide name, description, source, n_states, n_actions, parameter details, etc.

Return type:

dict

property problem_spec: DDCProblem

Return the DDCProblem specification for this environment.

property state_dim: int

Dimensionality of the continuous state representation.