def test_obs_all(self): model = RecursiveLogitModelEstimation(network_struct, observations_record=input_obs, initial_beta=-0.4, mu=1, optimiser=optimiser) ll = model.get_log_likelihood()[0] assert pytest.approx(ll) == 6.01398195541
def _tiny_modified_common_data_checks(travel_times_mat, left, u_turn, t_time_incidence, incidence_mat, obs_record): data_list = [travel_times_mat, left, u_turn, t_time_incidence] network_data_struct = ModelDataStruct(data_list, incidence_mat) # network_data_struct.add_second_travel_time_for_testing() optimiser = optimisers.LineSearchOptimiser( optimisers.OptimHessianType.BFGS, max_iter=4) RecursiveLogitModelEstimation.zeros_error_override = False # hack model = RecursiveLogitModelEstimation(network_data_struct, optimiser, observations_record=obs_record) log_like_out, grad_out = model.get_log_likelihood() eps = 1e-6 print(optimiser.get_iteration_log( model.optim_function_state)) # Note this is currently required to # set the gradient so that compute relative gradient works, really bad # model.hessian = np.identity(network_data_struct.n_dims) # Pre @42f564e9, we are manipulating behaviour slightly so this test still works # should just replace with Sioux falls or similar ll, line_search_step, grad_norm, rel_grad_norm = (2.079441541679836, 0.0, 0.7071067811865476, 0.24044917348149386) assert np.abs(log_like_out - ll) < eps assert np.abs(model.optimiser.step - line_search_step) < eps assert np.abs(linalg.norm(grad_out) - grad_norm) < eps assert np.abs(model.optimiser.compute_relative_gradient_non_static() - rel_grad_norm) < eps targets = [(1.699556, 0.7071068, 0.3803406, 0.1582422), (1.495032, 0.8230394, 0.1457128, 0.06891792), (1.440549, 0.5111388, 0.07468365, 0.03665915)] for t in targets: ll, line_search_step, grad_norm, rel_grad_norm = t out_flag, hessian, log = optimiser.iterate_step( model.optim_function_state, verbose=False) log_like_out, grad_out = model.get_log_likelihood() print( f"({log_like_out:.7}, " f"{linalg.norm(model.optimiser.step):.7}, {linalg.norm(grad_out):.7}, " f"{model.optimiser.compute_relative_gradient_non_static():.7})" ) assert np.abs(log_like_out - ll) < eps assert np.abs( linalg.norm(model.optimiser.step) - line_search_step) < eps assert np.abs(linalg.norm(grad_out) - grad_norm) < eps assert np.abs( model.optimiser.compute_relative_gradient_non_static() - rel_grad_norm) < eps RecursiveLogitModelEstimation.zeros_error_override = None # reset
def test_compare_optim_methods(self): subfolder = "ExampleTinyModifiedObs" # big data from classical v2 folder = join("Datasets", subfolder) obs_mat, attrs = load_standard_path_format_csv(folder, delim=" ", angles_included=True) import awkward1 as ak obs_mat = obs_mat.toarray() obs_record = ak.from_numpy(obs_mat) incidence_mat, travel_times_mat, angle_cts_mat = attrs left, _, _, u_turn = AngleProcessor.get_turn_categorical_matrices( angle_cts_mat, incidence_mat) data_list = [travel_times_mat, left, u_turn] network_data_struct = ModelDataStruct(data_list, incidence_mat) # network_data_struct.add_second_travel_time_for_testing() optimiser = optimisers.LineSearchOptimiser( optimisers.OptimHessianType.BFGS, max_iter=4) RecursiveLogitModelEstimation.zeros_error_override = False model = RecursiveLogitModelEstimation(network_data_struct, optimiser, observations_record=obs_record, initial_beta=-15) m1_ll_out, m1_grad_out = model.get_log_likelihood() optimiser2 = optimisers.ScipyOptimiser(method='newton-cg') model2 = RecursiveLogitModelEstimation(network_data_struct, optimiser2, observations_record=obs_record, initial_beta=-15) m2_ll_out, m2_grad_out = model2.get_log_likelihood() assert np.allclose(m2_ll_out, m1_ll_out) assert np.allclose(m2_grad_out, m1_grad_out) beta1 = model.solve_for_optimal_beta() beta2 = model2.solve_for_optimal_beta(verbose=True) m1_ll_out, m1_grad_out = model.get_log_likelihood() m2_ll_out, m2_grad_out = model2.get_log_likelihood() print(m1_ll_out, m2_ll_out) print(m1_grad_out, m2_grad_out) assert np.allclose(beta1, beta2, 0.34657) RecursiveLogitModelEstimation.zeros_error_override = None
def test_obs1(self): model = RecursiveLogitModelEstimation( network_struct, observations_record=[input_obs[0]], initial_beta=-0.4, mu=1, optimiser=optimiser) ll = model.get_log_likelihood()[0] start_link_ind, fin_link_ind = model._compute_obs_path_indices( ak.from_iter(input_obs[0])) assert tuple(start_link_ind) == (0, 1, 2) assert tuple(fin_link_ind) == (1, 2, 1) assert (pytest.approx( model.get_short_term_utility()[start_link_ind, fin_link_ind].sum()) == -4.4) assert pytest.approx(ll, abs=1e-6) == 2.537993985
def test_singleton_fails(self): with pytest.raises(TypeError) as excinfo: RecursiveLogitModelEstimation(network_struct, observations_record=input_obs[0], initial_beta=-0.4, mu=1, optimiser=optimiser) assert "List observation format must contain list of lists" in str( excinfo.value)
def _first_example_common_data_checks(travel_times_mat, incidence_mat, obs_mat): data_list = [travel_times_mat, travel_times_mat] network_data_struct = ModelDataStruct(data_list, incidence_mat) optimiser = optimisers.LineSearchOptimiser( optimisers.OptimHessianType.BFGS, max_iter=4) model = RecursiveLogitModelEstimation(network_data_struct, optimiser, observations_record=obs_mat) log_like_out, grad_out = model.get_log_likelihood() eps = 1e-6 assert np.abs(log_like_out - 2.7725887222397816) < eps assert np.abs(linalg.norm(grad_out) - 0) < eps # model.hessian = np.identity(network_data_struct.n_dims) out_flag, hessian, log = optimiser.iterate_step( model.optim_function_state, verbose=False) assert out_flag is True assert (hessian == np.identity(2)).all() assert optimiser.n_func_evals == 1
def test_obs2(self): obs = [input_obs[1]] model = RecursiveLogitModelEstimation(network_struct, observations_record=obs, initial_beta=-0.4, mu=1, optimiser=optimiser) ll = model.get_log_likelihood()[0] start_link_ind, fin_link_ind = model._compute_obs_path_indices( ak.from_iter(obs[0])) assert tuple(start_link_ind) == (0, 3, 0) assert tuple(fin_link_ind) == (3, 0, 1) assert (pytest.approx( model.get_short_term_utility()[start_link_ind, fin_link_ind].sum()) == -5.2) print(model.get_short_term_utility()[start_link_ind, fin_link_ind].sum()) assert pytest.approx(ll) == 3.337993985
def consistency_test(network_file, orig_indices, dest_indices, obs_per_pair, beta0, test_range=None): if test_range is None: test_range = np.arange(-0.1, -2.1, -0.1) # network_file = "EMA_net.tntp" data_list, data_list_names = load_tntp_node_formulation( network_file, columns_to_extract=[ "length", ], ) distances = data_list[0] incidence_mat = (distances > 0).astype(int) network_struct = ModelDataStruct(data_list, incidence_mat, data_array_names_debug=("distances", "u_turn")) beta_vec = np.array([-0.1]) model = RecursiveLogitModelPrediction(network_struct, initial_beta=beta_vec, mu=1) print("Linear system size", model.get_exponential_utility_matrix().shape) print( f"Generating {obs_per_pair * len(orig_indices) * len(dest_indices)} obs total per " f"beta sim val") def get_data(beta_vec, seed=None): beta_vec_generate = np.array([beta_vec]) model = RecursiveLogitModelPrediction(network_struct, initial_beta=beta_vec_generate, mu=1) 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, ) return obs optimiser = optimisers.ScipyOptimiser(method='l-bfgs-b') # bfgs, l-bfgs-b import time a = time.time() expected = [] actual = [] for n, beta_gen in enumerate(test_range, start=1): expected.append(beta_gen) try: obs = get_data(beta_gen, seed=None) except ValueError as e: print(f"beta = {beta_gen} failed, {e}") actual.append(0.0) continue # print(obs) beta0 = -5 model = RecursiveLogitModelEstimation(network_struct, observations_record=obs, initial_beta=beta0, mu=1, optimiser=optimiser) beta = model.solve_for_optimal_beta(verbose=False) actual.append(float(beta)) print("beta_expected", beta_gen, "beta actual", beta, "\nOBS:") # text_list = wrapper.wrap(str(obs)) # print("\n".join(text_list)) b = time.time() print("elapsed =", b - a, "s") return np.array(expected), np.array(actual)
distances = dok_matrix(distances) incidence_mat = (distances > 0).astype(int) data_list = [distances] network_struct = ModelDataStruct(data_list, incidence_mat, data_array_names_debug=("distances",)) beta = -5 beta_vec = np.array([beta]) # 4.96 diverges optimiser = optimisers.LineSearchOptimiser(optimisers.OptimHessianType.BFGS, max_iter=40) model = RecursiveLogitModelEstimation(network_struct, observations_record=obs_ak, initial_beta=beta_vec, mu=1, optimiser=optimiser) log_like_out, grad_out = model.get_log_likelihood() print("LL1:", log_like_out, grad_out) h = 0.0002 model.update_beta_vec([beta + h]) ll2, grad2 = model.get_log_likelihood() print("LL2:", ll2, grad2) print("finite difference:", (ll2 - log_like_out) / h) ls_out = model.solve_for_optimal_beta() print(model.optim_function_state.val_grad_function(beta)) # ======================================================= print(120 * "=", 'redo with scipy') optimiser = optimisers.ScipyOptimiser(method='bfgs')
left, _, _, u_turn = AngleProcessor.get_turn_categorical_matrices( angle_cts_mat, incidence_mat) # incidence matrix which only has nonzero travel times - rather than what is specified in file t_time_incidence = (travel_times_mat > 0).astype('int').todok() data_list = [travel_times_mat, left, u_turn, t_time_incidence] network_data_struct = ModelDataStruct(data_list, incidence_mat) # # network_data_struct, obs_mat = ModelDataStruct.from_directory( # folder, add_angles=True, angle_type='comparison', delim=" ") # # print(network_data_struct.data_array) # # print(network_data_struct.data_array) time_io_end = time.time() optimiser = LineSearchOptimiser(OptimHessianType.BFGS, max_iter=4) model = RecursiveLogitModelEstimation(network_data_struct, optimiser, observations_record=obs_mat) model.solve_for_optimal_beta() time_finish = time.time() print(f"IO time - {round(time_io_end - time_io_start, 3)}s") print(f"Algorithm time - {round(time_finish - time_io_end, 3)}s") print("got ", model.get_log_likelihood()[0]) print(f'{"matlab target":40}', 0.346581873680351) print(f'{"py result (matlab data ordering )":40}', 0.3465818736803499) print(f"{'py result (angles together ordering )':40}", 0.34658187368035076) # 0.3465818736803499
orig_indices = np.arange(0, node_max, 2) dest_indices = (orig_indices + 5) % node_max # sample every OD pair once # orig_indices = np.arange(0, node_max, 1) # dest_indices = np.arange(0, node_max, 1) 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_est = 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_est[0]:6.4f}, {beta_est[1]:6.4f}]") def test_est(): assert np.allclose([-1.02129578, -0.000175462809], beta_est) def test_sim(): assert obs == [[5, 0, 1, 5], [5, 2, 3, 4, 5],
warnings.simplefilter("error") # file ="ExampleTutorial"# "ExampleTutorial" from classical logicv2 # file = "ExampleTiny" # "ExampleNested" from classical logit v2, even smaller network time_io_start = time.time() subfolder = "ExampleTiny" # big data from classical v2 folder = join("Datasets", subfolder) time_io_end = time.time() obs_mat, attrs = load_standard_path_format_csv(folder, delim=" ", angles_included=False) incidence_mat, travel_times_mat = attrs data_list = [travel_times_mat, travel_times_mat] network_data_struct = ModelDataStruct(data_list, incidence_mat) optimiser = optimisers.LineSearchOptimiser(optimisers.OptimHessianType.BFGS, max_iter=4) model = RecursiveLogitModelEstimation(network_data_struct, optimiser, observations_record=obs_mat) model.solve_for_optimal_beta() time_finish = time.time() print(f"IO time - {round(time_io_end - time_io_start, 3)}s") print(f"Algorithm time - {round(time_finish - time_io_end, 3)}")
incidence_mat = (distances > 0).astype(int) network_struct = ModelDataStruct([distances], incidence_mat, data_array_names_debug=("distances", )) optimiser = optimisers.ScipyOptimiser(method='bfgs') # this did come from generate obs with beta = -0.4, but that code might change with fixes # obs = model.generate_observations(origin_indices=[0], # dest_indices=[1], # num_obs_per_pair=3, iter_cap=2000, rng_seed=1, # ) input_obs = [[1, 0, 1, 2, 1], [1, 0, 3, 0, 1], [1, 0, 1]] model = RecursiveLogitModelEstimation(network_struct, observations_record=input_obs, initial_beta=[-0.4], mu=1, optimiser=optimiser) class TestCases(object): def test_singleton_fails(self): with pytest.raises(TypeError) as excinfo: RecursiveLogitModelEstimation(network_struct, observations_record=input_obs[0], initial_beta=-0.4, mu=1, optimiser=optimiser) assert "List observation format must contain list of lists" in str( excinfo.value)