Program Listing for File netlist_algo.hpp

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

#include <algorithm>
#include <memory>
#include <pldl/netlist.hpp>
#include <py2cpp/py2cpp.hpp>
#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/algorithm/min_element.hpp>
#include <tuple>
#include <vector>

using node_t = typename SimpleNetlist::node_t;

namespace pldl {

template <typename Netlist, typename C1, typename C2>
auto min_vertex_cover(const Netlist &H, const C1 &weight, C2 &coverset) ->
    typename C1::mapped_type {
    using T = typename C1::mapped_type;
    auto in_coverset = [&](const auto &v) { return coverset.contains(v); };
    [[maybe_unused]] auto total_dual_cost = T(0);
    auto total_primal_cost = T(0);
    auto gap = weight;
    for (auto &&net : H.nets) {
        if (ranges::any_of(H.G[net], in_coverset)) {
            continue;
        }

        auto min_vtx =
            *ranges::min_element(H.G[net], [&](const auto &v1, const auto &v2) {
                return gap[v1] < gap[v2];
            });
        auto min_val = gap[min_vtx];
        coverset.insert(min_vtx);
        total_primal_cost += weight[min_vtx];
        total_dual_cost += min_val;
        for (auto &&u : H.G[net]) {
            gap[u] -= min_val;
        }
    }

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

template <typename Netlist, typename C1, typename C2>
auto min_maximal_matching(const Netlist &H, const C1 &weight, C2 &&matchset,
                          C2 &&dep) -> typename C1::mapped_type {
    auto cover = [&](const auto &net) {
        for (auto &&v : H.G[net]) {
            dep.insert(v);
        }
    };

    auto in_dep = [&](const auto &v) { return dep.contains(v); };

    using T = typename C1::mapped_type;

    auto gap = weight;
    [[maybe_unused]] auto total_dual_cost = T(0);
    auto total_primal_cost = T(0);
    for (auto &&net : H.nets) {
        if (ranges::any_of(H.G[net], in_dep)) {
            continue;
        }
        if (matchset.contains(net)) { // pre-define independent
            cover(net);
            continue;
        }
        auto min_val = gap[net];
        auto min_net = net;
        for (auto &&v : H.G[net]) {
            for (auto &&net2 : H.G[v]) {
                if (ranges::any_of(H.G[net2], in_dep)) {
                    continue;
                }
                if (min_val > gap[net2]) {
                    min_val = gap[net2];
                    min_net = net2;
                }
            }
        }
        cover(min_net);
        matchset.insert(min_net);
        total_primal_cost += weight[min_net];
        total_dual_cost += min_val;
        if (min_net != net) {
            gap[net] -= min_val;
            for (auto &&v : H.G[net]) {
                for (auto &&net2 : H.G[v]) {
                    gap[net2] -= min_val;
                }
            }
        }
    }
    // assert(total_dual_cost <= total_primal_cost);
    return total_primal_cost;
}

} // namespace pldl