Model: Main Recursive Logit Implementation (recursiveRouteChoice.recursive_route_choice)

Includes data structure classes, classes for prediction and parameter estimation

class recursiveRouteChoice.recursive_route_choice.ModelDataStruct(data_attribute_list: List[Union[dok_matrix, ndarray]], incidence_matrix: dok_matrix, data_array_names_debug=None, resize=True)

Bases: object

Generic struct which stores all the arc attributes together in a convenient manner. Additionally, if it hasn’t already been done, the input data is padded with an additional row/ col to bottom right which will have the destination dummy arc mapped to. This is perhaps not particularly, clear but it is done here to avoid having to resize all the dependent quantities later

__init__(data_attribute_list: List[Union[dok_matrix, ndarray]], incidence_matrix: dok_matrix, data_array_names_debug=None, resize=True)

Instantiate a ModelDataStruct instance.

Parameters:
  • data_attribute_list (list of scipy.sparse.dok_matrix or list of array like) – List of all network attribute matrices

  • incidence_matrix (scipy.sparse.dok_matrix or array like) – Network incidence matrix

  • data_array_names_debug (list of str, optional) – List of plaintext descriptors for the network attributes, used for debug printing

  • resize (bool) – Whether to resize matrix to include zero column for dest. Should be True, unless you know what you are doing.

class recursiveRouteChoice.recursive_route_choice.RecursiveLogitModel(data_struct: ModelDataStruct, initial_beta=-1.5, mu=1.0, safety_checks=True)

Bases: ABC

Abstraction of the linear algebra operations for the recursive logit model to solve the matrix system for the value functions.

Is subclassed to provide functionality for prediction and estimation and should not be directly instantiated

__init__(data_struct: ModelDataStruct, initial_beta=-1.5, mu=1.0, safety_checks=True)

Initialises a RecursiveLogitModel instance.

Parameters:
  • data_struct (ModelDataStruct) – The ModelDataStruct corresponding to the network being estimated on

  • initial_beta (float or int or list[float] or array_like) – The initial value for the parameter weights of the network attributes

  • mu (float) – The scale parameter of the Gumbel random variables being modelled. Generally set equal to 1 as it is non-identifiable due to the uncertainty in the parameter weights.

compute_value_function(m_tilde, data_is_sparse=None) bool

Solves the linear system \(z = Mz+b\) and stores the output for future use. Returns a boolean indicating if solving the linear system was successful or not.

Parameters:
  • m_tilde (scipy.sparse.csr_matrix) – The matrix M modified to reflect the current location of the sink destination state.

  • data_is_sparse (bool, optional) – flag to indicate if the data - in this case m_tilde is sparse. If supplied, we don’t need to check this manually.

Returns:

error_flag – Returns True if an error was encountered, else false if execution finished successfully. Errors are due to the linear system having no solution, high residual or having negative solution, such that the value functions have no real solution.

Return type:

bool

get_beta_vec()

Get the current value of the network attribute parameters.

Returns:

beta_vec

Return type:

numpy.array() of float

get_exponential_utility_matrix()

Returns the matrix of exponentiated short term utilities between all states for the current value of beta.

In the mathematical notation this is \([M_{s,a}]\).

Returns:

short_term_utility

Return type:

scipy.sparse.csr_matrix

get_short_term_utility()

Returns the matrix of short term utilities between all states for the current value of beta.

In the mathematical notation this is \([r(s,a)]\) or \([v(a|k)]\) in the notation of Fosgerau.

Returns:

short_term_utility

Return type:

scipy.sparse.csr_matrix

zeros_error_override = None
class recursiveRouteChoice.recursive_route_choice.RecursiveLogitModelEstimation(data_struct: ModelDataStruct, optimiser: OptimiserBase, observations_record, initial_beta=-1.5, mu=1, sort_obs=True)

Bases: RecursiveLogitModelPrediction

Extension of RecursiveLogitModel to support Estimation of network attribute parameters.

__init__(data_struct: ModelDataStruct, optimiser: OptimiserBase, observations_record, initial_beta=-1.5, mu=1, sort_obs=True)

Initialise recursive logit model for estimation

Parameters:
  • data_struct (ModelDataStruct) – containing network attributes of desired network

  • optimiser (ScipyOptimiser or LineSearchOptimiser) – The wrapper instance for the desired optimisation routine

  • observations_record (ak.highlighlevel.Array or scipy.sparse.spmatrix) –

    or list of list

    record of observations to estimate from

  • initial_beta (float or list or array like) – initial guessed values of beta to begin optimisation algorithm with. If a scalar, beta are uniformly initialised to this value

  • mu – The scale parameter of the Gumbel random variables being modelled. Generally set equal to 1 as it is non-identifiable due to the uncertainty in the parameter weights.

  • sort_obs (bool) – flag to sort input observations to allow for efficient caching. Should only be set to False if the data is large and already known to be sorted.

eval_log_like_at_new_beta(beta_vec)

update beta vec and compute log likelihood in one step - used for lambdas Effectively a bad functools.partial

get_log_likelihood()

Compute the log likelihood of the data and its gradient for the current beta vec

Main purpose is to update internal state however also returns the negative of these two quantities

Returns:

  • log_like_stored (float) – The current negative log likelihood. Note that it is negative to be consistent with a minimisation problem

  • self.grad_stored numpy.array() of float – The current negative gradient of the log likelihood. Note that it is negative to be consistent with a minimisation problem

get_value_func_grad_orig(orig_index, m_tilde, exp_val_funcs)

Note relies on ‘self’ for the attribute data. Computes the gradient of the value function evaluated at the origin Named GradValFnOrig in companion notes, see also GradValFn2 for component part - this function applies the 1/z_{orig} * [rest]_{evaluated at orig}

solve_for_optimal_beta(verbose=True, output_file=None)

Executes the optimisation algorithm specified in the init to determine the most likely parameter values based upon the input observations

Parameters:
  • verbose (bool) – Flag for printing of output

  • output_file (str or os.path.PathLike, optional) – file to send verbose output to

Returns:

beta_vec – The optimal determined vector of parameters

Return type:

numpy.array()

update_beta_vec(new_beta_vec, from_init=False) bool

Update the interval value for the network parameters beta with the supplied value.

Parameters:
  • new_beta_vec (numpy.array() of float) –

  • from_init (bool) – flag used in subclasses to avoid messy dependence sequencing issues

Returns:

error_flag – Returns a boolean flag to indicate if updating beta was successful. This fails for an ill chosen beta which either is positive and illegal, or is large in magnitude such that the short term utility calculation overflows.

This flag is likely not used by an end user, only the internal code

Return type:

bool

class recursiveRouteChoice.recursive_route_choice.RecursiveLogitModelPrediction(data_struct: ModelDataStruct, initial_beta=-1.5, mu=1.0, safety_checks=True)

Bases: RecursiveLogitModel

Subclass which generates simulated observations based upon the supplied beta vector. Uses same structure as estimator in the hopes I can unify these such that one can use the estimator for prediction as well (probably have estimator inherit from this)

generate_observations(origin_indices, dest_indices, num_obs_per_pair, iter_cap=1000, rng_seed=None)
Parameters:
  • origin_indices (list or array like) – iterable of indices to start paths from

  • dest_indices (list or array like) – iterable of indices to end paths at

  • num_obs_per_pair (int) – Number of observations to generate for each OD pair

  • iter_cap (int) – iteration cap in the case of non convergent value functions. Hopefully should not occur but may happen if the value function solutions are negative and ill conditioned.

  • rng_seed (int or np.random.BitGenerator) – (any legal input to np.random.default_rng() )

Returns:

  • output_path_list (list of list of int)

  • List of lists containing all observations generated