Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

My code takes a long time for big graphs.

How can I make it faster?

I'm trying to calculate the shortest path for 3 path's using queue but for big input my program crashes.

I'm stuck here. Can someone help me?

def bfs(graph, start, end):
    queue = []
    queue.append([start])
    while queue:
        path = queue.pop(0)
        node = path[-1]
        if node == end:
            return len(path)
        for adjacent in graph.get(node, []):
            new_path = list(path)
            new_path.append(adjacent)
            queue.append(new_path)

def all_possiblities():
    possiblites = []
    for clinique in cliniques[0][1:]:
        for clinique2 in cliniques[1][1:]:
            path1 = bfs(sorted_connections, a, clinique)
            path2 = bfs(sorted_connections, clinique, clinique2)
            path3 = bfs(sorted_connections, clinique2, b)
            total_path = path1 + path2 + path3
            possiblites.append(total_path)
    return min(possiblites) - 2

if __name__ == '__main__':
    input_values = input().split()
    n, m = int(input_values[0]), int(input_values[1])
    a, b = int(input_values[2]), int(input_values[3])
    connections = [list(map(int, input().split())) for _ in range(m)]
    cliniques = [list(map(int, input().split())) for _ in range(m, m+2)]
    sorted_connections = {}
    for road in connections:
        city1, city2 = road
        sorted_connections.setdefault(city1, []).append(city2)
        sorted_connections.setdefault(city2, []).append(city1)
    print(all_possiblities())

Input:

10 12 4 6
0 1
1 2
2 7
7 6
6 9
9 8
8 4
4 3
3 0
5 1
5 4
5 6
2 0 2
2 8 9

Output:

8
share|improve this question
3  
As we all want to make our code more efficient or improve it in one way or another, try to write a title that summarizes what your code does, not what you want to get out of a review. Please see How to get the best value out of Code Review - Asking Questions for guidance on writing good question titles. – BCdotWEB Jun 13 at 9:46
    
Can you provide an example of input? – N3buchadnezzar Jun 13 at 9:53
    
I updated my question with example – Joe Jun 13 at 9:57
2  
@Joe: Is this a programming challenge? If so, can you link to the original problem description? – Gareth Rees Jun 13 at 10:19

The key reasons for the poor performance are:

  1. Representing queue as a list. This is slow because popping an item off the beginning of a list takes time proportional to the length of the list.

    What you need here is a collections.deque.

  2. Computing shortest distances many times over. The shortest distance from a to clinique is computed again for every clinique2, even though it will be the same each time. Similarly, the shortest distance from clinique2 to b is computed again for every clinique.

    What you need here is to compute these distances once and remember them.

    If the number of cliniques is large compared with the number of cities, you should use the Floyd–Warshall algorithm to compute distances between all pairs of cities in one go (instead of using Dijkstra's algorithm many times, as in the posted code).

If I were implementing this, I'd use scipy.sparse.csgraph.floyd_warshall and write:

import numpy as np
from scipy.sparse.csgraph import floyd_warshall

def shortest_distance_via(graph, a, b, c1, c2):
    """Return the shortest distance in graph from a to b via C1 and C2 (in
    that order), where C1 and C2 are nodes in c1 and c2 respectively.

    Arguments:
    graph -- NxN array of distances between nodes.
    a, b -- nodes in the graph.
    c1, c2 -- arrays of nodes in the graph.

    """
    d = floyd_warshall(graph)
    ab = d[a, c1, np.newaxis] + d[np.meshgrid(c1, c2)] + d[np.newaxis, c2, b]
    return ab.min()
share|improve this answer
    
how can i avoid counting the shortest path many times in my code? – Joe Jun 13 at 10:47
    
using breath first search? – Joe Jun 13 at 10:48
1  
@Joe: Compute each path once and remember it! – Gareth Rees Jun 13 at 10:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.