.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/mdcev_no_outside_good/plot_generalized_forecasting.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_mdcev_no_outside_good_plot_generalized_forecasting.py: File generalized_forecasting.py Michel Bierlaire, EPFL Fri Jul 25 2025, 17:05:32 Forecasting with a MDCEV model and the "generalized translated utility" specification. .. GENERATED FROM PYTHON SOURCE LINES 8-135 .. rst-class:: sphx-glr-script-out .. code-block:: none Example: generalized translated utility Forecasting observation 0 / 2 [10 draws] ============ Comparison =================== Brute force: {1: '29.4', 2: '426', 3: '34.2', 4: '10.9'} objective 180, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '29.4', 2: '426', 3: '34', 4: '10.9'} objective 180, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '36.2', 2: '407', 3: '42.6', 4: '14.1'} objective 180, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '36.2', 2: '407', 3: '42.6', 4: '14.1'} objective 180, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '14.1', 2: '427', 3: '43.6', 4: '15.1'} objective 199, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '14.1', 2: '427', 3: '44', 4: '15'} objective 199, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '16.7', 2: '437', 3: '33', 4: '13.7'} objective 183, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '16.7', 2: '437', 3: '33', 4: '13.7'} objective 183, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '34.9', 2: '429', 3: '26.3', 4: '10.1'} objective 169, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '35', 2: '429', 3: '26.3', 4: '10.1'} objective 169, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '16.5', 2: '406', 3: '57.8', 4: '20.2'} objective 195, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '16.4', 2: '406', 3: '57.7', 4: '20.2'} objective 195, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '10.6', 2: '452', 3: '30.4', 4: '7.34'} objective 221, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '10.6', 2: '452', 3: '30.4', 4: '7.34'} objective 221, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '8.84', 2: '436', 3: '47.8', 4: '7.77'} objective 239, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '8.84', 2: '436', 3: '47.8', 4: '7.76'} objective 239, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '21.2', 2: '432', 3: '35', 4: '12.1'} objective 171, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '21.2', 2: '432', 3: '35', 4: '12.2'} objective 171, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '34.5', 2: '378', 3: '76.7', 4: '10.4'} objective 200, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '34.6', 2: '378', 3: '77.3', 4: '10.4'} objective 200, constraint 500, choice set {1, 2, 3, 4} Forecasting observation 1 / 2 [10 draws] ============ Comparison =================== Brute force: {1: '8.17', 2: '455', 3: '31.5', 4: '5.67'} objective 244, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '8.09', 2: '455', 3: '31.7', 4: '5.66'} objective 244, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '24.3', 2: '401', 3: '61.1', 4: '13.9'} objective 177, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '24.3', 2: '401', 3: '61.1', 4: '13.9'} objective 177, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '37.5', 2: '411', 3: '42.1', 4: '9.52'} objective 210, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '37.5', 2: '411', 3: '42.1', 4: '9.5'} objective 210, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '12.1', 2: '443', 3: '33.7', 4: '10.8'} objective 206, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '12.1', 2: '443', 3: '33.7', 4: '10.8'} objective 206, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '26.2', 2: '415', 3: '46.4', 4: '12.3'} objective 176, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '26.2', 2: '415', 3: '46.4', 4: '12.3'} objective 176, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '51.5', 2: '378', 3: '60.6', 4: '9.91'} objective 195, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '51.4', 2: '378', 3: '60.6', 4: '9.9'} objective 195, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '9.94', 2: '452', 3: '32.5', 4: '5.42'} objective 248, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '9.94', 2: '452', 3: '32.5', 4: '5.42'} objective 248, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '19.9', 2: '450', 3: '16.3', 4: '14.1'} objective 273, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '19.9', 2: '450', 3: '16.3', 4: '14.1'} objective 273, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '26.4', 2: '423', 3: '45', 4: '5.76'} objective 210, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '26.4', 2: '423', 3: '44.8', 4: '5.77'} objective 210, constraint 500, choice set {1, 2, 3, 4} ============ Comparison =================== Brute force: {1: '31.7', 2: '353', 3: '107', 4: '8.95'} objective 237, constraint 500, choice set {1, 2, 3, 4} Analytical: {1: '31.6', 2: '353', 3: '107', 4: '9.06'} objective 237, constraint 500, choice set {1, 2, 3, 4} Forecasting observation 0 / 2 [2000 draws] Forecasting observation 1 / 2 [2000 draws] Execution time for 2000 draws with brute force algorithm: 20.5 seconds Forecasting observation 0 / 2 [2000 draws] Forecasting observation 1 / 2 [2000 draws] Execution time for 2000 draws with analytical algorithm: 0.694 seconds 1 2 3 4 count 2.000000e+03 2000.000000 2000.000000 2000.000000 mean 2.439792e+01 426.929193 35.366062 13.306824 std 2.538291e+01 35.357368 16.587736 7.251341 min 3.891492e-16 81.458056 0.000000 1.295123 25% 1.171063e+01 410.720424 24.893909 8.972792 50% 1.841752e+01 430.479544 33.310344 11.952136 75% 2.867985e+01 449.590603 43.615841 15.749595 max 3.735747e+02 498.346029 148.925689 107.930952 1 2 3 4 count 2000.000000 2000.000000 2000.000000 2000.000000 mean 24.384192 426.950104 35.359549 13.306155 std 25.317514 35.294916 16.592635 7.247057 min 0.000000 81.419828 0.000000 1.295016 25% 11.713627 410.828540 24.889764 8.973056 50% 18.428000 430.437278 33.315996 11.929500 75% 28.729678 449.570674 43.571832 15.739476 max 373.612178 498.346598 148.858217 107.952013 1 2 3 4 count 2.000000e+03 2000.000000 2000.000000 2000.000000 mean 2.751289e+01 418.312799 44.009956 10.164356 std 2.328927e+01 37.856372 21.457813 5.170982 min 7.601052e-16 110.756965 0.000000 0.000000 25% 1.347040e+01 398.061316 30.703689 6.847331 50% 2.173273e+01 422.534456 41.124187 9.315500 75% 3.405653e+01 444.519786 52.669373 12.297088 max 3.559648e+02 499.719068 256.407717 45.326247 1 2 3 4 count 2000.000000 2000.000000 2000.000000 2000.000000 mean 27.508135 418.335139 43.992754 10.163971 std 23.260041 37.821507 21.433937 5.170667 min 0.000000 110.851464 0.000000 0.000000 25% 13.483257 398.308127 30.761719 6.846872 50% 21.733449 422.483878 41.136792 9.310790 75% 34.060759 444.571312 52.697874 12.294282 max 355.797541 499.718958 254.564340 45.334397 | .. code-block:: Python import sys import time import numpy as np import pandas as pd from IPython.core.display_functions import display import biogeme.biogeme_logging as blog from biogeme.database import Database from biogeme.results_processing import EstimationResults from generalized_specification import the_generalized from process_data import database logger = blog.get_screen_logger(level=blog.INFO) logger.info('Example: generalized translated utility') result_file = 'saved_results/generalized.yaml' try: results = EstimationResults.from_yaml_file(filename=result_file) except FileNotFoundError as e: print(e) print(f'File {result_file} is missing.') sys.exit() the_generalized.estimation_results = results # % # We apply the model only on the first two rows of the database. two_rows_of_database: Database = database.extract_rows([0, 1]) # % budget_in_hours = 500 # % # # Validation # % # As the implementation is still experimental, we compare the result obtained by the bruteforce algorithm and # the analytical algorithm for a few draws. # Note that minor discrepancies between the outcome of the two algorithms are likely to occur, due to numerical # imprecision, inevitable in finite arithmetic. # However, if there are major differences, it should be reported. # % number_of_draws = 10 # % # We generate the draws epsilons = [ np.random.gumbel( loc=0, scale=1, size=(number_of_draws, the_generalized.number_of_alternatives) ) for _ in range(two_rows_of_database.num_rows()) ] # % # We first compare the results obtained from the brute force and the analytical algorithms, for each draw. the_generalized.validate_forecast( database=two_rows_of_database, total_budget=budget_in_hours, epsilons=epsilons ) # % # # Forecasting # We use a larger number of draws to obtain the forecast. # % number_of_draws = 2_000 # % # We generate the draws epsilons = [ np.random.gumbel( loc=0, scale=1, size=(number_of_draws, the_generalized.number_of_alternatives) ) for _ in range(two_rows_of_database.num_rows()) ] # % # First, the brute force algorithm. start_time = time.time() optimal_consumptions_brute_force: list[pd.DataFrame] = the_generalized.forecast( database=two_rows_of_database, total_budget=budget_in_hours, epsilons=epsilons, brute_force=True, ) end_time = time.time() # % print( f'Execution time for {number_of_draws} draws with brute force algorithm: {end_time-start_time:.3g} seconds' ) # % # Then, the analytical algorithm. start_time = time.time() optimal_consumptions_analytical: list[pd.DataFrame] = the_generalized.forecast( database=two_rows_of_database, total_budget=budget_in_hours, epsilons=epsilons, brute_force=False, ) end_time = time.time() # % print( f'Execution time for {number_of_draws} draws with analytical algorithm: {end_time-start_time:.3g} seconds' ) # % # Results for the first observation, brute force method display(optimal_consumptions_brute_force[0].describe()) # % # Results for the first observation, analytical method display(optimal_consumptions_analytical[0].describe()) # % # Results for the second observation, brute force method display(optimal_consumptions_brute_force[1].describe()) # % # Results for the second observation, analytical method display(optimal_consumptions_analytical[1].describe()) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 22.622 seconds) .. _sphx_glr_download_auto_examples_mdcev_no_outside_good_plot_generalized_forecasting.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_generalized_forecasting.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_generalized_forecasting.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_generalized_forecasting.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_