1

I am working on the Vertex Cover problem and trying to compare the performance of three different algorithms: Greedy (GRY), Pricing Algorithm (PA), and LP-based Rounding (LR). Specifically, I want to compare them over randomly generated instances with two parameters: n denoting the number of nodes taking values among {100, 120, 140, 160, 180, 200}, and p ∈ {0.1, 0.2, 0.3, 0.4, 0.5} representing the uniform probability of an edge existing among each pair of nodes.

For each given pair (n, p), I want to do the following sequentially:

  • Generate M = 100 random graphs with each vertex cost uniformly sampled from [0, 1].
  • For each randomly generated instance, implement the three algorithms and compute the ratio of the total cost on the vertex cover returned by the algorithm to that on the optimal, which can be obtained by solving an Integral Program (IP).
  • Compute the average ratio over the M = 100 randomly generated instances for each of the three algorithms, denoted as τg(n, p), τp(n, p) and τl(n, p), which represent the performance of GRY, PA, and LR, respectively. However, I'm having trouble computing the ratios and comparing the performance of the algorithms.

How can I improve my implementation and comparison of the algorithms?

import random
import numpy as np
import matplotlib.pyplot as plt


import pulp


def generate_random_graph(n, p):
    adj_matrix = [[0 for _ in range(n)] for _ in range(n)]
    costs = [random.random() for _ in range(n)]

    for i in range(n):
        for j in range(i + 1, n):
            if random.random() < p:
                adj_matrix[i][j] = 1
                adj_matrix[j][i] = 1

    return adj_matrix, costs

def greedy_vc(adj_matrix, costs):
    n = len(adj_matrix)
    covered_edges = set()
    vertex_cover = set()

    while True:
        uncovered_edges = [(i, j) for i in range(n) for j in range(i + 1, n) if adj_matrix[i][j] == 1 and (i, j) not in covered_edges]

        if not uncovered_edges:
            break

        cost_ratio = [(i, costs[i] / sum(adj_matrix[i])) for i in range(n) if sum(adj_matrix[i]) > 0]
        selected_vertex = min(cost_ratio, key=lambda x: x[1])[0]

        vertex_cover.add(selected_vertex)
        for j in range(n):
            if adj_matrix[selected_vertex][j] == 1:
                covered_edges.add((min(selected_vertex, j), max(selected_vertex, j)))

    return vertex_cover

def pricing_algorithm_vc(adj_matrix, costs):
    n = len(adj_matrix)
    remaining_edges = {(i, j) for i in range(n) for j in range(i + 1, n) if adj_matrix[i][j] == 1}
    vertex_cover = set()

    while remaining_edges:
        edge = remaining_edges.pop()
        u, v = edge
        if costs[u] < costs[v]:
            vertex_cover.add(u)
            for j in range(n):
                if adj_matrix[u][j] == 1:
                    remaining_edges.discard((min(u, j), max(u, j)))
        else:
            vertex_cover.add(v)
            for j in range(n):
                if adj_matrix[v][j] == 1:
                    remaining_edges.discard((min(v, j), max(v, j)))

    return vertex_cover

def lp_rounding_vc(adj_matrix, costs):
    n = len(adj_matrix)
    prob = pulp.LpProblem("VertexCoverLP", pulp.LpMinimize)
    x_vars = [pulp.LpVariable(f"x_{i}", 0, 1, pulp.LpContinuous) for i in range(n)]

    prob += pulp.lpSum(costs[i] * x_vars[i] for i in range(n))

    for i in range(n):
        for j in range(i + 1, n):
            if adj_matrix[i][j] == 1:
                prob += x_vars[i] + x_vars[j] >= 1

    prob.solve()

    vertex_cover = set(i for i in range(n) if x_vars[i].value() >= 0.5)

    return vertex_cover

def optimal_vc(adj_matrix, costs):
    n = len(adj_matrix)
    prob = pulp.LpProblem("VertexCoverIP", pulp.LpMinimize)
    x_vars = [pulp.LpVariable(f"x_{i}", 0, 1, pulp.LpInteger) for i in range(n)]

    prob += pulp.lpSum(costs[i] * x_vars[i] for i in range(n))

    for i in range(n):
        for j in range(i + 1, n):
            if adj_matrix[i][j] == 1:
                prob += x_vars[i] + x_vars[j] >= 1
    prob.solve()

    vertex_cover = set(i for i in range(n) if x_vars[i].value() == 1)

    return vertex_cover


def compare_algorithms(n_values, p_values):
    champions = np.zeros((len(n_values), len(p_values)), dtype=int)

    for n_idx, n in enumerate(n_values):
        for p_idx, p in enumerate(p_values):
            gry_ratios = []
            pa_ratios = []
            lr_ratios = []

            for _ in range(10):
                adj_matrix, costs = generate_random_graph(n, p)
                gry_cover = greedy_vc(adj_matrix, costs)
                pa_cover = pricing_algorithm_vc(adj_matrix, costs)
                lr_cover = lp_rounding_vc(adj_matrix, costs)
                opt_cover = optimal_vc(adj_matrix, costs)

                if not opt_cover:
                    continue

                gry_ratios.append(
                    sum(costs[v] for v in gry_cover) / sum(costs[v]
                                                           for v in opt_cover))
                pa_ratios.append(
                    sum(costs[v] for v in pa_cover) / sum(costs[v]
                                                          for v in opt_cover))
                lr_ratios.append(
                    sum(costs[v] for v in lr_cover) / sum(costs[v]
                                                          for v in opt_cover))

            avg_gry = np.mean(gry_ratios)
            avg_pa = np.mean(pa_ratios)
            avg_lr = np.mean(lr_ratios)

            min_ratio = min(avg_gry, avg_pa, avg_lr)
            if min_ratio == avg_gry:
                champions[n_idx][p_idx] = 1
            elif min_ratio == avg_pa:
                champions[n_idx][p_idx] = 2
            else:
                champions[n_idx][p_idx] = 3

    return champions


def plot_champions(champions, n_values, p_values):
    colors = {1: 'red', 2: 'blue', 3: 'black'}
    for i, n in enumerate(n_values):
        for j, p in enumerate(p_values):
            plt.scatter(n, p, color=colors[champions[i][j]], marker='s')
    plt.xlabel('n')
    plt.ylabel('p')
    plt.show()


n_values = [2,3]
p_values = [0.1, 0.2]

champions = compare_algorithms(n_values, p_values)
plot_champions(champions, n_values, p_values)

the weeknd
  • 11
  • 2

0 Answers0