.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/swissmetro/plot_b11cnl.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_swissmetro_plot_b11cnl.py: Cross-nested logit ================== Example of a cross-nested logit model with two nests: - one with existing alternatives (car and train), - one with public transportation alternatives (train and Swissmetro) Michel Bierlaire, EPFL Sat Jun 21 2025, 16:33:38 .. GENERATED FROM PYTHON SOURCE LINES 15-24 .. code-block:: Python import biogeme.biogeme_logging as blog from IPython.core.display_functions import display from biogeme.biogeme import BIOGEME from biogeme.expressions import Beta from biogeme.models import logcnl from biogeme.nests import NestsForCrossNestedLogit, OneNestForCrossNestedLogit from biogeme.results_processing import get_pandas_estimated_parameters .. GENERATED FROM PYTHON SOURCE LINES 25-26 See the data processing script: :ref:`swissmetro_data`. .. GENERATED FROM PYTHON SOURCE LINES 26-46 .. code-block:: Python from swissmetro_data import ( CAR_AV_SP, CAR_CO_SCALED, CAR_TT_SCALED, CHOICE, GA, SM_AV, SM_COST_SCALED, SM_HE, SM_TT_SCALED, TRAIN_AV_SP, TRAIN_COST_SCALED, TRAIN_HE, TRAIN_TT_SCALED, database, ) logger = blog.get_screen_logger(level=blog.INFO) logger.info('Example b11cnl.py') .. rst-class:: sphx-glr-script-out .. code-block:: none Example b11cnl.py .. GENERATED FROM PYTHON SOURCE LINES 47-48 Parameters to be estimated. .. GENERATED FROM PYTHON SOURCE LINES 48-60 .. code-block:: Python asc_car = Beta('asc_car', 0, None, None, 0) asc_train = Beta('asc_train', 0, None, None, 0) asc_sm = Beta('asc_sm', 0, None, None, 1) b_time_swissmetro = Beta('b_time_swissmetro', 0, None, None, 0) b_time_train = Beta('b_time_train', 0, None, None, 0) b_time_car = Beta('b_time_car', 0, None, None, 0) b_cost = Beta('b_cost', 0, None, None, 0) b_headway_swissmetro = Beta('b_headway_swissmetro', 0, None, None, 0) b_headway_train = Beta('b_headway_train', 0, None, None, 0) ga_train = Beta('ga_train', 0, None, None, 0) ga_swissmetro = Beta('ga_swissmetro', 0, None, None, 0) .. GENERATED FROM PYTHON SOURCE LINES 61-64 .. code-block:: Python existing_nest_parameter = Beta('existing_nest_parameter', 1, 1, 5, 0) public_nest_parameter = Beta('public_nest_parameter', 1, 1, 5, 0) .. GENERATED FROM PYTHON SOURCE LINES 65-66 Nest membership parameters. .. GENERATED FROM PYTHON SOURCE LINES 66-69 .. code-block:: Python alpha_existing = Beta('alpha_existing', 0.5, 0, 1, 0) alpha_public = 1 - alpha_existing .. GENERATED FROM PYTHON SOURCE LINES 70-71 Definition of the utility functions .. GENERATED FROM PYTHON SOURCE LINES 71-87 .. code-block:: Python v_train = ( asc_train + b_time_train * TRAIN_TT_SCALED + b_cost * TRAIN_COST_SCALED + b_headway_train * TRAIN_HE + ga_train * GA ) v_swissmetro = ( asc_sm + b_time_swissmetro * SM_TT_SCALED + b_cost * SM_COST_SCALED + b_headway_swissmetro * SM_HE + ga_swissmetro * GA ) v_car = asc_car + b_time_car * CAR_TT_SCALED + b_cost * CAR_CO_SCALED .. GENERATED FROM PYTHON SOURCE LINES 88-89 Associate utility functions with the numbering of alternatives .. GENERATED FROM PYTHON SOURCE LINES 89-91 .. code-block:: Python v = {1: v_train, 2: v_swissmetro, 3: v_car} .. GENERATED FROM PYTHON SOURCE LINES 92-93 Associate the availability conditions with the alternatives .. GENERATED FROM PYTHON SOURCE LINES 93-95 .. code-block:: Python av = {1: TRAIN_AV_SP, 2: SM_AV, 3: CAR_AV_SP} .. GENERATED FROM PYTHON SOURCE LINES 96-97 Definition of nests. .. GENERATED FROM PYTHON SOURCE LINES 97-114 .. code-block:: Python nest_existing = OneNestForCrossNestedLogit( nest_param=existing_nest_parameter, dict_of_alpha={1: alpha_existing, 2: 0.0, 3: 1.0}, name='existing', ) nest_public = OneNestForCrossNestedLogit( nest_param=public_nest_parameter, dict_of_alpha={1: alpha_public, 2: 1.0, 3: 0.0}, name='public', ) nests = NestsForCrossNestedLogit( choice_set=[1, 2, 3], tuple_of_nests=(nest_existing, nest_public) ) .. GENERATED FROM PYTHON SOURCE LINES 115-116 The choice model is a cross-nested logit, with availability conditions. .. GENERATED FROM PYTHON SOURCE LINES 116-118 .. code-block:: Python log_probability = logcnl(v, av, nests, CHOICE) .. GENERATED FROM PYTHON SOURCE LINES 119-120 Create the Biogeme object .. GENERATED FROM PYTHON SOURCE LINES 120-123 .. code-block:: Python the_biogeme = BIOGEME(database, log_probability) the_biogeme.model_name = 'b11cnl' .. rst-class:: sphx-glr-script-out .. code-block:: none Biogeme parameters read from biogeme.toml. .. GENERATED FROM PYTHON SOURCE LINES 124-125 Estimate the parameters. .. GENERATED FROM PYTHON SOURCE LINES 125-127 .. code-block:: Python results = the_biogeme.estimate() .. rst-class:: sphx-glr-script-out .. code-block:: none *** Initial values of the parameters are obtained from the file __b11cnl.iter Parameter values restored from __b11cnl.iter Starting values for the algorithm: {'ASC_TRAIN': -2.9802322387695312e-08, 'B_TIME': -2.9802322387695312e-08, 'B_COST': -2.9802322387695312e-08, 'ALPHA_EXISTING': 0.5, 'MU_EXISTING': 1.0000000298023224, 'ASC_CAR': -2.9802322387695312e-08, 'MU_PUBLIC': 1.0000000298023224} As the model is rather complex, we cancel the calculation of second derivatives. If you want to control the parameters, change the algorithm from "automatic" to "simple_bounds" in the TOML file. Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds] ** Optimization: BFGS with trust region for simple bounds Iter. asc_train b_time_train b_cost b_headway_train ga_train alpha_existing existing_nest_p b_time_swissmet b_headway_swiss ga_swissmetro asc_car b_time_car public_nest_par Function Relgrad Radius Rho 0 0 0 0 0 0 0.5 1 0 0 0 0 0 1 7e+03 16 0.5 -0.35 - 1 0 0 0 0 0 0.5 1 0 0 0 0 0 1 7e+03 16 0.25 -0.33 - 2 0 0 0 0 0 0.5 1 0 0 0 0 0 1 7e+03 16 0.12 -0.29 - 3 0 0 0 0 0 0.5 1 0 0 0 0 0 1 7e+03 16 0.062 -0.21 - 4 0 0 0 0 0 0.5 1 0 0 0 0 0 1 7e+03 16 0.031 -0.075 - 5 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.031 0.12 + 6 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.016 -0.071 - 7 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.0078 -0.064 - 8 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.0039 -1 - 9 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.002 -0.83 - 10 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.00098 -0.74 - 11 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.00049 -0.69 - 12 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.00024 -0.68 - 13 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 0.00012 -0.67 - 14 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 6.1e-05 -0.66 - 15 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 3.1e-05 -0.66 - 16 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 1.5e-05 -0.66 - 17 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 7.6e-06 -0.66 - 18 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 3.8e-06 -0.66 - 19 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 1.9e-06 -0.66 - 20 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 9.5e-07 -0.66 - 21 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 4.8e-07 -0.66 - 22 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 2.4e-07 -0.66 - 23 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 1.2e-07 -0.66 - 24 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 6e-08 -0.66 - 25 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 3e-08 -0.66 - 26 -0.031 -0.031 -0.031 -0.031 0.031 0.5 1 0.031 0.031 0.031 -0.031 -0.031 1 6.4e+03 4.1 1.5e-08 -0.66 - Optimization algorithm has *not* converged. Algorithm: BFGS with trust region for simple bound constraints Cause of termination: Trust region is too small: 1.4901161193847656e-08 Number of iterations: 27 Proportion of Hessian calculation: 0/2 = 0.0% Optimization time: 0:00:04.671759 Calculate second derivatives and BHHH It seems that the optimization algorithm did not converge. Therefore, the results may not correspond to the maximum likelihood estimator. Check the specification of the model, or the criteria for convergence of the algorithm. File b11cnl~01.html has been generated. File b11cnl~01.yaml has been generated. .. GENERATED FROM PYTHON SOURCE LINES 128-130 .. code-block:: Python print(results.short_summary()) .. rst-class:: sphx-glr-script-out .. code-block:: none Results for model b11cnl Nbr of parameters: 13 Sample size: 6768 Excluded data: 3960 Final log likelihood: -6433.937 Akaike Information Criterion: 12893.87 Bayesian Information Criterion: 12982.53 .. GENERATED FROM PYTHON SOURCE LINES 131-133 .. code-block:: Python pandas_results = get_pandas_estimated_parameters(estimation_results=results) display(pandas_results) .. rst-class:: sphx-glr-script-out .. code-block:: none Name Value ... Robust p-value Active bound 0 asc_train -0.03125 ... 9.223247e-01 False 1 b_time_train -0.03125 ... 7.897335e-01 False 2 b_cost -0.03125 ... 4.847544e-01 False 3 b_headway_train -0.03125 ... 6.834533e-13 False 4 ga_train 0.03125 ... 9.182626e-01 False 5 alpha_existing 0.50000 ... 0.000000e+00 False 6 existing_nest_parameter 1.03125 ... 0.000000e+00 False 7 b_time_swissmetro 0.03125 ... 6.290057e-01 False 8 b_headway_swissmetro 0.03125 ... 6.661338e-16 False 9 ga_swissmetro 0.03125 ... 7.734929e-01 False 10 asc_car -0.03125 ... 7.682654e-01 False 11 b_time_car -0.03125 ... 4.664229e-01 False 12 public_nest_parameter 1.00000 ... 0.000000e+00 True [13 rows x 6 columns] .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 25.115 seconds) .. _sphx_glr_download_auto_examples_swissmetro_plot_b11cnl.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_b11cnl.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_b11cnl.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_b11cnl.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_