100 long long total_weight = 0;
101 size_t cardinality = 0;
124 for (
size_t i = 0; i < s.nodes.size(); ++i)
127 for (
const auto & e : s.edges)
161 for (
auto it =
matching.get_it(); it.has_curr(); it.next_ne())
163 auto * arc = it.get_curr();
164 size_t u =
static_cast<size_t>(g.
get_src_node(arc)->get_info());
165 size_t v =
static_cast<size_t>(g.
get_tgt_node(arc)->get_info());
172 for (
auto it =
sorted_pairs.get_it(); it.has_curr(); it.next_ne())
173 pairs.
append(it.get_curr());
175 return Solve_Output{result.total_weight, result.cardinality, pairs};
194 for (
size_t i = 0; i < pairs.
size(); ++i)
196 const auto & p = pairs(i);
197 out +=
"(" + std::to_string(p.first) +
"," + std::to_string(p.second) +
")";
198 if (i + 1 < pairs.
size())
220 const Solve_Output &
output,
222 const std::string & file_path)
226 std::ofstream
out(file_path);
229 std::cerr <<
"Cannot write file: " << file_path <<
"\n";
233 out <<
"\\documentclass[tikz,border=10pt]{standalone}\n";
234 out <<
"\\usepackage{tikz}\n";
235 out <<
"\\usetikzlibrary{arrows.meta,calc}\n";
236 out <<
"\\begin{document}\n";
237 out <<
"\\begin{tikzpicture}[x=1cm,y=1cm]\n";
239 out <<
" \\path[shade, left color=cyan!6, right color=blue!5] "
240 <<
"(-4.6,-3.4) rectangle (4.6,3.4);\n";
242 out <<
" \\node[font=\\bfseries\\large] at (0,3.05) {"
243 << s.title <<
"};\n";
245 out <<
" \\node[font=\\small] at (0,2.65) {objective: "
246 << (
max_cardinality ?
"max-cardinality then max-weight" :
"pure max-weight")
250 <<
"edge/.style={draw=black!58, line width=0.95pt, shorten <=2pt, shorten >=2pt},"
251 <<
"match/.style={draw=orange!92!black, line width=2.7pt},"
252 <<
"wlabel/.style={fill=white, inner sep=1.2pt, font=\\scriptsize},"
253 <<
"vertex/.style={circle, draw=black!70, fill=white, minimum size=9mm, inner sep=1pt, font=\\small\\bfseries}"
257 for (
size_t i = 0; i < s.nodes.size(); ++i)
259 const auto & p = s.nodes(i);
260 out <<
" \\node[vertex] (n" << i <<
") at ("
261 << std::fixed << std::setprecision(2) << p.x <<
"," << p.y <<
") {"
262 << p.label <<
"};\n";
269 size_t a = std::min(u, v);
270 size_t b = std::max(u, v);
273 out <<
" \\draw[" << (
matched ?
"match" :
"edge") <<
"] (n"
274 << u <<
") -- (n" << v <<
");\n";
276 out <<
" \\node[wlabel] at ($(n" << u <<
")!0.5!(n" << v <<
")$) {"
280 out <<
" \\node[font=\\small] at (0,-3.05) {matching size = "
282 <<
", total weight = " <<
output.total_weight <<
"};\n";
284 out <<
"\\end{tikzpicture}\n";
285 out <<
"\\end{document}\n";
306 Solve_Output & reference,
318 <<
" -> card " <<
got.cardinality
319 <<
", weight " <<
got.total_weight
322 if (
got.cardinality != reference.cardinality
323 or got.total_weight != reference.total_weight)
325 std::cerr <<
" Warning: backend objective mismatch\n";
339 std::cout <<
"\n" << s.title <<
"\n";
340 std::cout << std::string(s.title.size(),
'-') <<
"\n";
345 ?
"\nMode: maximum-cardinality then maximum-weight\n"
346 :
"\nMode: pure maximum-weight\n");
361 const std::string
tex_path =
"/tmp/weighted_blossom_" + s.slug +
"_" +
suffix +
".tex";
364 std::cout <<
" TikZ export: " <<
tex_path <<
"\n";
384 .slug =
"odd_cycle_bridge",
385 .title =
"Weighted blossom demo: odd cycle + bridge",
413 .title =
"Weighted blossom demo: weight/cardinality trade-off",
437 std::cout <<
"\nDone. Compile generated .tex files with pdflatex to visualize the matchings.\n";
Maximum-weight matching in general undirected graphs.
Default distance accessor for arc weights.
size_t size() const noexcept
Return the current dimension of array.
T & append()
Allocate a new entry to the end of array.
bool is_empty() const noexcept
Return true if the array is empty.
Dynamic doubly linked list with O(1) size and bidirectional access.
Dynamic set backed by balanced binary search trees with automatic memory management.
Arc for graphs implemented with simple adjacency lists.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
DynArray< Graph::Node * > nodes
Main namespace for Aleph-w library functions.
static void suffix(Node *root, DynList< Node * > &acc)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Default filter for filtered iterators on arcs.
Arc of graph implemented with double-linked adjacency lists.
Array-based graph implementation.
Lazy and scalable dynamic array implementation.
Dynamic set implementations based on balanced binary search trees.
Generic graph and digraph implementations.
Simple graph implementation with adjacency lists.
int main()
Runs example scenarios demonstrating maximum-weight matching and writes TikZ visualizations.