Program Listing for File graph_algo.hpp

Return to documentation for file (pldl/graph_algo.hpp)

// -*- coding: utf-8 -*-
#pragma once

#include <algorithm>
#include <cassert>
#include <numeric>

namespace pldl {

template <typename Graph, typename C1, typename C2>
auto min_vertex_cover(const Graph &G, const C1 &weight, C2 &cover) ->
    typename C1::mapped_type {
    using T = typename C1::mapped_type;

    [[maybe_unused]] auto total_dual_cost = T(0);
    auto total_primal_cost = T(0);
    auto gap = weight;
    for (auto &&e : G.edges()) {
        auto [u, v] = G.end_points(e);
        if (cover.contains(u) || cover.contains(v)) {
            continue;
        }
        if (gap[u] < gap[v]) {
            std::swap(u, v);
        }
        cover.insert(v);
        total_dual_cost += gap[v];
        total_primal_cost += weight[v];
        gap[u] -= gap[v];
        gap[v] = T(0);
    }

    assert(total_dual_cost <= total_primal_cost);
    assert(total_primal_cost <= 2 * total_dual_cost);
    return total_primal_cost;
}

template <typename Graph, typename C1, typename C2>
auto min_maximal_independent_set(const Graph &G, const C1 &weight, C2 &indset,
                                 C2 &dep) -> typename C1::mapped_type {
    using T = typename C1::mapped_type;

    auto cover = [&](const auto &u) {
        dep.insert(u);
        for (auto &&v : G[u]) {
            dep.insert(v);
        }
    };

    auto gap = weight;
    [[maybe_unused]] auto total_dual_cost = T(0);
    auto total_primal_cost = T(0);
    for (auto &&u : G) {
        if (dep.contains(u)) {
            continue;
        }
        if (indset.contains(u)) { // pre-define independent
            cover(u);
            continue;
        }
        auto min_val = gap[u];
        auto min_vtx = u;
        for (auto &&v : G[u]) {
            if (dep.contains(v)) {
                continue;
            }
            if (min_val > gap[v]) {
                min_val = gap[v];
                min_vtx = v;
            }
        }
        cover(min_vtx);
        indset.insert(min_vtx);
        total_primal_cost += weight[min_vtx];
        total_dual_cost += min_val;
        if (min_vtx != u) {
            for (auto &&v : G[u]) {
                gap[v] -= min_val;
            }
        }
    }
    assert(total_dual_cost <= total_primal_cost);
    return total_primal_cost;
}

} // namespace pldl