CSE 101 Algorithm Design and Analysis Sanjoy Dasgupta Russell Impagliazzo Ragesh Jaiswal (Thanks Miles Jones) Lecture 29: Dynamic Programming (Shortest Paths)
SHORTEST PATHS Given a graph with edge weights, find paths that minimize total weight of edges used Dijkstraβs shortest path algorithm assumed non-negative edge weights Another easy case: DAG
WHAT IF THERE ARE CYCLES? What if the graph has both negative weights and cycles? If the graph has negative cycles, some distances are negative infinity. Otherwise, πΈππ‘π’ π· β‘ !,# $% &' ()*(} {πΈππ‘π’ π€ + π₯ min π€, π· } ! But this doesnβt give a consistent recursion, because the recursion graph is not a DAG, so recursion loops around cyclesβ¦β¦ How can we make recursion acyclic when the graph is cyclic?
LESSONS Generalizing problems to allow recursion and hence DP Keeping recursions simple Trying multiple recursive algorithms based on different types of case analysis leading to different DP algorithms Using reductions (again)
WHY WE MIGHT WANT TO DO THIS: ARBITRAGE
SOME POSSIBILITIES What vertex do we visit first (after π‘ )? What vertex do we visit last (before π’ )? What is the middle vertex along the path? Do we ever visit vertex π€ ?
FIRST VERTEX Attempt 1: BTSP( π‘, π’, π» ) βͺ If π‘ = π’ return 0 βͺ π := β βͺ For each π€ β π(π‘) do: βͺ π := min( π , ( π₯(π‘, π€) + BTSP( π€, π’, π» ))) βͺ return π
PROBLEM: LOOPING Cycles in graph = cycles in recursive calls
FIRST VERTEX Attempt 2: BTSP( π‘, π’, π» ) βͺ If π‘ = π’ return 0 βͺ π := β βͺ For each π€ β π(π‘) do: βͺ π := min( π , ( π₯(π‘, π€) + BTSP( π€, π’, π» β {π‘} ))) βͺ return π
PROBLEM Changing G in recursive calls: exponentially many sub-graphs. Usable for longest simple path = TSP = NP-complete, so approach seems inherently exponential.
PREVENTING INFINITE RECURSION Letβs put a budget on how deep weβll recurse, π That corresponds to looking at which paths? How large should π be?
PREVENTING INFINITE RECURSION Letβs put a budget on how deep weβll recurse, π That corresponds to looking at paths with at most T edges How large should π be: π = π : search all simple paths. Not all paths we search are simple, but thatβs OK
MINIMUM LENGTH NEGATIVE CYCLE If there is a negative cycle, we can keep going around it. But we can break up any cycle into a set of simple cycles.
MINIMUM LENGTH NEGATIVE CYCLE If there is a negative cycle, we can keep going around it. But we can break up any cycle into a set of simple cycles. If the overall cycle is negative, at least one simple cycle is negative. So if there is any negative cycle, there is one of size at most π
PREVENTING INFINITE RECURSION Letβs put a budget on how deep weβll recurse, π That corresponds to looking at paths of length at most π If thereβs no negative cycle, then the shortest paths are simple, donβt repeat vertices. So the shortest path between any two vertices is of length at most |π| = π
FIRST VERTEX
BELLMAN-FORD SUBPROBLEMS BF[ π‘, π’, π ]: shortest weight of a path from π‘ to π’ with at most π edges Note: G is also an input to recursion, but G doesnβt change. Only need changing parts as parameters in matrix
BASE CASES: Base case : π = ? BF[ π‘, π’ ,?] = 0 if ?? ?? otherwise
BASE CASES: Base case : π = 0 BF[ π‘, π’ , 0] = 0 if π‘ = π’ β , otherwise
RECURSIVE PART: Check all first steps along path BF[ π‘, π’, π ] := min (BF[ π‘, π’, π β 1 ], min πΆπΊ π£, π’, π β 1 + π₯ π‘, π£ ) -β/ %
BELLMAN-FORD METHOD
BELLMAN-FORD ALGORITHM
BELLMAN-FORD ALGORITHM TIME ANALYSIS
SAVING MEMORY We never use BF( π£, π€, π ) beyond step π + 1 . Itβs OK if weβve made BF( π£, π€, π ) smaller as long as we never make it less than the shortest path length. So we can just use one matrix BF( π£, π€ ) rather than π different matrices, and make both read and write steps from the same Matrix.
ALTERNATIVE RECURSION Bellman-Fordβs recursion based on " What is the first vertex on the path from π£ to π€ ?" What other question could we ask about the path? What is the last vertex on the path? Symmetric
ALTERNATIVE RECURSION Bellman-Fordβs recursion based on " What is the first vertex on the path from π£ to π€ ? " What other question could we ask about the path? What is the last vertex ? (BF in reverse) What is the middle vertex of the path? (Min plus matrix multiply method) Is π€ ' ever used in the path? (Floyd-Warshall algorithm)
MIN-PLUS METHOD
MIN PLUS ALGORITHM
MIN PLUS ALGORITHM
WHICH IS BETTER?
FLOYD WARSHALL Is π€ used at all? Need to eliminate vertices in order, so that remaining vertices are consecutive. Subtlety one: need to distinguish between endpoints and set of intermediate points Subtlety two: implicitly assumes no negative cycles, so that shortest paths can be simple.
FLOYD WARSHALL GENERALIZATION Assuming the shortest paths are simple, find the shortest path in G from π‘ to π’ using intermediate nodes π = {π£ ! , β¦ , π£ " } , where π‘ and π’ may or may not be in π . BTFW( π‘, π’, π», π ) IF π is empty, and π‘ = π’ return 0 IF π is empty and ( π‘, π’ ) is an edge return w( π‘, π’ ) IF π is empty, return infinity Usecase:= BTFW( π‘, π£ " , π», π β {π£ " } ) + BTFW( π£ " , π’, π», π β {π£ " } ) // Use u_k at most once Dontusecase:=BTFW( π‘, π’, π», π β {π£ " } ) // Donβt use π£ " Return max(Usecase, Dontusecase)
REACHABLE SUBPROBLEMS π‘ can be arbitrary, π’ can be arbitrary, π = {π€ 0 , β¦ π€ 1 } for some 0 β€ π β€ π FW[ π‘, π’, π ] : Best path from π‘ to π’ using only π€ 0 , β¦ , π€ 1 as intermediate vertices Base case: π is empty, π = 0 , FW[ π‘, π‘, 0 ]=0, FW( π‘, π’ )=w( π‘, π’ ) for edge ( π‘, π’ ), FW[ π‘, π’, 0 ]= β Recursion: FW[ π‘, π’, π ] = min ( , )
REACHABLE SUBPROBLEMS π‘ can be arbitrary, π’ can be arbitrary, π = {π€ 0 , β¦ π€ 1 } for some 0 β€ π β€ π FW[ π‘, π’, π ] : Best path from π‘ to π’ using only π€ 0 , β¦ , π€ 1 as intermediate vertices Base case: π is empty, π = 0 , FW[ π‘, π‘, 0 ]=0, FW( π‘, π’ )=w( π‘, π’ ) for edge ( π‘, π’ ), FW[ π‘, π’, 0 ]= β Recursion: FW[ π‘, π’, π ] = min(F[ π‘, π€ 1 , π β 1 ]+F[ π€ 1 , π’, π β 1 ], F[ π‘, π’, π β 1 ])) Top down: k decreases, bottom-up : k increases
FW ALGORITHM DPFW( π») Initialize array FW[ π, π, 1 β¦ |π| ] For π‘ in π do: FW[ π‘, π‘, 0 ]:= 0 For edges π‘, π’ β E do: FW[ π‘, π’, 0 ] = w( π‘, π’ ) For π‘ in π do: For π’ in π β {π‘} do: F[ π‘, π’, 0 ]:= β For π = 1 to |π| do: For π‘ in π do: For π’ in π do: FW[ π‘, π’, π ] = min(FW[ π‘, π€ ! , π β 1 ]+FW[ π€ ! , π’, π β 1 ],FW[ π‘, π’, π β 1 ])) Return the matrix FW[ π‘, π’, |π| ] (Note: can save space by reusing single matrix)
WHICH IS BETTER?
Recommend
More recommend