Dijkstra's algorithm to find all the shortest paths possible - graph

I'm working on Dijkstra's algorithm, and I really need to find all the possible shortest paths, not just one. I'm using an adjacency matrix and I applied Dijkstra's algorithm, and I can find the shortest path. But I need to find all the paths with that minimum cost, I mean all the possible solutions, if they exist.
This is how my algorithm works, for a single solution:
public void dijkstra( int graph[][] )
{
int d[] = new int[ graph.length ];
int dC[] = new int[ graph.length ];
int p[] = new int[ graph.length ];
for( int i = 0; i < graph.length; i++ ){
d[ i ] = 100; dC[ i ] = 100; p[ i ] = -1;
}
d[ 0 ] = 0; dC[ 0 ] = 0;
int i = 0, min = 200, pos = 0; //You can change the min to 1000 to make it the largest number
while( i < graph.length ){
//extract minimum
for( int j = 0; j < dC.length; j++ ){
if( min > d[ j ] && dC[ j ] != -1 ){
min = d[ j ]; pos = j;
}
}
dC[ pos ] = -1;
//relax
for( int j = 0; j < graph.length; j++ ){
if( d[ j ] > graph[ pos ][ j ] + d[ pos ] ){
d[ j ] = graph[ pos ][ j ] + d[ pos ];
p[ j ] = pos;
}
}
i++; min = 200;
}
for( int j = 0; j < p.length; j++ ){
System.out.print( p[ j ] + " " );
}
System.out.print( "\n" );
for( int j = 0; j < d.length; j++ ){
System.out.print( d[ j ] + " " );
}
System.out.print( "\n" );
}

If you look at Dijkstra's algorithm in pseudocode form here:
Wikipedia Dijkstra's Algorithm Pseudocode
You will notice the line referred to as a Relax. Right now it only contains a case for if the path found is less than the current shortest path, but there isn't anything done if they are equal. You should probably keep all the equally short paths in a List.

If your implementation of Dijkstra's algorithm is based on a priority queue, take your first solution, record the depth and keep popping solutions out until the distance changes.

If your graphs allows edges with weight = 0 and also allows cycles, bear in mind that there are infinitely many shortest paths, and you cannot hope to output them all!
If there are either no zero-weight edges, or your graph is a DAG, then your solution is still problematic: it either doesn't produce all shortest paths as required, or it does so withO(2^N) space and time complexity. But then, perhaps there might be as many shortest paths, so you can not hope to do better in the general case.
This is the best source for a slightly more general problem: Finding the k Shortest Paths (Eppstein). You could apply this by iterating the shortest paths, stopping at the first path that is longer than the previous.
For the restricted problem of finding only the (equivalent) shortest paths, Anderson Imes' hint above (is this homework? Otherwise someone should spell it out) is good and much simpler than the above.

I'm not very sure Dijkstra's algorithm can be easily adapted to do that; of course is not as simple as removing the visited edges, because the n shortest might share some of them.
So an almost brute force, but heuristically oriented solution, is to try this:
for every edge E in the shortest path:
remove E and run the modified Dijkstra again over the new graph
if the shortest path is longer than the first one obtained, stop
else, repeat recursively removing one edge at a time from the new sub-graph
My intuition tells me that it should work, with an increase in complexity proportional to the length (n in number of edges) of the first solution... If there are no more shortest path, it should end in the first round, if it founds another, it goes on with n-1 tries. The worst case complexity increase estimation over the original algorithm is very bad (n! I guess?), but that also means that there are lots of paths, so that is a work that needs to be done with any algorithm...
edit: Thinking a little bit more, the complexity increase might be even larger than the factorial of the number of nodes of the first found path, as the second might have even more nodes! So I think it's very difficult to estimate the complexity of this method, but it should be something like the number of valid solutions times the average number of nodes in the paths times the number of nodes squared (this last term being the original complexity of the unmodified algorithm).
edit 2: I've found a research paper about this subject, it requires subscription to get the full text but maybe you can find it somewhere else: http://ieeexplore.ieee.org/Xplore/login.jsp?reload=true&url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel5%2F7719%2F21161%2F00982778.pdf%3Farnumber%3D982778&authDecision=-201

FloydWarshallShortestPaths class of JgraphT finds all shortest paths. Based on above comments, you are looking for shortest paths between two vertices. You may want to use getShortestPaths method, which will return all shortest paths from the a vertex to all other vertices. Then you may want to filter the result which interests you.

Consider this algorithm: https://www.programmingalgorithms.com/algorithm/dijkstra's-algorithm/php/
At the end there is a "< $distance[$v])" condition. If we change it to "<= ...", it will give all the existing shortest paths.
For collecting the paths we can put a
$this->paths[$v][] = $u;
row here also.
The whole snippet is here: https://pastebin.com/gk2ymyWw
if (!$this->known[$v] && $graph[$u][$v] && $this->distance[$u] != $this->INT_MAX && $this->distance[$u] + $graph[$u][$v] <= $this->distance[$v]) {
$this->distance[$v] = $this->distance[$u] + $graph[$u][$v];
$this->paths[$v][] = $u;
}

This paper from 1982 describes an algorithm for graphs with multi-dimensional edge weights, that gives all shortest paths.
The algorithm works fine with simple weighted graphs, so should work for your case.
The author compares it to Dijkstra, both in how it works and in a run-time complexity comparison.
In pseudocode, paraphrasing the paper:
1. H is a heap of paths sorted on the weights of these paths, either
a. lexicographically and decreasing in each element of the weight vector
b. on the negative sum of all the elements in the weight vector
Initially, H contains only path p0 (the starting point) the weight of which is O.
2. S1 through Sv are sets associated with vertices v1 through vv respectively.
These sets contain the maximal paths to each vertex, as they are discovered.
Initially, all sets are empty.
3. a. While (H is not empty) do begin
b. remove the root of H, p;
c. if p is not dominated by any of the paths in Sn where vn is last vertex of p
d. add it to Sn (the set of maxima for vertex vn)
e. for each possible extensions q of path p
g. if path q to node vm is not yet dominated by the maxima in Sm
h. insert q into H

I Just solved a task to find all possible shortest paths on leetcode.com using Dijkstra's algorithm.
The only difference is how you extract information from "parents" and "distances" arrays.
The main idea is
you are moving from target to source and from each node in your optimal path ("parents" array),
you are looking for neighbors who had same minimal distances to the source like recorded parent, and
then recursively moving through all of those possible parents till you reach the source.
Below is the code in Python.
if parent[endNode] > -1: # -1 means no path at all
self.traversingAllNodes(parents, shortestDistances, endNode, [endNode])
return self.finalList
def traversingAllNodes(self, parents, distances, startNode, path):
if parents[startNode] == -1:
self.saveFound(path) # saving one path
return
currentNode = startNode
parent = parents[currentNode] # recorded parent
optimalDistance = distances[parent] # distance from parent to source
for node in self.graph[currentNode]: # moving via neighbords
if distances[node] == optimalDistance:
path.append(node)
self.traversingAllNodes(parents, distances, node, path)
path.remove(node)

Related

Recurrence Analysis (Time complexity)

im writing a boolean function that calculate if two binary trees are identical.
Lets see the program:
boolean func(Node head1 , Node head2){
if(head1 == null || head2 == null) return head1 == null && head2 == null;
return func(head1.left , head2.left) && (head1.right,head2.right);
}
i know that in the worst case the program check n element so its O(n).
and i want to describe this recurrence function in T(n).
i dont know were to start becuse i dont know what is the value of the stopping point ,
i think that the function is T(n,m) = 2*t(n-1,m-1) + n + m.
Let n be the number of nodes in the binary trees. If the binary trees have different number of nodes, then n is smaller of the two sizes (since you'll stop comparing once you reach the end of one tree).
On each call you are doing some comparisons between the nodes of the tree. This will be in constant time, so you can call this time spent d which represents some arbitrary constant.
Lastly, you're making 2 recursive calls for the current node's 2 children. Note that in the worst case, each of the children are the root of a subtree that holds half the total number of nodes in the tree. In other words if you have a tree with n nodes, and you are looking at the root node, then each child of the root has about n/2 nodes below it (and including it).
So your recurrence is as follows:
T(n) = 2*T((n-1)/2) + d
You can simplify this to:
T(n) = 2*T(n/2) + d

Counting the number of restricted Integer partitions

Original problem:
Let N be a positive integer (actually, N <= 2000) and P - set of all possible partitions of the N, where with and . Let A be the number of partitions . Find the A.
Input: N. Output: A - the number of partitions .
What have I tried:
I think that this problem can be solved by dynamic-based algorithm. Let p(n,a,b) be the function, which returns the number of partitons of n using only numbers a. . .b. Then we can compute the A with the code like:
int Ans = 2; // the 1+1+...+1=N & N=N partitions
for(int a = 2; a <= N/2; a += 1){ //a - from 2 to N/2
int b = a*2-1;
Ans += p[N][a][b]; // add all partitions using a..b to Answer
if(a < (a-1)*2-1){ // if a < previous b [ (a-1)*2-1 ]
Ans -= p[N][a][(a-1)*2-1]; // then we counted number of partitions
} // using numbers a..prev_b twice.
}
Next I tried to find the dynamic algorithm computing p(n,a,b) for any integer a <= b <= n. This paper (.pdf) provides the folowing algorithm:
, were I(n<=b) = 1 if n<=b and =0 otherwise.
Question(s):
How should I realize the algorithm from the paper? I'm new at d-p problems and as I can see, this problem has 3 dimensions (n,a & b), which is quite tricky for me.
How actually that algorithm works? I know how work the algorithms for computing p(n,0,b) or p(n,a,n), but a little explanation for p(n,a,b) will be very helpful.
Does original problem have simpler solution? I'm quite sure that there's another clean solution, but I didn't found it.
I calculated all A(1)-A(600) in 23 seconds with memoization approach (top-down dynamic programming). 3D table requires 1.7 GB of memory.
For reference: A[50] = 278, A(200)=465202, A(600)=38860513616
N=2000 requires too large table for 32-bit environment, and map approach worked too slow.
I can make 2D table with reasonable size, but this approach requires table zeroing at every iteration of external loop - slow again.
A(1000) = 107292471486730 in 131 sec. And I think that long arithmetic might be needed for larger values to avoid Int64 overflow.

Sum of roots of binary search trees of height ≤H with N nodes

Consider all Binary Search Trees of height ≤H that can be created using the first N natural numbers. Find the sum of the roots of those Binary Search Trees.
For example, for N = 3, H = 3: There are 2 trees with 1 as root, 1 tree with 2 as root and 2 trees with 3 as root.
Hence, Sum = 2∗(1)+1∗(2)+2∗(3)=10
I am trying to solve this problem by writing a function f(n,h) which is related to f(n−1,h−1) and f(n−1,h) in some way, but unable to find the solution.
Note: All numbers [1,N] must be present in the tree and the height should be ≤H
Ok let us start with basics.
The number of BST that can be created using first N natural numbers can be very easily calculated using the following algorithm.
natural_number compute_no_of_BST(N)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
left = compute_no_of_BST(root-1);
right = compute_no_of_BST(N-root);
sum = sum + (left*right);
}
return sum;
}
}
Explanation:
The key to understand this algorithm is this:
No matter what the distinct keys are, the number of BST only depends on number of distinct keys
So, this is what we use in recursion.For the left subtree number of distinct values are root-1 and for the right subtree the number of distinct values are N-root.Also we give every key the chance of being the root using the for loop.
Now, let us handle the constraint of height H.I am assuming the height to be the number of edges from root to leaf path. This can also be handled by focusing on the above algorithm and the trick is:
We will not call the recursive function calls for height > H and for this we must keep track of the number of edges traversed from root, which initially is 0.
So that kind of narrows it down to what are new function call will look like.
natural_number compute_no_of_BST(N,H,0);
And every time we make a recursive call, we increment the third variable to indicate an edge traversal.
We will also use an extra data structure, which is an array of length N where
arr[i] = number of BST with root i+1.
Here goes the algorithm for this
natural_number compute_no_of_BST(N,H,l)
{
if(N<=1)
return 1;
else
{
left=0,right=0,sum=0;
for(root = 1 to N)
{
if(l+1<=H)
{
left = compute_no_of_BST(root-1,H,l+1);
right = compute_no_of_BST(N-root,H,l+1);
if(l==0)
arr[root-1] = (left*right);
sum = sum + (left*right);
}
}
return sum;
}
}
Now sum can be easily computed as
arr[0]*1 + arr[1]*2 + ..... arr[N-1]*N.
Here is just a DP conversion of the above recursive algorithm.
int bottom_up_specific_height(int n,int h){
int i,j,l;
for(l=0;l<=h;l++){
dp[0][l]=1;
dp[1][l]=1;
}
int s=0;
for(i=2;i<=n;i++){
for(j=1;j<=i;j++){
for(l=h;l>=0;l--){
if(l==h)
dp[i][l]=0;
else
dp[i][l]+=(dp[j-1][l+1]*dp[i-j][l+1]);
if(l==0 && i==n)
s+=(j)*(dp[j-1][l+1]*dp[i-j][l+1]);
}
}
}
return s;
}
Here complexity reduces to O(h*n^2).
Is it possible to optimize it further!!

Decompose integer into two bytes

I'm working on an embedded project where I have to write a time-out value into two byte registers of some micro-chip.
The time-out is defined as:
timeout = REG_a * (REG_b +1)
I want to program these registers using an integer in the range of 256 to lets say 60000. I am looking for an algorithm which, given a timeout-value, calculates REG_a and REG_b.
If an exact solution is impossible, I'd like to get the next possible larger time-out value.
What have I done so far:
My current solution calculates:
temp = integer_square_root (timeout) +1;
REG_a = temp;
REG_b = temp-1;
This results in values that work well in practice. However I'd like to see if you guys could come up with a more optimal solution.
Oh, and I am memory constrained, so large tables are out of question. Also the running time is important, so I can't simply brute-force the solution.
You could use the code used in that answer Algorithm to find the factors of a given Number.. Shortest Method? to find a factor of timeout.
n = timeout
initial_n = n
num_factors = 1;
for (i = 2; i * i <= initial_n; ++i) // for each number i up until the square root of the given number
{
power = 0; // suppose the power i appears at is 0
while (n % i == 0) // while we can divide n by i
{
n = n / i // divide it, thus ensuring we'll only check prime factors
++power // increase the power i appears at
}
num_factors = num_factors * (power + 1) // apply the formula
}
if (n > 1) // will happen for example for 14 = 2 * 7
{
num_factors = num_factors * 2 // n is prime, and its power can only be 1, so multiply the number of factors by 2
}
REG_A = num_factor
The first factor will be your REG_A, so then you need to find another value that multiplied equals timeout.
for (i=2; i*num_factors != timeout;i++);
REG_B = i-1
Interesting problem, Nils!
Suppose you start by fixing one of the values, say Reg_a, then compute Reg_b by division with roundup: Reg_b = ((timeout + Reg_a-1) / Reg_a) -1.
Then you know you're close, but how close? Well the upper bound on the error would be Reg_a, right? Because the error is the remainder of the division.
If you make one of factors as small as possible, then compute the other factor, you'd be making that upper bound on the error as small as possible.
On the other hand, by making the two factors close to the square root, you're making the divisor as large as possible, and therefore making the error as large as possible!
So:
First, what is the minimum value for Reg_a? (timeout + 255) / 256;
Then compute Reg_b as above.
This won't be the absolute minimum combination in all cases, but it should be better than using the square root, and faster, too.

NTh square free semi prime

I am trying to find the nth( n <= 2000000) square free semi prime. I have the following code to do so.
int k = 0;
for(int i = 0; i <= 1000; i++)
{
for(int j = i +1 ; j <= 2500; j++ )
{
semiprimes[k++] = (primes[i]*primes[j]);
}
}
sort(semiprimes,semiprimes+k);
primes[] is a list of primes.
My problem is, i get different values for n = 2000000, with different limits on the for loops. Could someone tell a way to correctly calculate these limits?
Thanks in advance..
You want to calculate the nth first semi-prime square-free numbers. "first" means that you have to generate all of them under a certain value. Your method consist of generating a lot of those numbers, sort them and extract the nth first values.
This can be a good approach but you must have all the numbers generated. Having two different limits in your nested loops is a good way to miss some of them (in your example, you are not calculating primes[1001]*primes[1002] which should be in semiprimes).
To avoid this problem, you have to compute all the semi-prime numbers in a square, say [1,L]*[1,L], where L is your limit for both loops.
To determine L, all you need is it to count.
Let N be the number of semi-prime square-free numbers under primes[L-1]*primes[L-1].
N = (L * L - L) / 2
L*L is the total number of pairwise multiplications. L is the number of squares. This has two be divided by two to get the right number (because primes[i]*primes[j] = primes[j]*primes[i]).
You want to pick L such that n<=N. So for n = 2000000 :
int L = 2001, k = 0;
for(int i = 0; i < L; i++)
{
for(int j = i+1 ; j < L; j++ )
{
semiprimes[k++] = (primes[i]*primes[j]);
}
}
sort(semiprimes,semiprimes+k);
I don't believe an approach that works by computing all semiprimes inside a box will work in any reasonable amount of time. Say we graph the factors (p,q) of the first 2 million semiprimes. To make the graph more symmetric, let's plot a point for both (p,q) and (q,p). The graph does not form a nice rectangular region, but instead looks more like the hyperbola y=1/x. This hyperbola stretches out quite far, and iterating over the entire rectangle containing these will be a lot of wasted computation.
You may want to consider first solving the problem "how many semiprimes are there below N?" and then using a binary search. Each query can be done in about sqrt(N) steps (hint: binary search strikes again). You will need a fairly large table of primes, certainly at least up to 1 million, probably more. Although this can be trimmed down by an arbitrarily large constant factor with some precomputation.

Resources