Dijkstra's Algorithm with Bounded Edge Weights: Implementation with Fib-Heaps, Study notes of Computer Science

Lecture notes on dijkstra's algorithm with bounded edge weights, using fib-heaps as the data structure. The notes cover the key observation, minor adjustments, and the implementation of insert, deckey, and deletemin operations. The algorithm is used for the single source shortest path problem and is shown to run in time o(v log v + e).

Typology: Study notes

Pre 2010

Uploaded on 07/30/2009

koofers-user-4x3
koofers-user-4x3 🇺🇸

10 documents

1 / 9

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
LECTURE NOTES FOR CMSC 651
DIJKSTRA’S ALGORITHM WITH BOUND ON THE WEIGHTS
1 DIJKSTRA’S ALGORITHM: BOUNDED
EDGE WEIGHTS
By using Fib-heaps as our data structure we obtained an algorithm for the
Single Source Shortest Path (SPPP) problem that runs in time
O(Vlog V+E).
Can we do better? Dijkstra’s algorithm can be used to SORT numbers
(this is an easy exercise). Hence, Dijkstra’s algorithm cannot do better than
O(Vlog V) time (the lower bound for sorting). But what if all the weights
are (non-negative) integers bounded by a constant C?
We can do better! We will exhibit an algorithm that runs in time
O((log C)V+E).
We will not change the algorithm, just the the data structure that supports
it.
This algorithm has been used at Bell Labs as a subroutine in an algorithm
for min-cost flow which assigned clients to nearby copies of websites.
Key Observation: Assume Cbounds the edge weights. Assume that Dijk-
stra’s algorithm is run. Assume that DELETEMIN removes vertex vwhich
has value d(v). Let wbe the very next vertex that is removed by DELTET-
MIN. Then
d(v)d(w)d(v) + C.
Minor Adjustment: We need one minor adjustment in Dijkstra’s algo-
rithms. Note that since the bound on the weights is C, and all paths are of
length nwe will obtain d(v)Cn. In the usual Dijkstra’s algorithm we
initially set the d(v)’s to be . We will instead set them equal to Cn + 1.
Note that the largest integer ever encountered for a value of d() will be Cn+1.
We will describe a data structure that supports INSERT, FINDMIN,
DELETEMIN, DECKEY.
1
pf3
pf4
pf5
pf8
pf9

Partial preview of the text

Download Dijkstra's Algorithm with Bounded Edge Weights: Implementation with Fib-Heaps and more Study notes Computer Science in PDF only on Docsity!

LECTURE NOTES FOR CMSC 651

DIJKSTRA’S ALGORITHM WITH BOUND ON THE WEIGHTS

1 DIJKSTRA’S ALGORITHM: BOUNDED

EDGE WEIGHTS

By using Fib-heaps as our data structure we obtained an algorithm for the Single Source Shortest Path (SPPP) problem that runs in time

O(V log V + E).

Can we do better? Dijkstra’s algorithm can be used to SORT numbers (this is an easy exercise). Hence, Dijkstra’s algorithm cannot do better than O(V log V ) time (the lower bound for sorting). But what if all the weights are (non-negative) integers bounded by a constant C? We can do better! We will exhibit an algorithm that runs in time

O((log C)V + E).

We will not change the algorithm, just the the data structure that supports it. This algorithm has been used at Bell Labs as a subroutine in an algorithm for min-cost flow which assigned clients to nearby copies of websites.

Key Observation: Assume C bounds the edge weights. Assume that Dijk- stra’s algorithm is run. Assume that DELETEMIN removes vertex v which has value d(v). Let w be the very next vertex that is removed by DELTET- MIN. Then d(v) ≤ d(w) ≤ d(v) + C.

Minor Adjustment: We need one minor adjustment in Dijkstra’s algo- rithms. Note that since the bound on the weights is C, and all paths are of length ≤ n we will obtain d(v) ≤ Cn. In the usual Dijkstra’s algorithm we initially set the d(v)’s to be ∞. We will instead set them equal to Cn + 1. Note that the largest integer ever encountered for a value of d() will be Cn+1. We will describe a data structure that supports INSERT, FINDMIN, DELETEMIN, DECKEY.

  • We will not bound the cost of these operations.
  • We will not bound the amortized cost of these operations.
  • We will bound the amortized cost provided that the DELETEMINS operate as in Dijkstra’s algorithm with bounded weights. That is, provided that if the DELETEMINS delete v 1 , v 2 ,... , vn in that order then, (∀i)[d(vi) ≤ d(vi+1) ≤ d(vi) + C].

The data structure itself depends on the number C. We will assume C is a power of 2. Let L = lg C. We describe the data structure.

  1. At every stage there will be a set of the form {dmin,... , nC + 1}. All keys are in this set. Initially dmin = 0.
  2. The numbers {dmin,... , nC + 1} are divided into L + 3 buckets of contiguous numbers. Initially the buckets are B 1 = { 0 } B 2 = { 1 } B 3 = { 2 , 3 } B 4 = { 4 , 5 , 6 , 7 } B 5 = { 8 ,... , 15 } .. . =

Bi = { 2 i−^2 ,... , 2 i−^1 − 1 } (for 2 ≤ i ≤ L + 2) ..

. =

BL+1 = { 2 L−^1 ,... , 2 L^ − 1 }

BL+2 = { 2 L,... , 2 L+1^ − 1 }

BL+3 = { 2 L+1,... , nC + 1}

In general we will denote the endpoints of Bi by [si, mi] where si = mi− 1 + 1. (si stands for Smallest in bucket i, mi stands for Max in bucket i.)

  1. The sizes of the buckets will be bounded: |B 1 | ≤ 1 |Bi| ≤ 2 i−^2 for 2 ≤ i ≤ L + 2 |BL+3| ≤ nC + 1 − 2 L+1^ + 1

1.1 INSERT

INSERT(x):

Do the comparisons x < si for decreasing i until you get a YES. Now you have s 1 , s 2 ,... , si− 1 ≤ x < si We now know that x should go into Bi− 1.

Link x to the linked list Bi− 1. (Formally we actually link (x, i) so that x ‘knows’ what bucket its in.)

H[i − 1] = H[i − 1] + 1.

END OF ALGORITHM FOR INSERT

The actual cost is dominated by the cost for the comparisons and is O(log L). (We could have used binary search to speed it up to O(log log(L)) but this will not help the analysis.) The most the potential function can increase occurs when we add the element to bucket L + 3. In this case the change in potential is O(log C). So the amortized cost is O(log C).

Note 1.1 There are two ways to decrease the amortized cost of INSERT. Unfortunately they still result in O(log C).

  1. Instead of using sequential search use binary search to find where to insert. This cuts the actual cost from O(log C) to O(log log C).
  2. In our particular application (Dijistras algorithm) we only insert one element s with d(s) = 0 and all the rest of the elements v have d(v) = nC + 1. Hence we do not have to search for which bucket to put them into. Thus the actual cost is O(1) per insert.

The increase in potential is still O(log L) per insert, so the amortized cost is still O(log L).

1.2 DECKEY

DECKEY(x, x′)

Let i be such that x ∈ Bi (this takes O(1) to find since all elements know the bucket they are in).

Do the comparisons x′^ ≥ si? x′^ ≥ si− 1? etc until you get a YES. If x′^ ≥ si then x ∈ Bi then just replace x by x′. If x′^ ∈ B[j], j < i, then

Remove x from B[i]. H[i] = H[i] − 1 Place x′^ into B[j]. H[j] = H[j] + 1.

END OF ALGORITHM FOR DECKEY

The number of comparisons made to find out which bucket to put x′^ into is i − j. So the actual cost is O(i − j). Since x is removed from Bi and placed into Bj , the potential is decreased by α(i − j). Hence the amortized cost is

O(i − j) − α(i − j).

Pick α so that this is O(1).

1.3 DELETEMIN

We now look at DELETEMIN which will be more complicated. Every time DELETEMIN is called we will change the intervals of the buckets and (more important) if the min is found in any bucket other than B 1 then every element in the bucket where the min was found will be moved into a bucket of lower index.

that makes the wrong things not a problem, while maintaining the right thing.

  1. RIGHT THING: Every element of the old Bj now belongs in a lower bucket. The old Bj had minimal element dmin and had a range of 2 j−^2 elements. Hence old Bj ⊆ {dmin,... , dmin + 2j−^2 − 1 }. The new Bj has least element dmin + 2j−^2. Hence every element from the old Bj belongs in a lower indexed bucket. Note that it is crucial that j 6 = L + 3, which comes from our particular application to Dijkstra’s algorithm with bound C on the edges which yields Key Observation above.
  2. WRONG THING: What if j = 10 and B 10 = {dmin, ..., dmin+9}. The buckets as defined above do not work. You could have B 1 , B 2 , B 3 , B 4 as defined, but the new B 5 would have an element from the old B 11 in it. The way around this is to make the max endpoint of Bi for i ≤ j be the max of the value written and mj. With this we need another convention- if si > mi then Bi = ∅.
  3. WRONG THING: What if the new Bj overlaps with Bj+1? It is im- portant that we DO NOT change Bj+1, Bj+2,... since that would be extra work. We will upper bound Bj with sj+1 − 1. We can now define the buckets correctly: B 1 = {dmin} B 2 = {min{dmin + 1, mj }} B 3 = {dmin + 2, min{dmin + 3, mj }} B 4 = {dmin + 4,... , min{dmin + 7, mj }} B 5 = {dmin + 8,... , min{dmin + 15, mj }} B 6 = {dmin + 16,... , min{dmin + 31, mj }} .. . =

Bi = {dmin + 2i−^2 ,... , min{dmin + 2i−^1 − 1 , mj }}(for 2 ≤ i ≤ j) ..

. =

Bj = {dmin + 2j−^2 ,... , min{dmin + 2j−^1 − 1 , sj+1 − 1 }} Bj+1 = old Bj+ ..

. =

BL+1 = old BL+ BL+2 = old BL+ BL+3 = old BL+

Assume that Bj has b elements in it. Amortized cost:

  1. j questions to find that H[j] 6 = ∅. O(j) actual cost.
  2. b elements had to be compared to find the minimum. O(b) actual cost.
  3. j adjustments to the bucket intervals. O(j) actual cost.

The last part of the amortized cost is the possible moving of the b − 1 elements in Bj into lower buckets. First note that every one of them will go into a lower indexed bucket: The old Bj had minimal element dmin and had ≤ 2 j−^2 elements in it. Hence the old Bj is contained in

{dmin,... , dmin + 2j−^2 − 1 }.

The new Bj has least element dmin + 2j−^2. Hence every element from the old Bj will get moved to a lower indexed bucket. Note that it is crucial that j 6 = L + 3, which comes from our particular application to Dijkstra’s algorithm with bound C on the edges. For each of the b − 1 elements in Bj (that are not dmin) we ask a number of questions and then place it in a lower indexed bucket. We count this carefully since we are balancing two things:

  • the more questions you have to ask the more steps you are taking (BAD NEWS)
  • the more questions you have to ask the lower the index of the bucket you place the elements, and hence the more you lower the potential function (GOOD NEWS).

Let x ∈ Bj (the old Bj ). If we have to make q questions to find out which new bucket it is in, then it is in bucket Bj−q. Hence the potential decreases by αq. The potential change of just dealing with x is q − αq = (1 − α)q. Since we will be taking α > 1 the amortized cost is highest when q is lowest. Hence we assume the worst case where every element is placed into Bj− 1. Then the potential change is at at most (b − 1)(1 − α) (which is negative). The total amortized cost is

O(j + b + b(1 − α)). We take α large enough so that this is O(j) = O(L) = O(log C).