0

I have written a piece of code however it takes an enormous amount of time to run and I don't know how to make it faster. Can anyone help me?

Here is the code:

import networkx as nx
import matplotlib.pyplot as plt
import osmnx as ox
import pandas as pd
from shapely.wkt import loads as load_wkt
import numpy as np
import matplotlib.cm as cm
ox.config(log_console=True, use_cache=True)
import matplotlib as mpl
import random as rd



distrito = ['Lisbon District', 'Setúbal District']
G = ox.graph_from_place(distrito, network_type='all_private')
hospitals = ox.pois_from_place(city, amenities=['hospital'])

coord_1 = (38.74817825481225, -9.160815118526642)  
coord_2 = (38.74110711410615, -9.152159572392323)  
coord_3 = (38.7287248180068, -9.139114834357233) 
target_1 = ox.get_nearest_node(G, coord_1)
target_2 = ox.get_nearest_node(G, coord_2)
target_3 = ox.get_nearest_node(G, coord_3)

nodes, edges = ox.graph_to_gdfs(G, nodes=True, edges=True)  # Transform nodes and edges into Geodataframes


travel_speed = 20  # km/h
meters_per_minute = travel_speed * 1000 / 60

nodes['shortest_route_length_to_target'] = 0
route_lengths = []
list_nodes = []
i = 0
# print(G.edges(data=True))
for u, v, k, data in G.edges(data=True, keys=True):

    data['time'] = data['length'] / meters_per_minute

for node in G.nodes:
    try:
        route_length_1 = nx.shortest_path_length(G, node, target_1, weight='time')
        route_length_2 = nx.shortest_path_length(G, node, target_3, weight='time')
        if route_length_1 < route_length_2:
            route_lengths.append(route_length_1)
            nodes['shortest_route_length_to_target'][node] = route_length_1
            list_nodes.append(node)
        elif route_length_1 > route_length_2:
            route_lengths.append(route_length_2)
            nodes['shortest_route_length_to_target'][node] = route_length_2
            list_nodes.append(node)

    except nx.exception.NetworkXNoPath:
        continue

In general up until the for node in G.nodes: the code runs quite fast. It's this for cycle that is taking far too long.

Thank you in advance.

yatu
  • 86,083
  • 12
  • 84
  • 139
DPM
  • 845
  • 7
  • 33

1 Answers1

1

You should profile your code to identify exactly what is slow. With high confidence I would assume that it is not your if conditions within that for loop (though they could be optimized a bit more). It looks like approximately all of your time complexity comes from trying to solve two shortest paths within each for loop run. This is inherently slow.

You could try calculating your shortest paths with something like igraph, which would be faster.

Note also that you do not need to manually calculate edge traversal times as of OSMnx v0.13.0.

gboeing
  • 5,691
  • 2
  • 15
  • 41
  • Thank you for your answer. I am trying to implement your suggestions and have two questions: can I use ox.plot_graph of the igraph? The other question is: after calculating the times attribute using what you said, what is the name of the attribute created so I can access it? – DPM Jun 01 '20 at 16:08
  • 1
    Both your questions are answered in the documentation. 1) [plot_graph](https://osmnx.readthedocs.io/en/stable/osmnx.html#osmnx.plot.plot_graph) takes a networkx MultiDiGraph, not an igraph graph, so no. 2) the [add_edge_travel_times](https://osmnx.readthedocs.io/en/stable/osmnx.html#osmnx.speed.add_edge_travel_times) function adds "edge travel time (seconds) to graph as new travel_time edge attributes." – gboeing Jun 02 '20 at 18:08