CSOR W4231 (Fall B): Analysis of Algorithms Dec 8, 2020 Homework 6: Due on Dec 14 by 5:30pm (Columbia U time) Instructor: Alex Andoni Instructions. Please follow the homework policy and submission instructions in the Course Information handout. A few highlights to remember: • submission is via GradeScope: https://www.gradescope.com/, where the “student ID” must be your uni (like aa3815), using code JBB3D7 (otherwise we can’t match your homework to you); • You are encouraged (but not required) to use LaTeX, using the provided template; • follow the stated collaboration and academic honesty policies; • write your name, uni, and collaborators on each problem; • make sure to identify the start of each problem in GradeScope, including the ones that you didn’t solve; • if you don’t know how to solve a particular part of a problem, just write “empty”, for which you will get 20% of the points of that part (in contrast, note that non-sensical text may get 0%). “Design an algorithm” entails proving both correctness and runtime bound; also the default expectation is for a deterministic algorithms (unless otherwise stated). Note that, for each bullet item of a problem, you can use the previous bullets as “black box”, even if you didn’t manage to solve them. Similarly, you can use anything from the lectures as black-box. Problem 1 (30pts) a) Suppose that you had a graph G = (V, E, w) with a source s and one negative cost edge (u, v) Design an algorithm that computes the shortest path from source s to v. b) Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 U.S. dollar buys 64 Indian rupees, 1 Indian rupee buys 1.8 Japanese yen, and 1 Japanese yen buys 0.009 U.S. dollars. Then, by converting currencies, a trader can start with 1 U.S. dollar and buy 64 × 1.8 × 0.009 = 1.0368 U.S. dollars, thus turning a profit of 3.68 percent. Suppose that you are given n currencies c1 , c2 , . . . , cn and an n × n table T of exchange rates, such that one unit of currency ci buys T [i, j] units of currency cj . Give an efficient algorithm to determine whether or not there exists a sequence of currencies < ci1 , ci2 , . . . , cik > such that T [i1 , i2 ] · T [i2 , i3 ] · · · T [ik−1 , ik ] · T [ik , i1 ] > 1 . Your algorithm should just return yes or no. (Optional exercise is to find the actual sequence.) 1 Solution a) The shortest path from s to v either uses the edge (u, v) or does not uses it. Therefore, consider the graph G0 where this edge has been removed. Run a Dijkstra’s algorithm from s to u and v. The shortest path is either the shortest path from s to v in G0 or the shortest path from s to u in G0 and the negative edge from u to v, which ever is the shortest. To check for a negative cycle, find the shortest path from v to u in G0 and compare it to the weight of the negative edge. The algorithm runs in total Dijkstra’s algorithm twice (once from s to u and v in G0 and once from v to u in G0 ) and therefore has the same complexity as Dijkstra’s algorithm. b) We consider the graph where the nodes are the currencies (ie vi is ci ) and has weighted directed edges: the weight of edge from ci to cj is − log(T [i, j]). Now, we can prove that an arbitrage exists if and only if there is a negative cycle in this graph: There exists an arbitrage in this graph iff there exists i1 , . . . , ik such that T [i1 , i2 ] · T [i2 , i3 ] . . . T [ik−1 , ik ] · T [ik , i1 ] > 1 iff there exists i1 , . . . , ik such that − log (T [i1 , i2 ] · T [i2 , i3 ] . . . T [ik−1 , ik ] · T [ik , i1 ]) < 0 iff there exists i1 , . . . , ik such that − log(T [i1 , i2 ]) + (− log(T [i2 , i3 ])) + · · · + (− log(T [ik−1 , ik ])) + (− log(T [ik , i1 ])) < 0 ie there is a negative cycle in the graph we have constructed. Running Bellman-Ford in this graph enables us to check if there is an arbitrage. The runtime is O(ne) where e is the number of edges in the graph: there are in total n × (n − 1) edges so the algorithm runs in O(n3 ) Problem 2 (20pts) Fix some graph G with integer capacities c(u, v) for all edges (u, v) ∈ E, and a source s and terminal t. Suppose you are also given a “slightly faulty” flow, given by values f (u, v) for (u, v) ∈ E, which satisfies all except that the “flow conservation” is broken at a single node z 6= s, t. In particular, P flow properties P (u,z)∈E f (u, z) − (z,u)∈E f (z, u) = 1. Design an algorithm that “fixes” the flow f , i.e., outputs a flow 0 f , whose value is the same as that of f (i.e., net flow out of s remains the same), and such that f 0 satisfies all flow constraints. The algorithm should output “not possible” if such f 0 does not exist. Your runtime should be O(e). Solution We fist need to find z. For this, create an array ’AlreadySeen’ which contains a boolean for each edge. For each edge (u, v) that hasn’t been seen already, check whether v is the node at which the flow is broken and mark all edges of the type (x, v) as seen. This takes O(e) time. Consider the residual graph of the flow f . Constructing this graph can be done in O(e) as it looks at each edge, substracts the flow from its capacity and create the reverse edge which is a constant number of operations per edge. Fixing the flow is finding a path where all edges have capacity at least 1 in the residual graph. This can be done using either BFS or DFS. Instead of using a visited array that would 2 take time linear in the number of nodes to create, when visiting a node, we can set the capacity of all incoming edges to 0 to make sure we never visit the node again. Problem 3 (30pts) Suppose we want to solve the s − t shortest path in a weighted directed graph G with the extra condition that the number of edges must be at most k, where k is the smallest number of edges in any path from s to t (ie, length of the shortest path in the unweighted version of the graph). You are to solve this problem by formulating it as an LP. You can assume that all weights are positive. a) For a given graph G = (V, E, w), nodes s, t, and a bound k, formulate the problem of finding the s − t shortest path with at most k edges as an LP program with e = |E| variables. Hint: first think of how you would formulate the program if you could set the unknowns xi to be from {0, 1}, and then relax to 0 ≤ xi ≤ 1. b) Show that the (optimal) value of the obtained LP is upper bounded by the shortest s − t path with at most k edges. c) Show that if the value of your LP is v, then there exists a shortest path of k edges and of weight v. Hint: use flow decomposition theorem. Can any path (with non-zero flow) have length more than k? Solution • We will formulate our LP with a variable fuv for each edge (u, v) in the original graph G. X min wuv fuv f s.t. (u,v)∈E X X fsv − (s,v)∈E (v,s)∈E X fuv − (u,v)∈E:u6=s,t X fvs = 1 X fvu = 0 (v,u)∈E:u6=s,t fuv ≤ k (u,v)∈E ∀(u, v) ∈ E : 0 ≤ fuv ≤ 1 Note that this is the same formulation as a flow problem of sending one unit of flow from s to t with the added condition that we can use at most k edges. • Observe that if we change the above LP to have the unknowns fuv be in {0, 1} instead of 0 ≤ fuv ≤ 1, we have that the problem will return the shortest s − t path with at most k edges. Once we relax the problem with the constraint that 0 ≤ fuv ≤ 1, the optimal value of the LP can only drop because the set of feasible solutions to the original integer linear program is a subset of the feasible solutions of the relaxed linear program we formulated above. Thus, the optimal value of the above LP is upper bounded by the shortest s − t path with at most k edges. 3 • Suppose the value of the LP is v. Since we can view the LP as a flow problem, by the flow decomposition theorem, we can also decompose the output flow into a series of feasible flows with non-zero flow and corresponding paths. Denote these paths as P1 , . . . , Pj with flow values q1 , . . . , qj ∈ [0, 1]. We will then show that it must be that one of these Pi has the same weight as the shortest path with k edges. P – First, we observe that no Pi can have length more than k. The constraint (u,v)∈E fuv ≤ k P can be rewritten in terms of the paths as ji=1 qi |Pi | ≤ k where |Pi | is the number of edges in path Pi . We rewrite the constraint as j X qi (|Pi | − k) + i=1 We also know that P qi = 1 so P j X qi k ≤ k i=1 qi k = k. That enables us to simplify this condition to j X qi (|Pi | − k) ≤ 0 i=1 Finally |Pi | ≥ k for all i as they are paths from s to t and all paths from s to t have at least k edges. If one Pi was such that |Pi | > 0 then the condition wouldn’t hold. Therefore all Pi have at most k edges. Now if a path Pi has a cost greater than v, then replacing Pi by a shortest path of at most k edges (which therefore have cost v) would strictly decrease P the cost. Therefore, the optimal solution only has paths of cost v. The total cost is therefore qi v = v. Problem 4 (20pts) In this problem, you’ll have to reduce the optimization version to decision version of the problem LONGEST-SIMPLE-PATH. The LONGEST-SIMPLE-PATH problem is as follows: given an directed unweighted graph G = (N, E), and nodes s, t, find the longest simple s − t path, i.e., a path from s to t where each node appears at most once. The decision version of the LONGEST-SIMPLE-PATH problem is as follows: given also a parameter b ≥ 1, is the LONGEST-SIMPLE-PATH length at least b ? Now suppose we have a magic algorithm M that solves the above decision version of the problem in polynomial time. Prove that, in this case, we can recover, in polynomial time, the actual longest simple path. No need to analyze the run-time/correctness. Solution First, we find the maximum length of the longest single path. To do this, we can start at b? = |E| and iterate backwards till we find a value of b? such that M returns True. Given b? , we then recover the actual longest simple path as follows. • Initialize a path with just the start vertex s. 4 • We start with the vertex s and consider all edges (s, v) ∈ E. Iterating over these edges one at a time, we run M on the graph without node s and all the edges connected to s with b? − 1 as found above. – If it returns False, continue. Else, decrement b? and add v to the path. • Iterate the above step with the chosen vertex v until b? = 0, at which point we return the path. Few notes on common issues/alternative solutions: 1. Some students did not delete nodes in the graph after doing the above, this can result in wrong / non-simple paths. 2. Some students deleted adjacent vertices that do not decrease the path and kept the first one that decreases it and added it to the path. This is wrong since you may find an adjacent node that is non-adjacent in the longest path (you may even keep t for example in first iteration if s-t connected). 3. Some students gave an alternative solution of iterating over e ∈ E and deleting edges which decreases the longest path. This nice solution works as well! 4. (3) above can also be done by removing vertices, but then you need to output a path as well, which can be done in a numerous ways in poly time... 5. Note if you dont delete unnecessary edges you may not make anny progress (consider the full graph). 6. Some students did some mixtures of the above in a wrong way, like going over edges first in arbitrary way but then only look at adjacent nodes / edges - those are usually wrong since you may end up with finding/deleting a middle edge and then stuck in the middle in some way... 5