23#include <py2cpp/dict.hpp>
24#include <py2cpp/set.hpp>
42 constexpr int INF = std::numeric_limits<int>::max() / 2;
85 template <
typename Node,
typename WeightFunc>
87 -> std::vector<std::vector<DualEdge<Node>>> {
90 std::map<std::pair<Node, Node>, std::vector<int>>
edge_face_map;
94 for (
size_t i = 0;
i <
sz; ++
i) {
96 auto v =
f[(
i + 1) %
sz];
97 if (
u >
v) std::swap(
u,
v);
102 std::map<std::pair<int, int>, std::pair<int, std::pair<Node, Node>>>
best;
106 const int w = weight(
u,
v);
120 std::vector<std::vector<DualEdge<Node>>>
dual(
n_face);
124 const auto& [
w, primal] =
info;
134 template <
typename Node>
136 -> std::pair<std::vector<int>, std::vector<int>>;
139 -> std::vector<int> {
140 std::vector<int>
path;
141 const auto*
p =
prev.data();
158 template <
typename Node>
160 -> std::vector<std::pair<int, int>>;
165 template <
typename Node>
167 -> std::vector<std::pair<int, int>>;
172 template <
typename Node>
174 const std::vector<std::vector<int>>&
dist)
175 -> std::vector<std::pair<int, int>> {
205 -> std::vector<py::set<typename Graph::node_t>>;
240 template <
typename Graph,
typename WeightFunc>
242 const std::vector<std::vector<typename Graph::node_t>>&
faces)
244 using node_t =
typename Graph::node_t;
252 if (
faces[
i].size() % 2 == 1) {
260 for (
const auto&
e :
G.edges()) {
271 for (
const auto&
e :
G.edges()) {
282 for (
size_t k = 0;
k <
n_odd; ++
k) {
289 std::vector<std::vector<int>>(
n_odd));
291 for (
size_t i = 0;
i <
n_odd; ++
i) {
294 for (
size_t j = 0;
j <
n_odd; ++
j) {
306 std::map<std::pair<int, int>, std::pair<node_t, node_t>>
dedge_primal;
308 for (
const auto&
e :
dual[
fi]) {
309 int a =
static_cast<int>(
fi);
311 if (
a >
b) std::swap(
a,
b);
317 std::set<std::pair<node_t, node_t>>
excluded;
327 if (
a >
b) std::swap(
a,
b);
330 auto [
pu,
pv] =
it->second;
339 for (
const auto&
e :
G.edges()) {
341 if (
u >
v) std::swap(
u,
v);
365template <
typename Graph,
typename WeightFunc>
367 const std::vector<std::vector<typename Graph::node_t>>&
faces)
390 const std::vector<std::vector<std::vector<typename Graph::node_t>>>&
component_faces)
392 using node_t =
typename Graph::node_t;
393 using edge_t = std::pair<node_t, node_t>;
403 std::vector<std::future<py::set<edge_t>>>
futures;
408 const auto& comp_faces = component_faces[i];
410 auto comp_weight = [&weight](node_t u, node_t v) -> int { return weight(u, v); };
413 std::vector<std::pair<node_t, node_t>>
comp_edges;
418 if (
u >
v) std::swap(
u,
v);
427 using node_t =
typename std::remove_reference<
428 decltype(
comp_edges)>::type::value_type::first_type;
429 const std::vector<std::pair<node_t, node_t>>&
edge_list;
451 const py::set<std::pair<typename Graph::node_t, typename Graph::node_t>>&
cut_edges,
453 using node_t =
typename Graph::node_t;
455 std::map<node_t, std::vector<node_t>>
cut_adj;
463 std::map<node_t, int>
colour;
468 std::queue<node_t>
q;
489 const py::set<std::pair<typename Graph::node_t, typename Graph::node_t>>&
cut_edges)
490 -> std::pair<bool, int> {
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 size() const -> size_t
Get the number of elements in the view.
Definition coreviews.hpp:49
auto end() const
Get iterator to the end of the view.
Definition coreviews.hpp:61
Command pattern: tasks are encapsulated as command objects (std::function<void()>) placed in a shared...
Definition thread_pool.hpp:42
auto validate_max_cut(const Graph &G, const py::set< std::pair< typename Graph::node_t, typename Graph::node_t > > &cut_edges, WeightFunc weight) -> std::pair< bool, int >
Definition hadlock.hpp:449
auto solve_hadlock_max_cut(const Graph &G, WeightFunc weight, const std::vector< std::vector< typename Graph::node_t > > &faces) -> py::set< std::pair< typename Graph::node_t, typename Graph::node_t > >
Solve MAX-CUT for a planar graph using Hadlock's algorithm.
Definition hadlock.hpp:366
Definition hadlock.hpp:40
auto dijkstra(const std::vector< std::vector< DualEdge< Node > > > &dual, int src) -> std::pair< std::vector< int >, std::vector< int > >
auto reconstruct_path(const std::vector< int > &prev, int src, int dst) -> std::vector< int >
Definition hadlock.hpp:138
auto biconnected_components(const Graph &G) -> std::vector< py::set< typename Graph::node_t > >
Decompose a graph into its biconnected components (blocks).
auto exact_mwpm(const std::vector< int > &odd_faces, const std::vector< std::vector< int > > &dist) -> std::vector< std::pair< int, int > >
auto solve_hadlock_component(const Graph &G, WeightFunc weight, const std::vector< std::vector< typename Graph::node_t > > &faces) -> py::set< std::pair< typename Graph::node_t, typename Graph::node_t > >
Solve MAX-CUT for a single planar biconnected component.
Definition hadlock.hpp:241
auto build_dual(const std::vector< std::vector< Node > > &faces, WeightFunc weight) -> std::vector< std::vector< DualEdge< Node > > >
Build the planar dual graph: faces become vertices, shared primal edges become edges with equal weigh...
Definition hadlock.hpp:86
auto min_weight_perfect_matching(const std::vector< int > &odd_faces, const std::vector< std::vector< int > > &dist) -> std::vector< std::pair< int, int > >
Definition hadlock.hpp:173
auto greedy_mwpm(const std::vector< int > &odd_faces, const std::vector< std::vector< int > > &dist) -> std::vector< std::pair< int, int > >
constexpr int INF
Definition hadlock.hpp:42
Definition hadlock.hpp:32
Definition hadlock.hpp:44
std::pair< Node, Node > primal
Definition hadlock.hpp:47
int weight
Definition hadlock.hpp:46
int neighbor
Definition hadlock.hpp:45
size_t operator()(const pair< T1, T2 > &p) const
Definition hadlock.hpp:34