Assignment mechanics -------------------- Performing traffic assignment, or even just computing paths through a network is always a little different in each platform, and in AequilibraE is not different. The complexity in computing paths through a network comes from the fact that transportation models usually house networks for multiple transport modes, so the loads (links) available for a passenger car may be different than those available for a heavy truck, as it happens in practice. For this reason, all path computation in AequilibraE happens through Graph objects. While users can operate models by simply selecting the mode they want AequilibraE to create graphs for, Graph objects can also be manipulated in memory or even created from networks that are :ref:`NOT housed inside an AequilibraE model `. .. _aequilibrae-graphs: AequilibraE Graphs ~~~~~~~~~~~~~~~~~~ As mentioned above, AequilibraE's graphs are the backbone of path computation, skimming and Traffic Assignment. Besides handling the selection of links available to each mode in an AequilibraE model, graphs also handle the existence of bi-directional links with direction-specific characteristics (e.g. speed limit, congestion levels, tolls, etc.). The Graph object is rather complex, but the difference between the graph and the physical links are the availability of two class member variables consisting of Pandas DataFrames: the **network** and the **graph**. .. code-block:: python >>> from aequilibrae.paths import Graph >>> g = Graph() >>> g.network # doctest: +SKIP >>> g.graph # doctest: +SKIP Directionality ^^^^^^^^^^^^^^ Links in the Network table (the Pandas representation of the project's *Links* table) are potentially bi-directional, and the directions allowed for traversal are dictated by the field *direction*, where -1 and 1 denote only BA and AB traversal respectively and 0 denotes bi-directionality. Direction-specific fields must be coded in fields **_AB** and **_BA**, where the name of the field in the graph will be equal to the prefix of the directional fields. For example: The fields **free_flow_travel_time_AB** and **free_flow_travel_time_BA** provide the same metric (*free_flow_travel_time*) for each of the directions of a link, and the field of the graph used to set computations (e.g. field to minimize during path-finding, skimming, etc.) will be **free_flow_travel_time**. Graphs from a model ^^^^^^^^^^^^^^^^^^^ Building graphs directly from an AequilibraE model is the easiest option for beginners or when using AequilibraE in anger, as much of the setup is done by default. .. code-block:: python >>> project = create_example(project_path, "coquimbo") >>> project.network.build_graphs() # We build the graph for all modes >>> graph = project.network.graphs['c'] # we grab the graph for cars Manipulating graphs in memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As mentioned before, the AequilibraE Graph can be manipulated in memory, with all its components available for editing. One of the simple tools available directly in the API is a method call for excluding one or more links from the Graph, **which is done** **in place**. .. code-block:: python >>> graph.exclude_links([123, 975]) More sophisticated graph editing is also possible, but it is recommended that changes to be made in the network DataFrame. For example: .. code-block:: python # We can add fields to our graph >>> graph.network["link_type"] = project.network.links.data["link_type"] # And manipulate them >>> graph.network.loc[graph.network.link_type == "motorway", "speed_ab"] = 100 >>> graph.network.loc[graph.network.link_type == "motorway", "speed_ba"] = 100 Skimming settings ^^^^^^^^^^^^^^^^^ Skimming the field of a graph when computing shortest path or performing traffic assignment must be done by setting the skimming fields in the Graph object, and there are no limits (other than memory) to the number of fields that can be skimmed. .. code-block:: python >>> graph.set_skimming(["distance", "travel_time"]) Setting centroids ^^^^^^^^^^^^^^^^^ Like other elements of the AequilibraE Graph, the user can also manipulate the set of nodes interpreted by the software as centroids in the Graph itself. This brings the advantage of allowing the user to perform assignment of partial matrices, matrices of travel between arbitrary network nodes and to skim the network for an arbitrary number of centroids in parallel, which can be useful when using AequilibraE as part of more general analysis pipelines. As seen above, this is also necessary when the network has been manipulated in memory. **When setting regular network nodes as centroids, the user should take care in not blocking flows through "centroids".** .. code-block:: python >>> graph.prepare_graph(np.array([13, 169, 2197, 28561, 37123], np.int32)) >>> graph.set_blocked_centroid_flows(False) .. seealso:: * :func:`aequilibrae.paths.Graph` Class documentation * :func:`aequilibrae.paths.TransitGraph` Class documentation .. _traffic_assignment_procedure: .. include:: traffic_assignment_procedure.rst