XNetwork 1.7.8
Loading...
Searching...
No Matches
cover.hpp
Go to the documentation of this file.
1
10#pragma once
11
12#include <algorithm>
13#include <cassert>
14#include <deque>
15#include <optional>
16#include <py2cpp/dict.hpp>
17#include <py2cpp/set.hpp>
18#include <utility>
19#include <vector>
20
51template <typename MakeViolator, typename WeightMap, typename SolutionSet>
53 -> std::pair<SolutionSet, typename WeightMap::mapped_type> {
54 using CostType = typename WeightMap::mapped_type;
55 using NodeType = typename SolutionSet::value_type;
56
58 auto gap = weight; // copy weights
59 std::vector<NodeType> added_order;
60
61 // Phase 1: Primal-Dual Selection
62 // Repeatedly call the violator for each violation, updating
63 // coverset/gap between calls (lazy evaluation equivalent to the
64 // original coroutine-based generator).
65 {
66 auto next = make_violator();
67 while (auto opt = next()) {
68 auto& violate_set = *opt;
69 if (violate_set.empty()) continue;
70
71 auto min_vtx = *std::min_element(
73 [&](const auto& v1, const auto& v2) { return gap[v1] < gap[v2]; });
74 auto min_val = gap[min_vtx];
75
76 if (!soln.contains(min_vtx)) {
77 soln.insert(min_vtx);
78 added_order.emplace_back(min_vtx);
79 }
80
82
83 for (const auto& vtx : violate_set) {
84 gap[vtx] -= min_val;
85 }
86 }
87 }
88
89 // Phase 2: Reverse-Delete Post-Processing
90 for (auto it = added_order.rbegin(); it != added_order.rend(); ++it) {
91 soln.erase(*it);
92 bool is_redundant = true;
93 {
94 auto check = make_violator();
95 while (auto opt = check()) {
96 if (!opt->empty()) {
97 is_redundant = false;
98 break;
99 }
100 }
101 }
102 if (!is_redundant) {
103 soln.insert(*it);
104 }
105 }
106
108 for (const auto& vtx : soln) {
109 final_prml_cost += weight[vtx];
110 }
111
113 return std::make_pair(soln, final_prml_cost);
114}
115
127template <typename Graph, typename WeightMap, typename CoverSet>
128auto min_vertex_cover(const Graph& ugraph, WeightMap& weight, CoverSet& coverset)
129 -> std::pair<CoverSet, typename WeightMap::mapped_type>;
130
134template <typename Graph, typename WeightMap>
135auto min_vertex_cover(const Graph& ugraph, WeightMap& weight)
136 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
138 return min_vertex_cover(ugraph, weight, coverset);
139}
140
144template <typename Node> struct BFSInfo {
145 Node parent;
146 int depth;
147
148 BFSInfo(Node p, int d) : parent(p), depth(d) {}
149 BFSInfo(const BFSInfo&) = default;
150 BFSInfo(BFSInfo&&) = default;
151 BFSInfo& operator=(const BFSInfo&) = default;
152 BFSInfo& operator=(BFSInfo&&) = default;
153 ~BFSInfo() = default;
154};
155
165template <typename Node> auto construct_cycle(const py::dict<Node, BFSInfo<Node>>& info,
166 Node parent, Node child) -> std::deque<Node>;
167
180template <typename Graph, typename CoverSet>
181auto generic_bfs_cycle(const Graph& ugraph, const CoverSet& coverset)
182 -> std::vector<std::tuple<py::dict<typename Graph::node_t, BFSInfo<typename Graph::node_t>>,
183 typename Graph::node_t, typename Graph::node_t>>;
184
196template <typename Graph, typename WeightMap, typename CoverSet>
197auto min_cycle_cover(const Graph& ugraph, WeightMap& weight, CoverSet& coverset)
198 -> std::pair<CoverSet, typename WeightMap::mapped_type> {
199 using node_t = typename Graph::node_t;
200
201 // Factory: returns a violator that does a fresh BFS each call
202 // and returns the first cycle found (or nullopt if none).
203 auto make_violate = [&]() {
204 return [&ugraph, &coverset]() -> std::optional<std::vector<node_t>> {
206 if (cycles.empty()) return std::nullopt;
207 const auto& [info, parent, child] = cycles[0];
209 return std::vector<node_t>(cycle_deque.begin(), cycle_deque.end());
210 };
211 };
212
213 return pd_cover(make_violate, weight, coverset);
214}
215
219template <typename Graph, typename WeightMap>
220auto min_cycle_cover(const Graph& ugraph, WeightMap& weight)
221 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
223 return min_cycle_cover(ugraph, weight, coverset);
224}
225
237template <typename Graph, typename WeightMap, typename CoverSet>
239 -> std::pair<CoverSet, typename WeightMap::mapped_type>;
240
244template <typename Graph, typename WeightMap>
245auto min_odd_cycle_cover(const Graph& ugraph, WeightMap& weight)
246 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
248 return min_odd_cycle_cover(ugraph, weight, coverset);
249}
Read-only map of maps of maps (view into a dict-of-dict-of-dict structure)
Definition coreviews.hpp:109
AdjacencyView(Atlas &d)
Construct an AdjacencyView from an Atlas container.
Definition coreviews.hpp:115
auto begin() const
Get iterator to the beginning of the view.
Definition coreviews.hpp:55
auto end() const
Get iterator to the end of the view.
Definition coreviews.hpp:61
auto pd_cover(MakeViolator make_violator, WeightMap &weight, SolutionSet &soln) -> std::pair< SolutionSet, typename WeightMap::mapped_type >
Implements a primal-dual approximation algorithm for covering problems.
Definition cover.hpp:52
auto generic_bfs_cycle(const Graph &ugraph, const CoverSet &coverset) -> std::vector< std::tuple< py::dict< typename Graph::node_t, BFSInfo< typename Graph::node_t > >, typename Graph::node_t, typename Graph::node_t > >
Generic BFS cycle detection.
auto min_vertex_cover(const Graph &ugraph, WeightMap &weight, CoverSet &coverset) -> std::pair< CoverSet, typename WeightMap::mapped_type >
Performs minimum weighted vertex cover using primal-dual approximation.
auto min_cycle_cover(const Graph &ugraph, WeightMap &weight, CoverSet &coverset) -> std::pair< CoverSet, typename WeightMap::mapped_type >
Performs minimum cycle cover using primal-dual approximation.
Definition cover.hpp:197
auto min_odd_cycle_cover(const Graph &ugraph, WeightMap &weight, CoverSet &coverset) -> std::pair< CoverSet, typename WeightMap::mapped_type >
Performs minimum odd cycle cover using primal-dual approximation.
auto construct_cycle(const py::dict< Node, BFSInfo< Node > > &info, Node parent, Node child) -> std::deque< Node >
Constructs a cycle from BFS information.
Information structure for BFS traversal.
Definition cover.hpp:144
Node parent
Definition cover.hpp:145
BFSInfo & operator=(const BFSInfo &)=default
~BFSInfo()=default
BFSInfo & operator=(BFSInfo &&)=default
int depth
Definition cover.hpp:146
BFSInfo(const BFSInfo &)=default
BFSInfo(BFSInfo &&)=default
BFSInfo(Node p, int d)
Definition cover.hpp:148