27 February 2014

Fork me on GitHub

  • DP for hard problems
    • Non-trivial exponential time
    • Approximation algorithms
      • Reduced precision
def RSP2(G, s, t, L):
  best <- RSP2(G, s, t, L/2)
  for each u in V do:
    best <- min(best, RSP2(G, s, u, L/2) + RSP2(G, u, t, L/2))
def DP2SP:
  initialize D[v, w, l], v in V, w in V, l in {0, ..., ceil(log(n))} to infinity.
  for u in V: D[u, u, 0] <- 0
  for u in V, v in N(u): D[u, v, 0] <- w((u, v))
  for l = 1 to ceil(log(n)):
    for v in V, w in V:
      best <- D[v, w, l - 1]
      for u in V:
        best <- min(best, D[v, u, l - 1] + D[u, w, l - 1])
      D[v, w, l] <- best
  return (D[v, w] = D(v, w, ceil(log(n)))

The above has complexity \( O(n ^ 3 \log n) \). Recall Bellman-Ford is \( O(|V| |E|) \), but recall this algorithm gives all pairs distances where BF only gives the distance between a fixed pair. There's another even better algorithm called Floyd's. This one is sometimes called the "matrix-multiply based algorithm", but the name is confusing.

Hamiltonian Path

For the problem of finding a longest path, we'll need to require the path be simple.

def RHP(G, s):
  if |V| = 1 return True;
  for each u in N(s):
    if RHP(G - {s}, u): return True;
  return False; 

The above has complexity \( O((n-1)!) \).

def DPHP:
  initialize H[S, u], S a subset of V, u in V
  for u in V:
    H[{u}, u] <- True
  for k = 2 to n:
    for each S a subset of V, where |S| = k and each s in S:
      found <- False
      for each u in intersect(N(s), S):
        if H[S -{s}, u]:
          found <- True
      H[S, s] <- found
  return H[V, s]

The above has \( O(n 2 ^ n) \) subproblems and \( O(n^2 2^n) \) complexity.

Min makespan

2-machine scheduling. Time jobs will take: a1, a2, ..., an. Assign each job to a machine to minimize the time all jobs are finished. The problem is NP-hard, but there is a poly-time algorithm in n and \( \max a_i \leq 2^l \). \( O(n ^ {O(1)} 2 ^ l) \).

We'll need to keep track of the difference between the total time scheduled to the two machines.

def RMM(a1, ..., an, L1, L2):
  if n == 0: return max(L1, L2)
  return min(RMM(a2, ..., an, L1 + a1, L2), RMM(a2, ..., an, L1, L2 + a1))

Let \( A = \max a_i \). Note \( L_1 \leq i A \) at step \( i \), and \( L_2 = \sum_{j = 1}^i a_j - L_1 \).

def DPM(a1, ..., an):
  Sum <- sum(ai)
  A <- max ai
  initialize LB[I, L1]
  for L1 = 0 to n * A:
    LB[n+1, L1] <- max(L1, Sum - L1)
  for I = n down to 1
    for L1 = 0 to (I-1) * A
      LB[I, L1] <- min (LB[I + 1, L1 + a], LB[I + 1, L1])
  return LB[1, 0]

Approximation

Within a factor of \( 1 + \epsilon \). Define Sum as the sum of the ai. \( B := \epsilon Sum / (2n) \). Define aiHat = ceil(ai/B).