XNetwork 1.7.5; VERSION ${PROJECT_VERSION}
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
35template <typename MakeViolator, typename WeightMap, typename SolutionSet>
37 -> std::pair<SolutionSet, typename WeightMap::mapped_type> {
38 using CostType = typename WeightMap::mapped_type;
39 using NodeType = typename SolutionSet::value_type;
40
42 auto gap = weight; // copy weights
43 std::vector<NodeType> added_order;
44
45 // Phase 1: Primal-Dual Selection
46 // Repeatedly call the violator for each violation, updating
47 // coverset/gap between calls (lazy evaluation equivalent to the
48 // original coroutine-based generator).
49 {
50 auto next = make_violator();
51 while (auto opt = next()) {
52 auto& violate_set = *opt;
53 if (violate_set.empty()) continue;
54
55 auto min_vtx = *std::min_element(
57 [&](const auto& v1, const auto& v2) { return gap[v1] < gap[v2]; });
58 auto min_val = gap[min_vtx];
59
60 if (!soln.contains(min_vtx)) {
61 soln.insert(min_vtx);
62 added_order.emplace_back(min_vtx);
63 }
64
66
67 for (const auto& vtx : violate_set) {
68 gap[vtx] -= min_val;
69 }
70 }
71 }
72
73 // Phase 2: Reverse-Delete Post-Processing
74 for (auto it = added_order.rbegin(); it != added_order.rend(); ++it) {
75 soln.erase(*it);
76 bool is_redundant = true;
77 {
78 auto check = make_violator();
79 while (auto opt = check()) {
80 if (!opt->empty()) {
81 is_redundant = false;
82 break;
83 }
84 }
85 }
86 if (!is_redundant) {
87 soln.insert(*it);
88 }
89 }
90
92 for (const auto& vtx : soln) {
93 final_prml_cost += weight[vtx];
94 }
95
97 return std::make_pair(soln, final_prml_cost);
98}
99
111template <typename Graph, typename WeightMap, typename CoverSet>
112auto min_vertex_cover(const Graph& ugraph, WeightMap& weight, CoverSet& coverset)
113 -> std::pair<CoverSet, typename WeightMap::mapped_type>;
114
118template <typename Graph, typename WeightMap>
119auto min_vertex_cover(const Graph& ugraph, WeightMap& weight)
120 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
122 return min_vertex_cover(ugraph, weight, coverset);
123}
124
128template <typename Node> struct BFSInfo {
129 Node parent;
130 int depth;
131
132 BFSInfo(Node p, int d) : parent(p), depth(d) {}
133 BFSInfo(const BFSInfo&) = default;
134 BFSInfo(BFSInfo&&) = default;
135 BFSInfo& operator=(const BFSInfo&) = default;
136 BFSInfo& operator=(BFSInfo&&) = default;
137 ~BFSInfo() = default;
138};
139
149template <typename Node> auto construct_cycle(const py::dict<Node, BFSInfo<Node>>& info,
150 Node parent, Node child) -> std::deque<Node>;
151
164template <typename Graph, typename CoverSet>
165auto generic_bfs_cycle(const Graph& ugraph, const CoverSet& coverset)
166 -> std::vector<std::tuple<py::dict<typename Graph::node_t, BFSInfo<typename Graph::node_t>>,
167 typename Graph::node_t, typename Graph::node_t>>;
168
180template <typename Graph, typename WeightMap, typename CoverSet>
181auto min_cycle_cover(const Graph& ugraph, WeightMap& weight, CoverSet& coverset)
182 -> std::pair<CoverSet, typename WeightMap::mapped_type> {
183 using node_t = typename Graph::node_t;
184
185 // Factory: returns a violator that does a fresh BFS each call
186 // and returns the first cycle found (or nullopt if none).
187 auto make_violate = [&]() {
188 return [&ugraph, &coverset]() -> std::optional<std::vector<node_t>> {
190 if (cycles.empty()) return std::nullopt;
191 const auto& [info, parent, child] = cycles[0];
193 return std::vector<node_t>(cycle_deque.begin(), cycle_deque.end());
194 };
195 };
196
197 return pd_cover(make_violate, weight, coverset);
198}
199
203template <typename Graph, typename WeightMap>
204auto min_cycle_cover(const Graph& ugraph, WeightMap& weight)
205 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
207 return min_cycle_cover(ugraph, weight, coverset);
208}
209
221template <typename Graph, typename WeightMap, typename CoverSet>
223 -> std::pair<CoverSet, typename WeightMap::mapped_type>;
224
228template <typename Graph, typename WeightMap>
229auto min_odd_cycle_cover(const Graph& ugraph, WeightMap& weight)
230 -> std::pair<py::set<typename Graph::node_t>, typename WeightMap::mapped_type> {
232 return min_odd_cycle_cover(ugraph, weight, coverset);
233}
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:36
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:181
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:128
Node parent
Definition cover.hpp:129
BFSInfo & operator=(const BFSInfo &)=default
~BFSInfo()=default
BFSInfo & operator=(BFSInfo &&)=default
int depth
Definition cover.hpp:130
BFSInfo(const BFSInfo &)=default
BFSInfo(BFSInfo &&)=default
BFSInfo(Node p, int d)
Definition cover.hpp:132