views:

779

answers:

4

Hi All,

Can anybody help me to make j2ME implementation of Dijkstra algorithm faster ? I have two loops, one inside another. Like this

while(for each item in Q)
{
    //...do something.

    //the following loop is to find the minimum
    for(all un-visited nodes in Q)
    {
       //.. do something to get min.
    }

}

I have almost 23000 nodes and 50000 edges connecting them...The inner loop executes an average of 169330131 times after all improvements mentioned below. This takes 5 minutes to complete on my w910i mobile and more than minutes on my emulator. This looks too much for me. Any suggestions for improvement? I have the following improvements already implemented.

  1. Using array instead of vector.
  2. Make sure that the inner loop does not consider the visited nodes. All my visited nodes are at the end of the array and I node know the count. So, I can easily skip them altogether.

Thanks in advance

D M

+1  A: 

Something wrong with your implementation. It's complexity is O(E + V * log2 (V)).

That means 50000 + 23000 * ~15 = 400 000 iterations.

Your current complexity is almost O(V^2).

Roman
+2  A: 

I think your algorithm in the question is wrong. The inner loop should be looking at each unvisited neighbour of the item in the outer loop:

for each (item in Q)
{
  for each (unvisited neighbour of item)
  {
  }
}

Compare it with the pseudocode implementation in wikipedia:

 1  function Dijkstra(Graph, source):
 2      for each vertex v in Graph:           // Initializations
 3          dist[v] := infinity               // Unknown distance function from source to v
 4          previous[v] := undefined          // Previous node in optimal path from source
 5      dist[source] := 0                     // Distance from source to source
 6      Q := the set of all nodes in Graph
        // All nodes in the graph are unoptimized - thus are in Q
 7      while Q is not empty:                 // The main loop
 8          u := vertex in Q with smallest dist[]
 9          if dist[u] = infinity:
10              break                         // all remaining vertices are inaccessible
11          remove u from Q
12          for each neighbor v of u:         // where v has not yet been removed from Q.
13              alt := dist[u] + dist_between(u, v) 
14              if alt < dist[v]:             // Relax (u,v,a)
15                  dist[v] := alt
16                  previous[v] := u
17      return previous[]
1800 INFORMATION
I referred this algorithm. I found a simpler algorith some other place. Please note that If I had to implement the one in Wikipedia, there are two inner loops. while Q is not empty: //Outer loop. u := vertex in Q with smallest dist[];// First inner loop. .... for each neighbor v of u: //Second inner loop.The second inner loop is smaller. It might execute a maximum of 4-5 as there are at most 5 edges for each node. The number of nodes having more than 2 edges is 1000 out of 23000 total nodes. So, the execution time for inner loop is negligible.
dmantamp
Have you read the section in the wikipedia about running time? It suggests to use adjacency lists and a binary heap or some other structure as a priority queue - this will largely remove that first inner loop
1800 INFORMATION
Take a closer look, Deekshit - if you use a priority queue (a heap) for Q, finding the smallest element in Q is O(1), which makes the total runtime O(n+m) with the number of nodes and edges.
Nick Johnson
Thanks Nick Jonson, I will try that approach. As the target platform is a j2ME enabled phone, I have a constraint of memory consumption as well. I will give it a try.
dmantamp
+1  A: 

I referred this algorithm. I found a simpler algorithm some other place. Please note that If I had to implement the one in Wikipedia, there are two inner loops.

while Q is not empty: //Outer loop. 
  u := vertex in Q with smallest dist[];// First inner loop. 
  .... 
  for each neighbor v of u: //Second inner loop.

The second inner loop is smaller. It might execute a maximum of 4-5 as there are at most 5 edges for each node. The number of nodes having more than 2 edges is 1000 out of 23000 total nodes. So, the execution time for inner loop is negligible. The first inner loop is the problem. Finding the smallest node. As I have to execute this on a j2ME device, I have to make it to take as much less space as possible.

dmantamp
Is it negligible? Did you profile it and test it? The pseudo-code above *is* Dijkstra's algorithm, so no; the inner loop is required. Your algorithm is almost is almost O(V^2), as Roman said, but if you implement the algorithm correctly, without assumptions or premature-optimizations, you'll get the correct O() complexity.
GMan
Yes I did. The maximum number of times First inner loop exeution for each iteration of outer loop execution is 23000 (number of notes). But the second inner loop is executed only 5 times(the maximum number of edges for each node). Let us consider my example where I have 25000 nodes. And I find the shortest path in 1000th iteration. So, the second inner loop executes a minimum of 24000 for each iteration of outer loop. That is 1000*25000. But the second inner loop takes only 5 iterations. That is 1000*5 (max). So only the bottleneck is first inner loop.
dmantamp
When I tested the second loop hardly consumes 2-3 seconds of execution time. But the first loop is really heavy. I tried to reduce the time by half by saving second minimum distance. This reduced 30% of execution time. But increased the complexity of the code. BTW, the program does not take more than 2 seconds on my desktop PC. It takes almost 5 minutes on my mobile or emulator.
dmantamp
A: 

Hello Deekshit,

have you solved your complexity problems with Dijkstra algorithm?

I would need an efficient implementation for J2ME too. Is your solution an open source? ;)

Regards Mobile Developer [email protected]

Mobile Developer