ADVANCED ALGORITHMS - NP-COMPLETENESS:Approximation Algorithms for NP-Hard Problems

Mastering approximation algorithms for np-hard problems concepts and implementation.

Approximation Algorithms for NP-Hard Problems

Why Approximation?

For NP-hard optimization problems, exact algorithms require exponential time (assuming P ≠ NP). Approximation algorithms run in polynomial time and guarantee a solution within a factor α of optimal.

An α-approximation algorithm returns a solution with cost ≤ α · OPT (for minimization) or value ≥ (1/α) · OPT (for maximization).

2-Approximation for Vertex Cover

def vertex_cover_2_approx(graph):
    """
    2-approximation for minimum vertex cover.
    
    Algorithm: Greedily pick edges and take both endpoints.
    
    Correctness: Every optimal cover must include at least one endpoint
    of each selected edge. Since no two selected edges share an endpoint,
    optimal cover size ≥ (number of selected edges).
    Our cover size = 2 × (number of selected edges) ≤ 2 × OPT.
    """
    cover = set()
    matched = set()
    
    for u, v in graph.edges():
        if u not in matched and v not in matched:
            cover.add(u)
            cover.add(v)
            matched.add(u)
            matched.add(v)
    
    return cover

Greedy log(n)-Approximation for Set Cover

def set_cover_greedy(universe, sets):
    """
    Greedy log(n)-approximation for minimum set cover.
    
    At each step, pick the set covering the most uncovered elements.
    
    Proof: Let k = OPT. After t steps, at most n(1 - 1/k)^t elements
    remain uncovered. After k * ln(n) steps, < 1 element remains.
    So greedy uses ≤ k * ln(n) + 1 = O(OPT * log n) sets.
    """
    uncovered = set(universe)
    cover_indices = []
    
    while uncovered:
        # Find the set covering the most uncovered elements
        best_idx = max(range(len(sets)), 
                       key=lambda i: len(sets[i] & uncovered))
        cover_indices.append(best_idx)
        uncovered -= sets[best_idx]
    
    return cover_indices

PTAS and FPTAS

PTAS (Polynomial-Time Approximation Scheme): For any ε > 0, gives (1+ε)-approximation in poly(n) time (but possibly exponential in 1/ε).

FPTAS (Fully Polynomial-Time Approximation Scheme): For any ε > 0, runs in poly(n, 1/ε) time.

FPTAS for Knapsack

def knapsack_fptas(weights, values, capacity, epsilon):
    """
    FPTAS for 0/1 Knapsack via value scaling.
    
    Scale values down by K = epsilon * max_value / n
    Solve exactly with scaled values (now fit in polynomial range)
    Return solution — at most (1 + epsilon) * OPT by scaling argument
    
    Time: O(n^2 / epsilon)
    """
    n = len(values)
    max_val = max(values)
    K = epsilon * max_val / n  # Scaling factor
    
    # Scale values
    scaled_values = [int(v / K) for v in values]
    max_scaled = sum(scaled_values)
    
    # DP on scaled values
    # dp[v] = minimum weight to achieve value v
    INF = float('inf')
    dp = [INF] * (max_scaled + 1)
    dp[0] = 0
    
    for i in range(n):
        new_dp = dp[:]
        for v in range(scaled_values[i], max_scaled + 1):
            if dp[v - scaled_values[i]] + weights[i] <= capacity:
                new_dp[v] = min(new_dp[v], dp[v - scaled_values[i]] + weights[i])
        dp = new_dp
    
    # Find maximum achievable value
    best_val = 0
    for v in range(max_scaled, -1, -1):
        if dp[v] <= capacity:
            best_val = v * K  # Un-scale
            break
    
    return best_val

Inapproximability

Some NP-hard problems cannot be approximated better than a constant ratio unless P = NP:

  • Clique: No O(n^{1−ε})-approximation for any ε > 0 (Håstad, 1999)
  • Chromatic number: No O(n^{1−ε})-approximation
  • TSP (general metric): No better than (3/2 − ε) unless P = NP

The PCP Theorem (1992–1998): Probabilistically checkable proofs led to a revolution in inapproximability results, showing tight hardness-of-approximation thresholds for many problems.

Practice Problems

  1. Implement the Christofides 1.5-approximation for metric TSP (outline)
  2. Prove that the greedy set cover achieves H(n) ≈ ln(n) approximation
  3. Show that if a problem has a PTAS, it is not APX-hard unless P = NP
  4. Design a 2-approximation for the metric k-median problem