.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_auto_examples/route_choice/plot_route_choice_basics.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_route_choice_plot_route_choice_basics.py: .. _example_usage_route_choice: Route Choice ============ In this example, we show how to perform route choice set generation using BFSLE and Link penalisation, for a city in La Serena Metropolitan Area in Chile. .. GENERATED FROM PYTHON SOURCE LINES 11-14 .. admonition:: References * :doc:`../../route_choice` .. GENERATED FROM PYTHON SOURCE LINES 16-22 .. seealso:: Several functions, methods, classes and modules are used in this example: * :func:`aequilibrae.paths.Graph` * :func:`aequilibrae.paths.RouteChoice` * :func:`aequilibrae.matrix.AequilibraeMatrix` .. GENERATED FROM PYTHON SOURCE LINES 24-33 .. code-block:: Python # Imports from uuid import uuid4 from tempfile import gettempdir from os.path import join from aequilibrae.utils.create_example import create_example .. GENERATED FROM PYTHON SOURCE LINES 35-41 .. code-block:: Python # We create the example project inside our temp folder fldr = join(gettempdir(), uuid4().hex) project = create_example(fldr, "coquimbo") .. GENERATED FROM PYTHON SOURCE LINES 42-45 .. code-block:: Python import logging import sys .. GENERATED FROM PYTHON SOURCE LINES 46-54 .. code-block:: Python # When the project opens, we can tell the logger to direct all messages to the terminal as well logger = project.logger stdout_handler = logging.StreamHandler(sys.stdout) formatter = logging.Formatter("%(asctime)s;%(levelname)s ; %(message)s") stdout_handler.setFormatter(formatter) logger.addHandler(stdout_handler) .. GENERATED FROM PYTHON SOURCE LINES 55-57 Model parameters ---------------- .. GENERATED FROM PYTHON SOURCE LINES 57-60 .. code-block:: Python import numpy as np .. GENERATED FROM PYTHON SOURCE LINES 61-64 We'll set the parameters for our route choice model. These are the parameters that will be used to calculate the utility of each path. In our example, the utility is equal to :math:`distance * theta`, and the path overlap factor (PSL) is equal to :math:`beta`. .. GENERATED FROM PYTHON SOURCE LINES 64-71 .. code-block:: Python # Distance factor theta = 0.00011 # PSL parameter beta = 1.1 .. GENERATED FROM PYTHON SOURCE LINES 72-73 Let's select a set of nodes of interest .. GENERATED FROM PYTHON SOURCE LINES 73-75 .. code-block:: Python nodes_of_interest = (71645, 74089, 77011, 79385) .. GENERATED FROM PYTHON SOURCE LINES 76-77 Let's build all graphs .. GENERATED FROM PYTHON SOURCE LINES 77-81 .. code-block:: Python project.network.build_graphs() # We get warnings that several fields in the project are filled with NaNs. # This is true, but we won't use those fields. .. rst-class:: sphx-glr-script-out .. code-block:: none 2025-07-25 10:28:11,339;WARNING ; Field(s) speed, travel_time, capacity, osm_id, lanes has(ve) at least one NaN value. Check your computations /home/runner/work/aequilibrae/aequilibrae/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph! [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133] warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids])) 2025-07-25 10:28:11,412;WARNING ; Field(s) speed, travel_time, capacity, osm_id, lanes has(ve) at least one NaN value. Check your computations 2025-07-25 10:28:11,499;WARNING ; Field(s) speed, travel_time, capacity, osm_id, lanes has(ve) at least one NaN value. Check your computations 2025-07-25 10:28:11,586;WARNING ; Field(s) speed, travel_time, capacity, osm_id, lanes has(ve) at least one NaN value. Check your computations /home/runner/work/aequilibrae/aequilibrae/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph! [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133] warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids])) .. GENERATED FROM PYTHON SOURCE LINES 82-83 We also see what graphs are available .. GENERATED FROM PYTHON SOURCE LINES 83-85 .. code-block:: Python project.network.graphs.keys() .. rst-class:: sphx-glr-script-out .. code-block:: none dict_keys(['b', 'c', 't', 'w']) .. GENERATED FROM PYTHON SOURCE LINES 86-87 We grab the graph for cars .. GENERATED FROM PYTHON SOURCE LINES 87-98 .. code-block:: Python graph = project.network.graphs["c"] # Let's say that utility is just a function of distance, so we build our 'utility' field as distance * theta graph.network = graph.network.assign(utility=graph.network.distance * theta) # Prepare the graph with all nodes of interest as centroids graph.prepare_graph(np.array(nodes_of_interest)) # And set the cost of the graph the as the utility field just created graph.set_graph("utility") .. rst-class:: sphx-glr-script-out .. code-block:: none 2025-07-25 10:28:11,655;WARNING ; Field(s) speed, travel_time, capacity, osm_id, lanes has(ve) at least one NaN value. Check your computations .. GENERATED FROM PYTHON SOURCE LINES 99-102 Mock demand matrix ------------------ We'll create a mock demand matrix with demand 1 for every zone and prepare it for computation. .. GENERATED FROM PYTHON SOURCE LINES 102-113 .. code-block:: Python from aequilibrae.matrix import AequilibraeMatrix names_list = ["demand", "5x demand"] mat = AequilibraeMatrix() mat.create_empty(zones=graph.num_zones, matrix_names=names_list, memory_only=True) mat.index = graph.centroids[:] mat.matrices[:, :, 0] = np.full((graph.num_zones, graph.num_zones), 10.0) mat.matrices[:, :, 1] = np.full((graph.num_zones, graph.num_zones), 50.0) mat.computational_view() .. GENERATED FROM PYTHON SOURCE LINES 114-117 Create plot function -------------------- Before dive into the Route Choice class, let's define a function to plot assignment results. .. GENERATED FROM PYTHON SOURCE LINES 117-119 .. code-block:: Python import folium .. GENERATED FROM PYTHON SOURCE LINES 120-141 .. code-block:: Python def plot_results(link_loads): link_loads = link_loads[link_loads["demand_tot"] > 0] max_load = link_loads["demand_tot"].max() links = project.network.links.data loaded_links = links.merge(link_loads, on="link_id", how="inner") loads_lyr = folium.FeatureGroup("link_loads") # Maximum thickness we would like is probably a 10, so let's make sure we don't go over that factor = 10 / max_load return loaded_links.explore( color="red", style_kwds={ "style_function": lambda x: { "weight": x["properties"]["demand_tot"] * factor, } }, ) .. GENERATED FROM PYTHON SOURCE LINES 142-145 Route Choice class ------------------ Here we'll construct and use the Route Choice class to generate our route sets .. GENERATED FROM PYTHON SOURCE LINES 145-147 .. code-block:: Python from aequilibrae.paths import RouteChoice .. GENERATED FROM PYTHON SOURCE LINES 148-150 This object construct might take a minute depending on the size of the graph due to the construction of the compressed link to network link mapping that's required. This is a one time operation per graph and is cached. .. GENERATED FROM PYTHON SOURCE LINES 150-155 .. code-block:: Python rc = RouteChoice(graph) # Let's check the default parameters for the Route Choice class print(rc.default_parameters) .. rst-class:: sphx-glr-script-out .. code-block:: none {'generic': {'seed': 0, 'max_routes': 0, 'max_depth': 0, 'max_misses': 100, 'penalty': 1.01, 'cutoff_prob': 0.0, 'beta': 1.0, 'store_results': True}, 'link-penalisation': {}, 'bfsle': {'penalty': 1.0}} .. GENERATED FROM PYTHON SOURCE LINES 156-157 Let's add the demand. If it's not provided, link loading cannot be preformed. .. GENERATED FROM PYTHON SOURCE LINES 157-159 .. code-block:: Python rc.add_demand(mat) .. GENERATED FROM PYTHON SOURCE LINES 160-161 It is highly recommended to set either ``max_routes`` or ``max_depth`` to prevent runaway results. .. GENERATED FROM PYTHON SOURCE LINES 161-163 .. code-block:: Python rc.set_choice_set_generation("bfsle", max_routes=5) .. GENERATED FROM PYTHON SOURCE LINES 164-166 We can now perform a computation for single OD pair if we'd like. Here we do one between the first and last centroid as well as an assignment. .. GENERATED FROM PYTHON SOURCE LINES 166-169 .. code-block:: Python results = rc.execute_single(77011, 74089, demand=1.0) print(results[0]) .. rst-class:: sphx-glr-script-out .. code-block:: none (-24222, 30332, 30333, -10435, 30068, 30069, 14198, 14199, 31161, 30928, 30929, 30930, 30931, 24172, 30878, 30879, 30880, 30881, 30882, 30883, 30884, 30885, 30886, 30887, 30888, 30889, 30890, 30891, 5179, 5180, 5181, 5182, -26463, -26462, -26461, -26460, -26459, -26458, -26457, -26456, -26480, 3341, 3342, 3339, 9509, 9510, 9511, 9512, 18487, 14972, 14973, 32692, 32693, 32694, 2300, 2301, 33715, 19978, 19979, -19977, -19976, -19975, -19974, -19973, -19972, -19971, -19970, 22082, 22080, 5351, 5352, 2280, 2281, 2282, 575, 576, 577, 578, 579, 536, 537, 538, 539, 540, 541, 15406, 15407, 15408, 553, 552, 633, 634, 635, 630, 631, 632, 623, 624, 625, 626, 471, 5363, 34169, 34170, 34171, 34785, -6466, -6465, 29938, 29939, 29940, 29941, 1446, 1447, 1448, 1449, 1450, 939, 940, 941, 9840, 9841, -26314, -26313, -26312, -26311, -26310, -26309, -26308, -26307, -26306, -26305, -26304, -26303, -26302, -26301, -26300, 34079, 34147, 29962, -26422, -26421, -26420, -765, -764, -763, -762, -761, -760, 736, 10973, 10974, 10975, 725, -10972, 727, 728, 26424, 733, 734, -29899, -20970, -20969, -20968, -20967, -20966, -20965, -20964, -20963, -20962, 9584, 9583, -20981, 21398, 20982, 34208, 35, 36, 59, 60, 61, 22363, 22364, 22365, 22366, 22367, 28958, 28959, 28960, 28961, 28962, 28805, 28806, 28807, 28808, 28809, 28810, 28827, 28828, 28829, 28830, 28874) .. GENERATED FROM PYTHON SOURCE LINES 170-171 Because we asked it to also perform an assignment we can access the various results from that. .. GENERATED FROM PYTHON SOURCE LINES 171-174 .. code-block:: Python res = rc.get_results() res.head() .. raw:: html
origin id destination id cost mask path overlap probability route set
0 77011 74089 1.907420 1 0.386507 0.231745 [-24222, 30332, 30333, -10435, 30068, 30069, 1...
1 77011 74089 1.890617 1 0.287132 0.175078 [-24222, 30332, 30333, -10435, 30068, 30069, 1...
2 77011 74089 1.896528 1 0.304541 0.184599 [24223, 31635, 31636, 31637, 31638, 31639, 316...
3 77011 74089 1.909910 1 0.430542 0.257506 [-24222, 30332, 30333, -10435, 30068, 30069, 1...
4 77011 74089 1.886882 1 0.246836 0.151071 [-24222, 30332, 30333, -10435, 30068, 30069, 1...


.. GENERATED FROM PYTHON SOURCE LINES 175-177 .. code-block:: Python plot_results(rc.get_load_results()) .. raw:: html
Make this Notebook Trusted to load map: File -> Trust Notebook


.. GENERATED FROM PYTHON SOURCE LINES 178-182 Batch operations ---------------- To perform a batch operation we need to prepare the object first. We can either provide a list of tuple of the OD pairs we'd like to use, or we can provided a 1D list and the generation will be run on all permutations. .. GENERATED FROM PYTHON SOURCE LINES 182-184 .. code-block:: Python rc.prepare() .. GENERATED FROM PYTHON SOURCE LINES 185-186 Now we can perform a batch computation with an assignment .. GENERATED FROM PYTHON SOURCE LINES 186-190 .. code-block:: Python rc.execute(perform_assignment=True) res = rc.get_results() res.head() .. raw:: html
origin id destination id cost mask path overlap probability route set
0 71645 74089 0.607017 1 0.384514 0.204478 [-19550, -19549, -19548, -19547, -19546, -1954...
1 71645 74089 0.607425 1 0.273951 0.145623 [-19550, -19549, -19548, -19547, -19546, -1954...
2 71645 74089 0.622079 1 0.544362 0.285155 [-19550, -19549, -19548, -19547, -19546, -1954...
3 71645 74089 0.611944 1 0.443492 0.234682 [-19550, -19549, -19548, -19547, -19546, -1954...
4 71645 74089 0.604384 1 0.243935 0.130063 [-19550, -19549, -19548, -19547, -19546, -1954...


.. GENERATED FROM PYTHON SOURCE LINES 191-192 Since we provided a matrix initially we can also perform link loading based on our assignment results. .. GENERATED FROM PYTHON SOURCE LINES 192-194 .. code-block:: Python rc.get_load_results() .. raw:: html
demand_ab demand_ba 5x demand_ab 5x demand_ba demand_tot 5x demand_tot
link_id
1 0.0 0.0 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 0.0 0.0
12 0.0 0.0 0.0 0.0 0.0 0.0
13 0.0 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ...
34938 0.0 0.0 0.0 0.0 0.0 0.0
34939 0.0 0.0 0.0 0.0 0.0 0.0
34940 0.0 0.0 0.0 0.0 0.0 0.0
34941 0.0 0.0 0.0 0.0 0.0 0.0
34942 0.0 0.0 0.0 0.0 0.0 0.0

19983 rows × 6 columns



.. GENERATED FROM PYTHON SOURCE LINES 195-196 We can plot these as well .. GENERATED FROM PYTHON SOURCE LINES 196-198 .. code-block:: Python plot_results(rc.get_load_results()) .. raw:: html
Make this Notebook Trusted to load map: File -> Trust Notebook


.. GENERATED FROM PYTHON SOURCE LINES 199-204 Select link analysis -------------------- We can also enable select link analysis by providing the links and the directions that we are interested in. Here we set the select link to trigger when (7369, 1) and (20983, 1) is utilised in "sl1" and "sl2" when (7369, 1) is utilised. .. GENERATED FROM PYTHON SOURCE LINES 204-207 .. code-block:: Python rc.set_select_links({"sl1": [[(7369, 1), (20983, 1)]], "sl2": [[(7369, 1)]]}) rc.execute(perform_assignment=True) .. GENERATED FROM PYTHON SOURCE LINES 208-209 We can get then the results in a Pandas DataFrame for both the network. .. GENERATED FROM PYTHON SOURCE LINES 209-212 .. code-block:: Python sl = rc.get_select_link_loading_results() sl .. raw:: html
demand_sl1_ab demand_sl1_ba 5x demand_sl1_ab 5x demand_sl1_ba demand_sl2_ab demand_sl2_ba 5x demand_sl2_ab 5x demand_sl2_ba demand_sl1_tot 5x demand_sl1_tot demand_sl2_tot 5x demand_sl2_tot
link_id
1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
12 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
13 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ...
34938 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
34939 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
34940 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
34941 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
34942 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

19983 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 213-216 We can also access the OD matrices for this link loading. These matrices are sparse and can be converted to SciPy sparse matrices for ease of use. They're stored in a dictionary where the key is the matrix name concatenated with the select link set name via an underscore. .. GENERATED FROM PYTHON SOURCE LINES 216-218 .. code-block:: Python rc.get_select_link_od_matrix_results() .. rst-class:: sphx-glr-script-out .. code-block:: none {'sl1': {'demand': , '5x demand': }, 'sl2': {'demand': , '5x demand': }} .. GENERATED FROM PYTHON SOURCE LINES 219-222 .. code-block:: Python od_matrix = rc.get_select_link_od_matrix_results()["sl1"]["demand"] od_matrix.to_scipy().toarray() .. rst-class:: sphx-glr-script-out .. code-block:: none array([[0. , 0. , 0. , 3.04610785], [0. , 0. , 0. , 0. ], [0. , 0. , 0. , 0. ], [0. , 0. , 0. , 0. ]]) .. GENERATED FROM PYTHON SOURCE LINES 223-224 .. code-block:: Python project.close() .. rst-class:: sphx-glr-script-out .. code-block:: none WARNING:aequilibrae:This project at /tmp/a943fc597b2b46888ae2dcdc5a39ee30 is already closed .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.326 seconds) .. _sphx_glr_download__auto_examples_route_choice_plot_route_choice_basics.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_route_choice_basics.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_route_choice_basics.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_route_choice_basics.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_