Dijkstra with parallel edges between two Vertices - algorithm

I've got a routing problem where I need to retrieve the best n solutions between two points. I am using Dijkstra for the optimal solution and Yen Top K algorithm on top of that to get the n best solutions.
However there is a twist to it, you can have multiple parallel edges between to vertices. Lets imagine a bus network:
Line A: a -> b -> c -> d -> e
Line B: b -> c -> d -> e -> f
Line C: a -> b -> c -> g -> h
When you build your graph, how do you handle these parallel connections?
I am thinking of building the graph like:
Line A: a->b,a->c,a->d a->e,b->c,b->d,b->d,b->e,c->d,c->e,d->e
Line B: b->c,b->d,b->e,e->f,c->d,c->e,c->f,d->e,d->f,e->f
Line C: a->b,a->c,a->g,a->h,b->c,b->g,b->h,c->g,c->h,g->h
With that I have direct edges for when I don't have to change bus.
For each Vertex I go through I add a connection penalty weight.
So if I want to go from a->e I would probably get Line A as using Line C a->b, Line B b->e might be longer because of the connection time even if the time Line C a->b and Line B b->e might be faster than the route on Line A.
However I still need to handle parallel connections. So I guess I need to sort the parallel edges by weight.
Currently this is based on static timing information but at some point it should take actual schedule information into account. And depending on that your weights between two vertices could change. E.g. by the time you would get to point b the fastest connection via Line C wouldn't be the fastest anymore as you would have just missed Line C etc.
Are there any resources anywhere that explain how you would handle these more complex situations?

One approach could be to reduce the problem back to a simple graph (no parallel edges), by "splitting nodes"
That means, if you have a node u, with edges (v,u)_1, (v,u)_2, ..., (v,u)_k, you can split u to: u, u_1, u_2,...,u_k, with edges: (u_1,u), (u_2,u), ..., (u_k,u), (v,u_1), (v,u_2), ...., (v,u_k), and weights:
w(u_i,u) = 0 for all i and w(v,u_i) = w((v,u)_i) for all i
Now you can run any algorithm designed for simple graph with ease, where the number of vertices is increased in a linear factor of the number of parallel edges.

Related

Sort a directed graph that contains exactly one cycle

I have a graph that contains exactly one cycle but I need to sort it using a "topological sort" (of course actual topological sort does not handle cycle). I am wondering how can it be done?
For example:
A -> B
B -> C
C -> D
D -> A
Possible solutions are:
A -> B -> C -> D
B -> C -> D -> A
C -> D -> A -> B
D -> A -> B -> C
I see there is this algorithm as suggested here but it's too overcomplicated for my use case.
There are a few approaches and implementations for topological sort. The most intuitive one I have found is to:
Identify nodes with no incoming edges (Can be done through creating an adjacency list and a dictionary containing incoming edge counts for vertices).
Add these to the sorted list
Remove this node from the graph and subtract it from the count of incoming edges for the node
Repeat process until there are no longer any nodes with a count above 0.
If the sorted list is larger than the number of vertices you will know that you have a cycle at this point and can terminate the algorithm.
There are many code samples with various implementations online but this algorithm should help guide the implementation for a basic topological sort.

Need assistance in resolving this variation of shortest path algorithm

The below picture is the representation from the question which was asked to me during samsung interview. I had to write the program to find the minimum distance between I and M. There was an additional constraint that we can change one of the edges. For example, The edge FM can be moved to join edge L and M and the edge value will still be 4.
If you notice, the distance between I and M via I-> E -> F -> G -> M is 20. However, if we change one of the edges such that L to M edge value is 4 now. We have to move edge FM to join L and M now. By this method, the distance between I and M is 20.
An arbitrary edge u, v can be changed to u, t or t,v. It can not be changed to x,y. So one of the vertices in the edge has to be same.
Please find the picture below to illustrate the scenario -
So my problem is that I had to write the program for this. To find the minimum distance between two vertices, I thought of using Djikstra's algorithm. However , I as not sure how to take care of the additional constraint where I had the option of changing one of the vertices. If I could get some help to solve this, I would really appreciate it.
If we move an edge (A, B), the new end should be either the start S or the target T vertex (otherwise, the answer is not optimal).
Let's assume that we move the edge (A, B) and the new end is T (the case when it's S is handled similarly). We need to know the shortest path from S to A that doesn't use this edge (once we know it, we can update the answer with the S->A->T path).
Let's compute the shortest path from S to all other vertices using Dijkstra's algorithm.
Let's fix a vertex A and compute the two minimums of dist[B] + weight(A, B) for all B adjacent to A. Let's iterate over all edges adjacent to A. Let the current edge be (A, B). If dist[B] + weight(A, B) is equal to the first minimum, let d be the second minimum. Otherwise, let d be the first minimum. We need to update the answer with d + weight(A, B) (it means that (A, B) becomes (A, T) now).
This solution is linear in the size of the graph (not counting the Dijkstra's algorithm run time).
To avoid code duplication, we can handle the case when the edge is redirected to S by swapping S and T and running the same algorithm (the final answer is the minimum of the results of these two runs).
In the graph you've shown, the shortest path I see is I -> E -> F -> M with a length of 13.
Moving the edge F -> M so that it connects L -> M just makes things worse. The new shortest path is I -> E-> F -> L -> M with a length of 18.
The obvious answer is to move edge F -> M so that it connects I directly to M, giving a length of 4.
In other words, find the shortest edge that's connected to I or M and use it to connect I directly to M.
For future reference, it's highly unlikely that you'll be asked to implement Djikstra's algorithm from memory in an interview. So you need to look for something simpler.

Find the all chain of one to one node in graph

I go the un-directed graph G an my goal is to find all the possible chains longest than N of nodes in a one to one relation.
For example:
In the the next Graph the "chains" of length more than 2 of nodes in one to one relation are:
- d -> e -> f -> g
- c -> k -> l -> m
So what is the best approach or algorithm to solve this problem ?
If you want to find all paths so that each vertex in it has a degree <=2, then the simple approach may be as follows.
Remove all vertices with degree >2 from your graph. You are left with a graph with each vertex having a degree <=2. It is easy to prove that every connected component of such a graph is either a simple way, either a simple loop, and it is easy to distinguish them (for example, running a DFS from one node and seeing whether you ever return to it).
So, every component that is a path is a path you look for. Every component that is a loop is also a path you look for, or can be easily converted to such a path by removing an edge or a vertex, depending on whether you allow a loop as the needed path.

Algorithm for laying out a directed acyclic graph in memory to maxmise data locality

Say I have the edges
A -> C
A -> D
A -> E
B -> D
B -> E
To maximise data locality I'd arrange for the DAG to be stored in this order in memory (as an array) to minimise the distance between the node and it's dependencies.
C, A, D, E, B
so that A has a distance 1 to C, 1 to D, 2 to E.
And that B has a distance of 1 to E, and 2 to D.
Is there name for an algorithm that does this? If not, how would one implement this?
Looks like you want to linearize the DAG. I don't know whether you are using it for dependancy resolution. Topological_sorting looks familiar to your question. also the program tsort does very similer thing.
However it is dependancy linearization.
neel#gentoo:~$ tsort
C A
D A
E A
D B
E B
C
D
E
B
A
Which prints the order in which that tasks have to be performed. and it will possible not work if there is a cycle. its relevant as you mentioned its acyclic.
I dont know if there is any such algorithm for data locality ordering string or anything similar however It looks like your data locality string have some problem.
What if C is close(1) to A and is also close(1) to B and B is too far(4) from A how will you represent it with your data locality string ?
I don't now what exactly you want to do. If you want to liniarize dependency to perform tasks in proper order then do a topological sort.
Here is slightly different approach to improve locality:
http://ceur-ws.org/Vol-733/paper_pacher.pdf
The described algorithm seems to be closer to force-directed graph drawing algorithm than to topological sorting.
You should also read papers on in-memory graph databases such as imGraph

Weighted Graph Algorithm

I have a weighted, directed graph with multiples edges starting from the ending at the same nodes.
Ex.
Multiple edges going from node A to node B.
What would be the best search algorithm to get all of the paths to a certain node and the associated costs of these paths?
Since you want all the paths, I'd use a simple breadth-first search. However, I also suggest that you collapse all the parallel edges into a single edge that has a list of weights.
Once you get all the different paths (that is, all the paths in which the nodes visited are different), for each path you can calculate all the possible alternative parallel routes.
So if you've got the following edges:
A -> C (5)
A -> C (3)
A -> B (7)
B -> C (1)
B -> C (4)
The first step transforms it into:
A -> C (5,3)
A -> B (7)
B -> C (1,4)
The breadth-first search on this graph will yield the following paths between A and B:
A -> B (7)
A -> C -> B (5,3) + (1,4)
So for the second path, you'll get the following costs:
5 + 1
5 + 4
3 + 1
3 + 4
This isn't going to be any faster in itself than just doing a BFS on the original graph, but a simpler graph is easier to handle.
If you have to output the cost of each path, there is nothing better than a plain DFS (or BFS). Since the problem is output sensitive and you might just have O(E + V) paths, you cannot accomplish anything better in terms of big-O notation.
As already stated, you can do bruteforce/backtracking using Depth First Search, etc.
Don't expect to find any shortcuts for this - if your graph is dense enough there can be lots of paths and even just finding how many of them there are is #P-complete (ie.: untractable).
(If your problem is different - maybe repeated nodes are allowed or you only want to find the shortest path or something like that then there could be tractable solution)
do you allow the cycling, that is you have directed link/path from a->b b-x-x-->a? for which case you will end up with unlimited paths.

Resources