89#include <tclap/CmdLine.h>
108 cout <<
"\n" << string(60,
'=') <<
"\n";
110 cout << string(60,
'=') <<
"\n\n";
120 cout << label <<
": {";
122 for (
auto it =
nodes.get_it(); it.has_curr(); it.next())
125 cout << it.get_curr()->get_info();
136 auto arc = it.get_curr();
150 cout <<
"A bipartite graph has two disjoint vertex sets L and R,\n";
151 cout <<
"where every edge connects a vertex in L to a vertex in R.\n";
152 cout <<
"No edges exist within L or within R.\n\n";
177 cout <<
"Workers: {Juan, Maria, Carlos}\n";
178 cout <<
"Tasks: {Cocinar, Limpiar, Comprar}\n\n";
179 cout <<
"Skills (edges):\n";
180 cout <<
" Juan -- Cocinar, Limpiar\n";
181 cout <<
" Maria -- Limpiar, Comprar\n";
182 cout <<
" Carlos -- Cocinar, Comprar\n\n";
192 cout <<
"Graph IS bipartite!\n\n";
196 catch (
const exception& e)
198 cout <<
"Graph is NOT bipartite: " << e.what() <<
endl;
210 cout <<
"A graph is bipartite ⟺ it has no odd-length cycles.\n";
211 cout <<
"Equivalently: it can be 2-colored.\n\n";
226 cout <<
"Square: A-B-C-D-A (cycle of length 4 = even)\n";
232 cout <<
"Result: BIPARTITE\n";
238 cout <<
"Result: NOT bipartite\n";
252 cout <<
"Triangle: X-Y-Z-X (cycle of length 3 = odd)\n";
258 cout <<
"Result: BIPARTITE\n";
260 catch (
const exception& e)
262 cout <<
"Result: NOT bipartite\n";
263 cout <<
"Reason: Cannot 2-color an odd cycle!\n";
270 auto u1 =
k33.insert_node(
"U1");
271 auto u2 =
k33.insert_node(
"U2");
272 auto u3 =
k33.insert_node(
"U3");
273 auto v1 =
k33.insert_node(
"V1");
274 auto v2 =
k33.insert_node(
"V2");
275 auto v3 =
k33.insert_node(
"V3");
282 cout <<
"K3,3: Complete bipartite (all U's connected to all V's)\n";
283 cout <<
" 9 edges, 6 vertices\n";
289 cout <<
"Result: BIPARTITE\n";
295 cout <<
"Result: NOT bipartite\n";
307 cout <<
"A matching is a set of edges with no shared vertices.\n";
308 cout <<
"Maximum matching = largest possible matching.\n\n";
310 cout <<
"Application: Assign workers to tasks (one task per worker).\n\n";
315 cout <<
"Workers: Ana, Bob, Cam, Dan\n";
316 cout <<
"Tasks: Programar, Diseñar, Testear, Documentar\n\n";
317 cout <<
"Skills (edges in bipartite graph):\n";
318 cout <<
" Ana: Programar, Testear\n";
319 cout <<
" Bob: Programar, Diseñar\n";
320 cout <<
" Cam: Diseñar, Documentar\n";
321 cout <<
" Dan: Testear, Documentar\n\n";
323 cout <<
"Maximum matching algorithm:\n";
324 cout <<
"1. Build flow network with source -> L, R -> sink\n";
325 cout <<
"2. Each edge has capacity 1\n";
326 cout <<
"3. Maximum flow = maximum matching size\n\n";
328 cout <<
"Optimal assignment for this example:\n";
329 cout <<
" Ana -- Programar (or Testear)\n";
330 cout <<
" Bob -- Diseñar (or Programar)\n";
331 cout <<
" Cam -- Documentar (or Diseñar)\n";
332 cout <<
" Dan -- Testear (or Documentar)\n\n";
334 cout <<
"Result: All 4 workers can be assigned!\n";
339 cout <<
"3 students, 2 courses:\n";
340 cout <<
" Student1 wants CourseA only\n";
341 cout <<
" Student2 wants CourseA only\n";
342 cout <<
" Student3 wants CourseB only\n\n";
344 cout <<
"Maximum matching: 2 students get assigned\n";
345 cout <<
" Student1 -- CourseA (or Student2)\n";
346 cout <<
" Student3 -- CourseB\n\n";
348 cout <<
"One student without a course (conflict over CourseA).\n";
354 auto ana =
jobs.insert_node(
"Ana");
355 auto bob =
jobs.insert_node(
"Bob");
356 auto prog =
jobs.insert_node(
"Programar");
357 auto dise =
jobs.insert_node(
"Diseñar");
367 cout <<
"Small graph verified as bipartite:\n";
373 cout <<
"Graph is not bipartite\n";
385 cout <<
"Match compatible people maximizing the number of dates.\n\n";
387 cout <<
"Compatibility graph:\n";
388 cout <<
" Sofia <-> Andres, Miguel\n";
389 cout <<
" Lucia <-> Miguel, David\n";
390 cout <<
" Camila <-> Andres, David\n\n";
394 auto p1 =
dating.insert_node(
"Sofia");
395 auto p2 =
dating.insert_node(
"Lucia");
396 auto p3 =
dating.insert_node(
"Camila");
397 auto q1 =
dating.insert_node(
"Andres");
398 auto q2 =
dating.insert_node(
"Miguel");
399 auto q3 =
dating.insert_node(
"David");
401 dating.insert_arc(p1, q1, 1);
404 dating.insert_arc(p2, q3, 1);
405 dating.insert_arc(p3, q1, 1);
406 dating.insert_arc(p3, q3, 1);
414 cout <<
"\nMaximum matching analysis:\n";
415 cout <<
" Each person in Group A has 2 compatible matches\n";
416 cout <<
" Hall's condition: every subset has enough neighbors\n\n";
418 cout <<
"Optimal pairing (found via max-flow):\n";
419 cout <<
" Sofia <3 Miguel\n";
420 cout <<
" Lucia <3 David\n";
421 cout <<
" Camila <3 Andres\n\n";
423 cout <<
"All 3 people get a date! (Perfect matching exists)\n";
434 cout <<
"Hall's Theorem: A bipartite graph G=(L,R,E) has a matching\n";
435 cout <<
"covering all of L if and only if for every subset S of L,\n";
436 cout <<
"|N(S)| >= |S| where N(S) = neighbors of S.\n\n";
438 cout <<
"In other words: Every subset of L must have 'enough' neighbors.\n\n";
443 cout <<
"Graph: Each H has 2 choices among W's\n";
444 cout <<
" H1 <-> W1, W2\n";
445 cout <<
" H2 <-> W2, W3\n";
446 cout <<
" H3 <-> W1, W3\n\n";
448 cout <<
"Check Hall's condition:\n";
449 cout <<
" |{H1}| = 1 <= |{W1, W2}| = 2 OK\n";
450 cout <<
" |{H2}| = 1 <= |{W2, W3}| = 2 OK\n";
451 cout <<
" |{H3}| = 1 <= |{W1, W3}| = 2 OK\n";
452 cout <<
" |{H1, H2}| = 2 <= |{W1, W2, W3}| = 3 OK\n";
453 cout <<
" |{H1, H3}| = 2 <= |{W1, W2, W3}| = 3 OK\n";
454 cout <<
" |{H2, H3}| = 2 <= |{W1, W2, W3}| = 3 OK\n";
455 cout <<
" |{H1, H2, H3}| = 3 <= |{W1, W2, W3}| = 3 OK\n\n";
457 cout <<
"Hall's condition SATISFIED => Perfect matching exists:\n";
458 cout <<
" H1 -- W2\n";
459 cout <<
" H2 -- W3\n";
460 cout <<
" H3 -- W1\n";
465 cout <<
"Graph: 3 A's but only 2 B's as neighbors\n";
466 cout <<
" A1, A2, A3 all <-> B1, B2 only (not B3)\n\n";
468 cout <<
"Check Hall's condition:\n";
469 cout <<
" |{A1, A2, A3}| = 3 but |N({A1, A2, A3})| = |{B1, B2}| = 2\n";
470 cout <<
" 3 > 2 => VIOLATED!\n\n";
472 cout <<
"Hall's condition VIOLATED => NO perfect matching!\n";
473 cout <<
"Maximum matching size = 2 (one A left unmatched)\n";
508 "Bipartite graph example for Aleph-w.\n"
509 "Demonstrates bipartition and maximum matching.",
515 "Run only specific section: def, test, match, dating, hall, or 'all'",
516 false,
"all",
"section",
cmd
524 cout <<
"============================================================\n";
525 cout <<
" ALEPH-W BIPARTITE GRAPHS EXAMPLE\n";
526 cout <<
"============================================================\n";
543 cout <<
"\n" << string(60,
'=') <<
"\n";
544 cout <<
"Bipartite graphs demo completed!\n";
545 cout << string(60,
'=') <<
"\n\n";
549 catch (TCLAP::ArgException& e)
551 cerr <<
"Error: " << e.error() <<
" for argument " << e.argId() <<
endl;
556 cerr <<
"Error: " << e.what() <<
endl;
WeightedDigraph::Node Node
void print_subsection(const string &title)
void print_section(const string &title)
void demo_halls_theorem()
void print_partition(const string &label, DynDlist< Graph::Node * > &nodes)
void print_matching(Graph &g, DynDlist< Graph::Arc * > &matching)
Dynamic doubly linked list with O(1) size and bidirectional access.
size_t size() const noexcept
Count the number of elements of the list.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
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)
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
DynArray< Graph::Node * > nodes
void compute_bipartite(const GT &g, DynDlist< typename GT::Node * > &l, DynDlist< typename GT::Node * > &r)
Computes the partition sets of a bipartite graph.
Main namespace for Aleph-w library functions.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Arc of graph implemented with double-linked adjacency lists.
Node belonging to a graph implemented with a double linked adjacency list.
Bipartite graph detection and 2-coloring.
Generic graph and digraph implementations.