RecursiveRouteChoice is an efficient Python implementation of the recursive logit model for route choice. This kind of model was first developed in Fosgerau, Frejinger & Karlstrom 2013
This implementation contains both prediction and estimation models. See the docs for a more detailed introduction. Here is a quick start overview.
The current most direct method of installation is to clone the repository and install using pip:
pip install -r requirements.txt
Note that (currently) on windows the 2004 update has broken some interactions with OpenBLAS. To avoid any problems it is recommended to use conda, which will use MKL BLAS and avoid any issues:
conda install --file (cat requirements.txt)
Note that there are no direct problems related to this in the code but pip will install numpy 1.19.4 by default, which will immediately crash to warn about this. Reverting to numpy 1.19.3 "fixes" this in that the warning isn't triggered, but other code which does require on the broken functionality may silently fail.
It is recommended to use some kind of virtual environment to avoid conflicting package versions.
There is also a requirements_strict.txt
which explicitly specifies package versions. This
will likely contain less up to date versions, but should always work regardless of future
api changes of the dependencies.
Note the tntp file here is not included in the repository data, download separately from TransportationNetworks
import numpy as np from recursiveRouteChoice.data_loading import load_tntp_node_formulation from recursiveRouteChoice import RecursiveLogitModelPrediction, ModelDataStruct, \ RecursiveLogitModelEstimation, optimisers # DATA network_file = "SiouxFalls_net.tntp" node_max = 24 # from network file data_list, data_list_names = load_tntp_node_formulation( network_file, columns_to_extract=["length", "capacity"], sparse_format=False) distances = data_list[0] incidence_mat = (distances > 0).astype(int) network_struct = ModelDataStruct(data_list, incidence_mat) beta_sim = np.array([-0.8, -0.00015]) model = RecursiveLogitModelPrediction(network_struct, initial_beta=beta_sim, mu=1) print("Linear system size", model.get_exponential_utility_matrix().shape) orig_indices = np.arange(0, node_max, 1) # dest_indices = (orig_indices + 5) % node_max dest_indices = np.arange(0, node_max, 1) # sample every OD pair obs_per_pair = 1 print(f"Generating {obs_per_pair * len(orig_indices) * len(dest_indices)} obs total per " f"configuration") seed = 42 obs = model.generate_observations(origin_indices=orig_indices, dest_indices=dest_indices, num_obs_per_pair=obs_per_pair, iter_cap=2000, rng_seed=seed) optimiser = optimisers.ScipyOptimiser(method='l-bfgs-b') beta_est_init = [-5, -0.00001] model_est = RecursiveLogitModelEstimation(network_struct, observations_record=obs, initial_beta=beta_est_init, mu=1, optimiser=optimiser) beta = model_est.solve_for_optimal_beta(verbose=False) print(f"beta expected: [{beta_sim[0]:6.4f}, {beta_sim[1]:6.4f}]," f" beta_actual: [{beta[0]:6.4f}, {beta[1]:6.4f}]")