1

I'm in need of a piece of code that finds the shortest path between nodes with the greatest weighting. For example, the quickest route from A to D, but with the greatest weighting:

  - B- --E
     /  \ /
    A    D
     \  / \
      C - -F

So right now the shortest would be ABD or ACD. Once the weighting is applied, the code should choose the longest path out of the two (counter-intuitive, huh?).

I'm trying to modify an algorithm for Dijkstra's Algorithm, but ultimately I just end up traversing the entire graph. Would anyone know how to do this? Even just an algorithm so I can code it myself would help immensely.

impo
  • 747
  • 1
  • 11
  • 37
  • Please clarify: what is the weight? on the edges? the vertices? – shapiro yaacov Jun 04 '15 at 14:25
  • In any case, you can run Dijkstra and get a list of shortest paths. Then choose any one of them according to whatever metrics you choose. – shapiro yaacov Jun 04 '15 at 14:33
  • so what you are trying to do is finding the longest paths, instead of the shortest? am I right? – Ashkan Kazemi Jun 04 '15 at 15:01
  • You can find all shortest paths with BFS (without any modification) and then select one of them with biggest weight. – Aleksei Shestakov Jun 04 '15 at 15:21
  • 1
    Finding "Longest" (/heaviest) path is [significantly harder than finding the shortest one](http://en.wikipedia.org/wiki/Longest_path_problem#NP-hardness). – amit Jun 04 '15 at 15:59
  • @shapiro.yaacov @AlexeiShestakov Problem with this approach is there could be exponential number of shortest paths. For example consider graph with edges: (a,v1),(a,v2),(v1,b),(v2,b),(b,v3),(b,v4),(v3,c),(v4,c),.... Number of shortest paths from `a` is `O(2^(d/2))`, where `d` is the length of the shortest path. – amit Jun 04 '15 at 16:42
  • Then build a graph with just the shortest paths there, including weights and run an algorithm on that – shapiro yaacov Jun 05 '15 at 15:55

2 Answers2

2
  1. Run BFS from the source (let it be s) on the graph to find the length of the shortest path from s to the target t, let it be d. Also mark d(s,v) - the distance from s to any node v.
  2. Create a subgraph G'=(V',E') of G such that: v is in V' only if its distance from the source (s) is at most d - d(s,v) <= d. e=(u,v) is in E' only if: both u and v are in V'.
  3. Create a new graph G*=(V*,E*), where V'=V*, and an edge (u,v) is in E* if it is in E' AND d(s,u) < d(s,v).
  4. Set a new weight function w*(u,v) = -w(u,v), and run Bellman Ford on G* using w*.
  5. The heaviest shortest path in G from s to t is of weight -d(t), and the path found by BF is the matching one.

Time complexity of the algorithm is O(VE), since Bellman-Ford is the bottleneck.


Correctness Proof

Claim 1: The shortest path from s to t does not contain any cycles.
Proof is simple by removing the cycle we get a shorter path.

Claim 2: All shortest paths from s to t are in G'
Proof: Since all shortest paths from s to t are of length d, and we eliminated only nodes with distance from s longer than d, we remove only nodes not needed for shortest paths.

Claim 3: All shortest paths from s to t are in G*.
Proof: Assume we removed some edge (u,v) in a shortest path, and let that path be s->...->x->u->v->y->...->t. Note that the path v->y->..->t is of length d-d(s,u)-1 (assuming d(s,u) is minimal)
However, note that from construction of E*, d(s,v) <= d(s,u) (otherwise (u,v) wouldn't have been removed). So, there is a path s->...->v->y->...->t with distance from s: d(s,v) + d-d(s,u)-1 <= d(s,u) + d - d(s,u) -1 <= d-1 - contradiction to minimality of d.

Claim 4: There are no cycles in G*.
Proof: Assume there is a cycle in G*: v1->v2->vk->v1. By definition of G', all nodes are reachable from s. Without loss of generality, let us assume d(s,v1) is minimal for all other d(s,vi) (otherwise rotate indices to match this assumption). But there is a path v1->v2->...->vk->v1, and d(s,v1)=d(s,v1). This means at least for one edge (vi,vi+1) in this path, d(vi) >= d(vi+1) - which is contradicting the construction of E*, and the cycle does not exist in G*.

Claim 5: The algorithm is correct.

From correctness of Bellman-Ford, and since G* does not contain negative cycles (no cycles at all), BF will find the path with minimal weight according to w* in G*. This path is the one with maximal weight according to w, from the construction of w*.
since all shortest paths in G also exist in G* (and only them), this path is also the shortest path in G with maximal weight.

QED

amit
  • 175,853
  • 27
  • 231
  • 333
-1

You can use Dijkstra if you adjust your weights.

If your optimal path must be one that visits the fewest nodes, you can use a high penalty p for traversing each edge and subtract the real weight:

    w' = pw

The penalty must be chosen higher than the highest weight wmax to prevent negative values for w', for which Dijsktra doesn't work. It must also be high enough so that really the shortest path is chosen. A good estimate for p for a graph of n nodes might be:

    p &approx; n·wmax

(Edit: My original answer proposed to use reciprocal weights w' = 1/w of each edge instead of the real weight w as an alternative. This will not necessarily give you the shortest path, but one whose weight is high while traversing few edges. This solution does not work for many cases. It is, however, totally independent from the penalty method, which doesn't use reciprocal values.)

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • Are you claiming by setting `w'=1/w` and running dijkstra, one can find the [longest (heaviest) path in a graph](http://en.wikipedia.org/wiki/Longest_path_problem)? That would be awesome to see, since it will prove [P=NP](http://en.wikipedia.org/wiki/P_versus_NP_problem). – amit Jun 04 '15 at 18:03
  • No, I am claiming that by adjusting the weights one can find what the OP wants: The shortest (or just _a_ short path for 1/_w_) path with the heighest sum of weights. (Frankly, I think you got worked up a bit with your longest path theory - no-one has asked for that.) – M Oehm Jun 04 '15 at 18:14
  • Can you show that the solution is indeed optimal (heaviest), and not just "good enough" (heavy)? – amit Jun 04 '15 at 18:23
  • In the penalty approach, if the penalty is greater than the sum of possible weights, the number of traversed edges is minimised. Among the paths of minimum length, the one with the highest total weight is chosen, because it has the smallest sum of adjusted weights. That's not a proof, but the rationale for the proposed solution. (The 1 / _w_ was just a first step; the good algorithm is the penalty approach, I think.) – M Oehm Jun 04 '15 at 19:31
  • that's not gonna work, sine for example 1/3 + 1/3 + 1/3 = 1/4 + 1/4 + 1/2, while 3+3+3 < 4+4+2, so the modofied weight will chose one at random, while there is a prefered solution on the regular weights. (the above is a counter example, by buillding a graph with 2 routes of length 3, one with weights 3,3,3 and the other with 2,4,4). – amit Jun 04 '15 at 19:39
  • A clear example where it will always fail is similarly for `1/3 + 1/6 < 1/2 + 1/10` while `3+6 < 2+10` – amit Jun 04 '15 at 19:45
  • So, from the above counter examples we can conclude that this solution is not optimal, even when adding the penalty (since both routes will suffer from same penalty) – amit Jun 04 '15 at 19:46
  • (P.S. Not the downvoter, just checking this thread regulary looking for your response and saw the downvote) – amit Jun 04 '15 at 21:01
  • I should have made clear that my answer poroposes two independent approaches: The reciprocal approach was my first thought, but it doesn't always produce the shortest path, and I say so in my answer. The penalty approach doesn't use reciprocal values at all. I think it should work (and it did in my tests) when the penalty is high enough that an additional edge will always be more exepnsive that all edge weights combined. – M Oehm Jun 05 '15 at 08:06