CSE 101 Algorithm Design and Analysis Miles Jones mej016@eng.ucsd.edu Office 4208 CSE Building Lecture 8: Negative Edges
DIJKSTRA S ALGORITHM WITH DIFFERENT PRIORITY QUEUES. Runtime of Array: O V 2 Runtime of Binary heap: O V + E log V Fibonacci Heap!!!: O V log V + E
SHORTEST PATHS WITH NEGATIVE EDGES Dijkstra s algorithm works on graphs with positive edge lengths. It finds all the shortest paths from a given vertex when all the edges have positive edge lengths. (Actually, it works if the edges are non - negative.) In the presence of negative edge lengths, Dijkstra s will not always return the shortest paths.
EXAMPLE S 3 5 A 1 B C -2 The shortest path from S to A passes through B And B is farther away from S than A!!!!! With Dijkstra s algorithm, each time you set dist(), it is an overestimate or equal to the actual distance.
CHANGING DIJKSTRA S I suppose you could change Dijkstra s to reinsert a vertex when it is assigned a new negative weight but then the algorithm may take longer. With positive edge weights, each vertex will be inserted and ejected once. With negative edge weights, each vertex will be inserted and ejected multiple times.
CHANGING DIJKSTRA S procedure dijkstra(g,l,s) for all u in V dist(u) := infinity prev(u) := nil dist(s) := 0 H := makequeue(v) while H is not empty u := deletemin(h) for all edges (u,v) in E if dist(v) > dist(u) + l(u,v) then if v is not in H then insert v back into H dist(v):= dist(u) + l(u,v) prev(v):=u decreasekey(h,v)
DIJKSTRA S WITH NEGATIVE CYCLES A B C
CHANGING DIJKSTRA S What s the worst case scenario? It could be the case that each vertex is inserted and ejected so many times that the algorithm would run in exponential time.
PROCEDURE UPDATE procedure update((u, v) E) dist v min dist v, dist u + l u, v The true shortest distance from S to v can not be more than dist u + l u, v u S v
PROCEDURE UPDATE procedure update((u, v) E) dist v min dist v, dist u + l u, v 1. It gives the correct distance to v in the case where u is the second to last vertex in the shortest path to v and dist(u) is correctly set. 2. It will never make dist(v) too small so it is safe. In other words, updating over and over won t ever hurt.
procedure dijkstra(g,l,s) for all u in V dist(u) := infinity prev(u) := nil dist(s) := 0 H := makequeue(v) while H is not empty u := deletemin(h) for all edges (u,v) in E update(u,v) decreasekey(h,v) DIJKSTRA S USING UPDATE
DIJKSTRA S USING UPDATE Dijkstra s algorithm finds the shortest distance by updating over and over The sequence it performs update goes along the current shortest path up to that point. (it is guaranteed to be the current shortest path up to that point by the fact that the edges are all positive.) This will not work well with negative edges as we have seen. It will work well, however, if the updates are performed along the correct shortest path.
DIJKSTRA S USING UPDATE Dijkstra s algorithm finds the shortest distance by updating over and over The sequence it performs update goes along the current shortest path up to that point. This will not work well with negative edges as we have seen. It will work well in the absence of negative cycles, however, if the updates are performed along the correct shortest path. (How will we know what the shortest path is?)
UPDATING ALONG THE SHORTEST PATH Suppose we update along the shortest path from s to t s u1 u3 uk t This path has at most how many edges?
UPDATING ALONG THE SHORTEST PATH Suppose we update along the shortest path from s to t s u1 u3 uk t This path has at most V 1 edges. because the shortest path could possibly pass through all V edges.
UPDATING ALONG THE SHORTEST PATH Suppose we update along the shortest path from s to t s u1 u3 uk t if the sequence of updates includes (s,u1),(u1,u2),,(uk,t) in that order then by the first property of update, the distance from s to t will be computed correctly. (even if there were other calls of update in between or if you update the same edge twice.)
UPDATING ALONG THE SHORTEST PATH Suppose we update along the shortest path from s to t s u1 u3 uk t How do you get to update in this order if you don t know the order to begin with?
EXERCISE Suppose I want to create a sequence of the numbers 1,2,3,4 that contains every sequence of length 3 as a subsequence. What is the shortest sequence you could create?
EXAMPLE Suppose I want to create a list of the numbers 1,2,3,4 such that every sequence of length 3 shows up. 123412341234 314231423142
UPDATING ALL EDGES V -1 TIMES To ensure that we update all edges in all possible orderings, we can update all edges in a certain order V -1 times.
BELLMAN FORD ALGORITHM procedure BFshortestpath(G,l,S) for all u V dist(u)=infinity dist(s)=0 repeat V -1 times for all e E update(e)
EXAMPLE A B C D E F
BELLMAN FORD RUNTIME procedure BFshortestpath(G,l,S) for all u V dist(u)=infinity dist(s)=0 repeat V -1 times for all e E update(e)
BELLMAN FORD RUNTIME procedure Bfshortestpath(G,l,S) for all u V dist(u)=infinity dist(s)=0 repeat V -1 times for all e E update(e) We are updating each edge V -1 times so the runtime is O V E
BELLMAN FORD RUNTIME procedure Bfshortestpath(G,l,S) for all u V dist(u)=infinity dist(s)=0 while dist() values don t change for all e E update(e) We can watch the values of dist() and if they don t change after an iteration then they will not change anymore and we can terminate the algorithm there.
EXAMPLE
NEGATIVE CYCLES
BELLMAN FORD We restrict our input graphs to be graphs with no negative cycles. What kinds of graphs are guaranteed to not have negative cycles? How can we detect if a graph has a negative cycle?
BELLMAN FORD TO DETECT NEGATIVE CYCLES. Run Bellman Ford and update V -1 times. Then update one more time and see if the values change. procedure Bfshortestpath(G,l,S) for all u V dist(u)=infinity dist(s)=0 while dist() values don t change or you have repeated V -1 times for all e E update(e) for all e E update(e) if dist value has changed: return negative cycle!!!!
DAGS WITH EDGE WEIGHTS How can we adjust Bellman Ford to work on DAGs and get a better runtime?
DAGS WITH EDGE WEIGHTS How can we adjust Bellman Ford to work on DAGs and get a better runtime? Linearize the DAG with DFS then update the edges in that order only 1 time!!!! DFS takes O V + E and updating the edges one time takes O E So for a DAG, we can find the shortest path in linear time!!
DAGS WITH (NEGATIVE) EDGE WEIGHTS
DAGS WITH (NEGATIVE) EDGE WEIGHTS
APPLICATION: CURRENCY EXCHANGE EUR GBP CHF USD AUD CAD HKD INR JPY SAR SGD ZAR SEK AED EUR 0.9007 1.0946 1.1151 1.4651 1.4716 8.6508 74.1617 115.4468 4.1826 1.5327 15.4025 9.6431 4.0956 GBP 1.1103 1.2154 1.2381 1.6268 1.6339 9.6054 82.3453 128.1861 4.6441 1.7018 17.1021 10.7072 4.5476 CHF 0.9136 0.8228 1.0187 1.3385 1.3444 7.9034 67.7539 105.4717 3.8212 1.4003 14.0717 8.8099 3.7417 USD 0.8968 0.8077 0.9816 1.3139 1.3197 7.7581 66.5083 103.5327 3.7509 1.3745 13.813 8.648 3.673 AUD 0.6825 0.6147 0.7471 0.7611 1.0044 5.9046 50.6185 78.7972 2.8548 1.0461 10.5128 6.5818 2.7954 CAD 0.6795 0.612 0.7438 0.7577 0.9956 5.8787 50.3966 78.4519 2.8423 1.0416 10.4668 6.553 2.7832 HKD 0.1156 0.1041 0.1265 0.1289 0.1694 0.1701 8.5728 13.3452 0.4835 0.1772 1.7805 1.1147 0.4734 INR 0.0135 0.0121 0.0148 0.015 0.0198 0.0198 0.1166 1.5567 0.0564 0.0207 0.2077 0.13 0.0552 JPY 0.0087 0.0078 0.0095 0.0097 0.0127 0.0127 0.0749 0.6424 0.0362 0.0133 0.1334 0.0835 0.0355 SAR 0.2391 0.2153 0.2617 0.2666 0.3503 0.3518 2.0683 17.7312 27.6019 0.3664 3.6825 2.3056 0.9792 SGD 0.6524 0.5876 0.7141 0.7275 0.9559 0.9601 5.6442 48.3862 75.3222 2.7289 10.0492 6.2916 2.6722 ZAR 0.0649 0.0585 0.0711 0.0724 0.0951 0.0955 0.5616 4.8149 7.4953 0.2716 0.0995 0.6261 0.2659 SEK 0.1037 0.0934 0.1135 0.1156 0.1519 0.1526 0.8971 7.6906 11.9719 0.4337 0.1589 1.5972 0.4247 AED 0.2442 0.2199 0.2673 0.2723 0.3577 0.3593 2.1122 18.1075 28.1878 1.0212 0.3742 3.7607 2.3545
APPLICATION: CURRENCY EXCHANGE
APPLICATION: CURRENCY EXCHANGE
APPLICATION: CURRENCY EXCHANGE Running Bellman-Ford starting at USD -log(rate) {'AED': -1.3569766261091263, 'AUD': -0.32942422934958415, 'CAD': -0.3333872159204456, 'CHF': -0.038369472419163664, 'EUR': 0.050366486630700535, 'GBP': 0.15716097246122818, 'HKD': -2.104734435635327, 'INR': -4.253321179933133, 'JPY': -4.695884613184539, 'SAR': -1.3781426689855023, 'SEK': -2.213322376052226, 'SGD': -0.3740745229364695, 'USD': -0.05843637321809858, 'ZAR': -2.681581736396172}, rate {'AED': 3.8844314419022132, 'AUD': 1.3901674803567063, 'CAD': 1.3956876263201596, 'CHF': 1.0391150863272347, 'EUR': 0.9508808755070799, 'GBP': 0.8545664860747241, 'HKD': 8.204923784874282, 'INR': 70.33863210339331, 'JPY': 109.49562708743326, 'SAR': 3.9675257712460703, 'SEK': 9.14605259711769, 'SGD': 1.4536454763499036, 'USD': 1.0601775278642156, 'ZAR': 14.608181323561656} {'AED': 'SGD', 'AUD': 'INR', 'CAD': 'SEK', 'CHF': 'INR', 'EUR': 'JPY', 'GBP': 'ZAR', 'HKD': 'SEK', 'INR': 'SEK', 'JPY': 'SEK', 'SAR': 'ZAR', 'SEK': 'ZAR', 'SGD': 'JPY', 'USD': 'JPY', 'ZAR': 'AED'}, 'negative cycle!!!!')
NEGATIVE CYCLE (SHORTEST PATH TREE) {'AED': 'SGD', 'AUD': 'INR', 'CAD': 'SEK', 'CHF': 'INR', 'EUR': 'JPY', 'GBP': 'ZAR', 'HKD': 'SEK', 'INR': 'SEK', 'JPY': 'SEK', 'SAR': 'ZAR', 'SEK': 'ZAR', 'SGD': 'JPY', 'USD': 'JPY', 'ZAR': 'AED'}, 'negative cycle!!!!')
CURRENCY BUY AND SELL RATES ({'AED': 0.7509881802497953, 'AUD': 1.7701936913134944, 'CAD': 1.7866256697565166, 'CHF': 2.07901363324571, 'EUR': 2.168137158022813, 'GBP': 2.263299381953173, 'HKD': 0, 'INR': -2.1352013979244284, 'JPY': -2.5714197194487083, 'SAR': 0.7507077352299669, 'SEK': -0.10344098068135654, 'SGD': 1.7460515932893461, 'USD': 2.067010488384354, 'ZAR': -0.5921926753589133}, {'AED': 'HKD', 'AUD': 'HKD', 'CAD': 'AED', 'CHF': 'AED', 'EUR': 'AUD', 'GBP': 'AED', 'HKD': '', 'INR': 'AUD', 'JPY': 'AUD', 'SAR': 'JPY', 'SEK': 'JPY', 'SGD': 'AED', 'USD': 'AED', 'ZAR': 'JPY'})
{'AED': 'HKD', 'AUD': 'HKD', 'CAD': 'AED', 'CHF': 'AED', 'EUR': 'AUD', 'GBP': 'AED', 'HKD': '', 'INR': 'AUD', 'JPY': 'AUD', 'SAR': 'JPY', 'SEK': 'JPY', 'SGD': 'AED', 'USD': 'AED', 'ZAR': 'JPY'}) SHORTEST PATH TREE