graph theory

Hi.

Does anyone of you know some nice (and possibly already implemented) algorithms for the k-shortest-path problem? In particular, I am interested in some special features: it has to work with a directed, weighted graph and should ignore loops, i.e. it should work with simple paths. And I don't want it to cut edges after finding a path.

Here is a small example with edges weighted 1 each, the direction is from left to right:

A - - - B - C

\/

F - G

So the algorithm should yield A-B-C as the shortest, and A-F-G-C as the second-shortest path.

I am glad for every hint, thank you in advanced,

greetings

Norman

Message was edited by:

Waldmeister_iii

[728 byte] By [Waldmeister_iiia] at [2007-10-2 21:32:46]
# 1

I assume you're using Dijkstra's Shortest Path finding algorithm.

Normally when the shortest path has been found the algorithm stops,

leaving all that useful data in it's heaps. For your requirement don't

stop and keep on iterating until a next path has been found (which is

the one after the shortest path). etc. etc.

kind regards,

Jos

JosAHa at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 2
It's not quite that simple, Jos. It's necessary to amend Dijkstra's algorithm to track for each node the k lowest weights. Even then the backtracking at the end needs to use extra state, and the priority queue needs to be capable of holding k instances of each node.
YAT_Archivista at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 3

> It's not quite that simple, Jos. It's necessary to amend Dijkstra's

> algorithm to track for each node the k lowest weights. Even then the

> backtracking at the end needs to use extra state, and the priority

> queue needs to be capable of holding k instances of each node.

But that's just a few (clever?) walks through that heap/priority queue

isn't it? I've done this before years ago, I'll check it out, I'll have to dig

up some old stuff.

kind regards,

Jos

JosAHa at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 4

> I'll check it out, I'll have to dig up some old stuff.

I just did (I went to the attic for it) and I have to apologize: the heuristic

I used was simple edge removal from the shortest path. I needed this

for traffic jam avoiding, but that's all the algorithm did. Because I did a

two way Dijkstra I was able to remove that single edge in a cheap way

from both heaps. Sorry again for all the misleading hope my remark

might have caused ;-)

kind regards,

Jos

JosAHa at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 5

This may or may not be relevant to the OP but there is an algorithm by Suurballe for finding two disjoint paths through a graph with minimum total weight. I implemented this a few years ago while working for a well known telecom company. The algorithm has been extended to finding 'k' disjoint paths though I have no direct experience of it.

sabre150a at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 6

just so the rest of us can join in, what is the definition of the k shortest path problem?

In your little example why weren't B-C, G-B, A-B and all the other unit length paths considered to be the shortest?

What is k?

Are you assuming that a start and an end node have been given? Are you assuming that there is a path between your start and you end node? i.e. you don't mind returning something less than k paths.

Assuming that you do want to go from one node to another, how big and how pathalogical are your graphs? For example consider the non-connected graph consisting of the union of the complete graph of the nodes from A to Y and the singlton Z. There are no paths from A to Z but it would be easy to build algorithms that would grovel a long time before they detected that little fact.

Give us some hints.

marlin314a at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 7

Hi all.

First, thanks for yours answers and sorry for me not answering so long!

In my graph, I have a start and an end node, for which I want to have all or just k shortest paths. So in my example, the goal would bei to extract A-B-C and A-F-G-B-C as the two shortest paths available, if k is 2.

Here are some constraints on my graph:

- size: 10.000 to 1.000.000 nodes with 20-100 edges each

- the graph is propably non-connected

- I only want to search up to a certain depth, while the depth is definded by hops

- loops should be ignored

I have implemented a solution for near-shortest paths, using this paper: "Near-shortest and K-shortest simple paths" by Carlyle and Woods. The solution works, but not as fast as I would like it to. This is due to the following fact: I use Dijkstra all-pairs shortest-path algorithm first for calculatin the shortest paths for each node to each other node (within a graph of n nodes I have to run Dijkstra n times). This is quite fast. Now, for each shortest path from each node to each other node, I start the NSP (near-shortest-paths) calculations. So I have to run the NSP-algorithm n*(n-m) times, with m being the number of nodes not reachable by a shortest path at all. And this now chews up my computing power for a long long time... :)

So I hope I could make my problem a little bit more understandable, thanks again for your answers,

Greetings,

Norman

Waldmeister_iiia at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 8

Hi guys.

@sabre150: I can't use the algorithm of Suurballe, since they calculate disjoint paths, and this is not required, respectivly a must not!

@Jos: I thought about edge-removal, too, but this would create partly-disjoint-paths, and as above, those I don't want :)

Thanks for your answers!

Greetings,

Norman

Message was edited by:

Waldmeister_iii

Waldmeister_iiia at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 9

This is interesting. I thought about it a few days and came up with a variation of Dijsktra that supports not one shortest but k shortest paths. If you think of Dijkstra as generating a tree that spreads out from the root (startNode), we now simply allow k branches to overlap at a node.

Since it was just a quick test and Dijsktra is well known, I have not commented that thoroughly. If you have any questions just ask. :)

import java.util.*;

/*

* @author Thomas Horstmeyer

*/

public class KShortestPath {

private final DirectedGraph graph;

private final Object startNode, targetNode;

private final int k;

private final boolean pathsMustBeSimple;

private HashMap<Object, MultiPathInfo> pathsByNode;

public KShortestPath(DirectedGraph graph, Object startNode, Object targetNode, int k, boolean pathsMustBeSimple) {

this.graph = graph;

this.startNode = startNode;

this.targetNode = targetNode;

this.k = k;

this.pathsMustBeSimple = pathsMustBeSimple;

}

public void compute() {

pathsByNode = new HashMap<Object, MultiPathInfo>();

MultiPathInfo targetPathInfos = new MultiPathInfo();

pathsByNode.put(targetNode, targetPathInfos);

PriorityQueue<PathInfo> candidates = new PriorityQueue<PathInfo>();

candidates.offer(new PathInfo(startNode, 0d, null));

while(targetpathInfos.isIncomplete() && !candidates.isEmpty()) {

PathInfo pi = candidates.poll();

System.out.print("inspecting candidate at "+pi.endNode+" weight="+pi.weight);

MultiPathInfo mpi = pathsByNode.get(pi.endNode);

if (mpi == null) {

mpi = new MultiPathInfo();

pathsByNode.put(pi.endNode, mpi);

}

if (mpi.isIncomplete() && (!pathsMustBeSimple || isSimplePath(pi))) {

System.out.println(" ...taken");

mpi.addPathInfo(pi);

Iterator it = graph.getSuccNodes(pi.endNode).iterator();

while (it.hasNext()) {

Object node = it.next();

candidates.add(new PathInfo(node, pi.weight + graph.getEdgeWeight(pi.endNode, node), pi));

System.out.println("\tcreated candidate at "+node+" weight="+(pi.weight + graph.getEdgeWeight(pi.endNode, node))+")");

}

}

else System.out.println(" ...discarded");

}

}

// checks whether endNode appears more than once in the path

private boolean isSimplePath(PathInfo path) {

Object node = path.endNode;

while (path.lead != null) {

path = path.lead;

if (node.equals(path.endNode)) return false;

}

return true;

}

public void printPaths() {

MultiPathInfo mpi = pathsByNode.get(targetNode);

for (int i=0; i<mpi.paths.length; i++) {

PathInfo pi = mpi.paths[i];

StringBuilder sb = new StringBuilder();

while (pi != null) {

sb.insert(0, ", ");

sb.insert(0, pi.endNode);

pi = pi.lead;

}

sb.insert(0, " : ");

sb.insert(0, mpi.paths[i].weight);

System.out.println(sb.toString());

}

}

private static class PathInfo implements Comparable{

double weight;

Object endNode;

PathInfo lead;

public PathInfo(Object endNode, double weight, PathInfo lead) {

this.endNode = endNode;

this.weight = weight;

this.lead = lead;

}

//inconsistent with equals

public int compareTo(Object o) {

PathInfo pi = (PathInfo) o;

if (weight >< pi.weight) return -1;

if (weight > pi.weight) return 1;

return 0;

}

}

private class MultiPathInfo {

PathInfo[] paths = new PathInfo[k];

int nextFreePosition = 0;

void addPathInfo(PathInfo pi) {

if (nextFreePosition < k) paths[nextFreePosition++] = pi;

}

boolean isIncomplete() {

return nextFreePosition < k;

}

}

}

Let's take a look at the complexity:

Let graph have n nodes and m edges.

The algorithm creates at most m*k candidates. Storing and removing them in the PriorityQueue takes O(log (k*m)).

So we have a complexity of O(m*k*log(k*m)). We could improve this to O(m*k) using a Fibonacci heap.

For simple paths the additional check adds a factor of (length of path) which is bounded by n.

It is also possible to bound the search depth with an additional hop-distance field in PathInfo.

And I can see some space for improvement in the check for simpleness of a path - not necessarily complexity-wise.

If you try out this approach I would really be interested in how it competes with your current approach.

Greetings,

Thomas

horstmeyera at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 10
Hello Horst.Thank you very much for this code. I will implement it as soon as possible, and then I will give you feedback!!Thanks again, greetings,Norman
Waldmeister_iiia at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 11
>Hello HorstIt's Thomas, not Horst. :-)Horstmeyer is my surname.
horstmeyera at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 12
> >Hello Horst> > It's Thomas, not Horst. :-)> Horstmeyer is my surname.Ahh, once again it's true: you live and learn... ;)
Waldmeister_iiia at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 13
Hey Thomas, is it possible to PM you?Regards,Norman
Waldmeister_iiia at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...
# 14
Depends on what you want. But sure, drop me a mail. (I presume your native language is German as well, so you need not write in English if you don't want to :-))thomasDOThorstmeyerATgmxDOTde
horstmeyera at 2007-7-14 0:46:20 > top of Java-index,Other Topics,Algorithms...