Computing paths over the network

Computing paths over the network#

In this example we show how to use the Router from the POLARIS API to compute paths over the network

Imports#

sphinx_gallery_thumbnail_path = “../../examples/working_with_models/routed_path.png”

from pathlib import Path

import folium
import numpy as np

from polaris import Polaris
from polaris.utils.database.db_utils import read_and_close
from polaris.utils.testing.temp_model import TempModel

Data Sources#

Open the demand database for analysis

model_fldr = TempModel("Grid")

project = Polaris.from_dir(Path(model_fldr))

# If you have a custom build batch_router.dll you can specify it via this command
# project.set_router_lib(Path('/home/user/bin/batch_router.so'))

router = project.router

We can first compute the path between two links The departure is in seconds, and we need to provide both the links and their directions (0 for AB and 1 for BA) If we don’t provide the link directions, they default to 0

path = router.route(origins=(678, 1), destinations=(656, 0), modes=0, departure_times=72000, ods_are="links")

# Then we can see the total travel time
print(path.travel_time)

# Then we can see the list of links (linkid/dir) that were traversed
print(path.links)

# And the cumulative travel time at each link
print(path.cumulative_time)
1686.0
[(678, 1), (677, 1), (426, 1), (425, 1), (127, 1), (498, 1), (497, 1), (496, 1), (495, 1), (494, 1), (35, 0), (36, 0), (38, 0), (297, 0), (298, 0), (299, 0), (300, 0), (301, 0), (302, 0), (303, 0), (304, 0), (305, 0), (59, 0), (57, 1), (356, 0), (357, 0), (358, 0), (625, 0), (626, 0), (627, 0), (628, 0), (629, 0), (630, 0), (640, 0), (641, 0), (642, 0), (643, 0), (655, 0), (656, 0)]
[  52.  104.  160.  216.  265.  330.  395.  440.  485.  530.  568.  597.
  626.  659.  692.  725.  758.  791.  824.  857.  890.  923.  984. 1000.
 1045. 1090. 1135. 1177. 1219. 1261. 1301. 1341. 1381. 1444. 1507. 1570.
 1633. 1686. 1739.]

We can also compute the path between two locations In this case, the link and direction associated with the locations will be used as Origin and destination If we don’t provide a departure time, 8AM (28800) is used If we don’t provide a mode, 0 (SOV car) is used

new_path = router.route(90, 740)
print(new_path)
Polaris Path:
  Origin: 90
  Destination: 740
  Travel Time: 1632.0
  Departure Time: 28800
  Links: [(574, 0), (137, 0), (543, 0), (544, 0), (545, 0), (546, 0), (547, 0), (53, 1), (54, 0), (320, 0), (321, 0), (322, 0), (323, 0), (324, 0), (325, 0), (326, 0), (327, 0), (328, 0), (331, 0), (332, 0), (333, 0), (334, 0), (335, 0), (336, 0), (337, 0), (338, 0), (339, 0), (340, 0), (341, 0), (34, 0), (40, 0), (41, 0), (590, 0), (591, 0), (592, 0), (593, 0), (594, 0), (595, 0), (440, 0), (441, 0), (442, 0)]
  Cumulative Time: [  58.  106.  166.  226.  273.  320.  367.  413.  450.  483.  516.  549.
  582.  615.  648.  681.  714.  747.  770.  793.  826.  859.  892.  925.
  958.  991. 1024. 1057. 1090. 1121. 1148. 1193. 1246. 1299. 1352. 1406.
 1460. 1514. 1573. 1632. 1691.]

We can compute the multi-modal travel time between two locations. We do need to input the mode, however

multimodal_path = router.route(90, 740, modes=1)
print(f"Multimodal travel time: {multimodal_path.travel_time}")
print(f"Car travel time: {new_path.travel_time}")
print(multimodal_path)
Multimodal travel time: 1632.0
Car travel time: 1632.0
Polaris Path:
  Origin: 90
  Destination: 740
  Travel Time: 1632.0
  Departure Time: 28800
  Links: [(574, 0), (137, 0), (543, 0), (544, 0), (545, 0), (546, 0), (547, 0), (53, 1), (54, 0), (320, 0), (321, 0), (322, 0), (323, 0), (324, 0), (325, 0), (326, 0), (327, 0), (328, 0), (331, 0), (332, 0), (333, 0), (334, 0), (335, 0), (336, 0), (337, 0), (338, 0), (339, 0), (340, 0), (341, 0), (34, 0), (40, 0), (41, 0), (590, 0), (591, 0), (592, 0), (593, 0), (594, 0), (595, 0), (440, 0), (441, 0), (442, 0)]
  Cumulative Time: [ 1.23120375e+05 -7.35426767e+15  1.86883500e+05  4.62489406e-36
  4.62493639e-36  2.74622129e-39 -7.35426767e+15 -7.35426767e+15
  0.00000000e+00  1.12339203e+02  0.00000000e+00  5.96087646e+02
  2.10194770e-44 -7.35426767e+15  2.10194770e-44  2.10194770e-44
  4.45251367e+03  3.15292154e-43  4.62428493e-44  4.62428493e-44
  3.37712930e-43  6.29183010e-43  6.51603786e-43  4.62428493e-44
  4.62428493e-44  6.29183010e-43  4.62428493e-44  6.29183010e-43
  6.29183010e-43  1.99553250e+05  6.68367500e+04  9.37782000e+05
  1.67026250e+05  2.45597750e+05 -1.02542649e-29  5.60007000e+05
  1.24852250e+05  2.51579000e+05  1.23115500e+05 -1.02542770e-29
 -1.02542529e-29]

And we can plot this path on the network

data = project.network.tables
with read_and_close(project.supply_file, spatial=True) as conn:
    links_layer = data.get("Link", conn).to_crs(4326)
    loc_layer = data.get("Location", conn).to_crs(4326)

loc_layer = loc_layer[loc_layer.location.isin([90, 740])]
path_layer = links_layer.query(f"link in @new_path.link_ids")

centr = path_layer.union_all().centroid

map = links_layer.explore(color="blue", style_kwds={"weight": 2}, tool_tip="link", name="links")
map = path_layer.explore(m=map, color="red", style_kwds={"weight": 5}, tool_tip="link", name="path")

map = loc_layer.explore(
    m=map,
    color="black",
    tool_tip="location",
    style_kwds={"radius": 6, "fillOpacity": 1.0, "fillColor": "black", "fill": True},
    name="Locations",
)
folium.LayerControl().add_to(map)  # Add a layer control button to our map

map
Make this Notebook Trusted to load map: File -> Trust Notebook


Total running time of the script: (0 minutes 1.939 seconds)

Gallery generated by Sphinx-Gallery