Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
min_cut_example.cc
Go to the documentation of this file.
1
49#include <iostream>
50#include <iomanip>
51#include <string>
52#include <vector>
53#include <cmath>
54#include <limits>
55
56#include <Karger_Stein.H>
57#include <Stoer_Wagner.H>
58#include <tpl_graph.H>
59
60using namespace std;
61using namespace Aleph;
62
63// ============================================================================
64// Helper: Print partition
65// ============================================================================
66template <typename GT>
67void print_partition(const string& name,
69{
70 cout << " " << name << ": { ";
71 bool first = true;
72 for (auto node : partition)
73 {
74 if (!first) cout << ", ";
75 cout << node->get_info();
76 first = false;
77 }
78 cout << " }\n";
79}
80
81// ============================================================================
82// Helper: Print cut edges
83// ============================================================================
84template <typename GT>
86{
87 cout << " Cut edges:\n";
88 for (auto arc : cut)
89 {
90 cout << " " << g.get_src_node(arc)->get_info()
91 << " --(" << arc->get_info() << ")-- "
92 << g.get_tgt_node(arc)->get_info() << "\n";
93 }
94}
95
96// ============================================================================
97// EXAMPLE 1: Network Reliability Analysis
98// ============================================================================
99// Use case: Find the weakest point in a network topology
100// Real-world: Data center, power grid, social network analysis
101// ============================================================================
102
104{
105 cout << "╔════════════════════════════════════════════════════════════════╗\n";
106 cout << "║ EXAMPLE 1: Network Reliability Analysis ║\n";
107 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
108
109 cout << "SCENARIO: A company has 6 offices connected by network links.\n";
110 cout << " We need to find the minimum number of links that,\n";
111 cout << " if cut, would split the network into two parts.\n\n";
112
114 GT network;
115
116 // Create offices
117 cout << "STEP 1: Building network topology\n";
118 cout << " Offices: HQ, Branch1, Branch2, Branch3, Remote1, Remote2\n\n";
119
120 auto hq = network.insert_node("HQ");
121 auto branch1 = network.insert_node("Branch1");
122 auto branch2 = network.insert_node("Branch2");
123 auto branch3 = network.insert_node("Branch3");
124 auto remote1 = network.insert_node("Remote1");
125 auto remote2 = network.insert_node("Remote2");
126
127 // HQ is well-connected (hub topology)
128 network.insert_arc(hq, branch1, 1); network.insert_arc(branch1, hq, 1);
129 network.insert_arc(hq, branch2, 1); network.insert_arc(branch2, hq, 1);
130 network.insert_arc(hq, branch3, 1); network.insert_arc(branch3, hq, 1);
131
132 // Branches have some redundancy
133 network.insert_arc(branch1, branch2, 1); network.insert_arc(branch2, branch1, 1);
134 network.insert_arc(branch2, branch3, 1); network.insert_arc(branch3, branch2, 1);
135
136 // Remote offices only connected to one branch each (vulnerability!)
137 network.insert_arc(branch1, remote1, 1); network.insert_arc(remote1, branch1, 1);
138 network.insert_arc(branch3, remote2, 1); network.insert_arc(remote2, branch3, 1);
139
140 cout << " Network structure:\n";
141 cout << " Remote1\n";
142 cout << " |\n";
143 cout << " Branch1--+--HQ--Branch3--Remote2\n";
144 cout << " | |\n";
145 cout << " Branch2-------+\n\n";
146
147 cout << " Total: " << network.get_num_nodes() << " offices, "
148 << network.get_num_arcs() / 2 << " unique links\n\n";
149
150 // Find min-cut using Karger-Stein
151 cout << "STEP 2: Finding minimum cut with Karger-Stein\n";
152 cout << " (Running 20 iterations for accuracy)\n\n";
153
157
158 size_t min_cut = ks(network, S, T, cut, 20);
159
160 cout << "RESULT:\n";
161 cout << " Minimum cut size: " << min_cut / 2 << " links\n"; // Divide by 2 for undirected
162 print_partition<GT>("Partition 1", S);
163 print_partition<GT>("Partition 2", T);
164
165 cout << "\nINTERPRETATION:\n";
166 cout << " The network can be split by cutting just " << min_cut / 2 << " link(s).\n";
167 cout << " RECOMMENDATION: Add redundant links to vulnerable offices.\n\n";
168}
169
170// ============================================================================
171// EXAMPLE 2: Weighted Network - Bandwidth Optimization
172// ============================================================================
173// Use case: Find the bottleneck in a network with different link capacities
174// Real-world: Network capacity planning, traffic analysis
175// ============================================================================
176
178{
179 cout << "╔════════════════════════════════════════════════════════════════╗\n";
180 cout << "║ EXAMPLE 2: Weighted Network - Bandwidth Analysis ║\n";
181 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
182
183 cout << "SCENARIO: A data center has servers connected with varying bandwidth.\n";
184 cout << " Find the minimum total bandwidth that could bottleneck.\n\n";
185
188
189 // Create servers
190 auto web1 = datacenter.insert_node("Web1");
191 auto web2 = datacenter.insert_node("Web2");
192 auto app = datacenter.insert_node("App");
193 auto db = datacenter.insert_node("Database");
194 auto cache = datacenter.insert_node("Cache");
195
196 cout << "STEP 1: Network topology with bandwidth (Gbps)\n\n";
197
198 // High bandwidth core connections
199 datacenter.insert_arc(web1, app, 10); datacenter.insert_arc(app, web1, 10);
200 datacenter.insert_arc(web2, app, 10); datacenter.insert_arc(app, web2, 10);
201 datacenter.insert_arc(app, cache, 20); datacenter.insert_arc(cache, app, 20);
202 datacenter.insert_arc(cache, db, 5); datacenter.insert_arc(db, cache, 5); // Bottleneck!
203 datacenter.insert_arc(app, db, 2); datacenter.insert_arc(db, app, 2); // Backup link
204
205 cout << " Web1 --10-- App --20-- Cache --5-- Database\n";
206 cout << " Web2 --10-- | |\n";
207 cout << " +-------2---------+\n\n";
208
209 // Find min-cut using Stoer-Wagner (handles weights properly)
210 cout << "STEP 2: Finding minimum cut with Stoer-Wagner\n\n";
211
215
216 int min_bandwidth = sw(datacenter, S, T, cut);
217
218 cout << "RESULT:\n";
219 cout << " Minimum cut bandwidth: " << min_bandwidth / 2 << " Gbps\n";
220 print_partition<GT>("Partition 1", S);
221 print_partition<GT>("Partition 2", T);
222 cout << "\n Bottleneck links:\n";
223 for (auto arc : cut)
224 {
225 cout << " " << datacenter.get_src_node(arc)->get_info()
226 << " <-> " << datacenter.get_tgt_node(arc)->get_info()
227 << " (" << arc->get_info() << " Gbps)\n";
228 }
229
230 cout << "\nINTERPRETATION:\n";
231 cout << " The database access is the bottleneck at " << min_bandwidth / 2 << " Gbps.\n";
232 cout << " RECOMMENDATION: Upgrade Cache-Database link or add more paths.\n\n";
233}
234
235// ============================================================================
236// EXAMPLE 3: Community Detection
237// ============================================================================
238// Use case: Find natural divisions in a social network
239// Real-world: Social media analysis, market segmentation
240// ============================================================================
241
243{
244 cout << "╔════════════════════════════════════════════════════════════════╗\n";
245 cout << "║ EXAMPLE 3: Community Detection in Social Network ║\n";
246 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
247
248 cout << "SCENARIO: A social network with two friend groups loosely connected.\n";
249 cout << " Find the natural division between communities.\n\n";
250
252 GT social;
253
254 // Group 1: Tech enthusiasts
255 auto alice = social.insert_node("Alice");
256 auto bob = social.insert_node("Bob");
257 auto carol = social.insert_node("Carol");
258
259 // Group 2: Sports fans
260 auto dave = social.insert_node("Dave");
261 auto eve = social.insert_node("Eve");
262 auto frank = social.insert_node("Frank");
263
264 cout << "STEP 1: Building social connections\n\n";
265
266 // Dense connections within Group 1
267 social.insert_arc(alice, bob, 1); social.insert_arc(bob, alice, 1);
268 social.insert_arc(alice, carol, 1); social.insert_arc(carol, alice, 1);
269 social.insert_arc(bob, carol, 1); social.insert_arc(carol, bob, 1);
270
271 // Dense connections within Group 2
272 social.insert_arc(dave, eve, 1); social.insert_arc(eve, dave, 1);
273 social.insert_arc(dave, frank, 1); social.insert_arc(frank, dave, 1);
274 social.insert_arc(eve, frank, 1); social.insert_arc(frank, eve, 1);
275
276 // Sparse connections between groups (just 1 link)
277 social.insert_arc(carol, dave, 1); social.insert_arc(dave, carol, 1);
278
279 cout << " Group 1 (Tech): Group 2 (Sports):\n";
280 cout << " Alice--Bob Dave--Eve\n";
281 cout << " \\ / \\ /\n";
282 cout << " Carol ---- Dave Frank\n";
283 cout << " (weak link)\n\n";
284
285 // Run both algorithms and compare
286 cout << "STEP 2: Running both algorithms\n\n";
287
288 // Karger-Stein
292 size_t ks_result = ks(social, ks_S, ks_T, ks_cut, 30);
293
294 // Stoer-Wagner
298 int sw_result = sw(social, sw_S, sw_T, sw_cut);
299
300 cout << "KARGER-STEIN RESULT:\n";
301 cout << " Min-cut size: " << ks_result / 2 << "\n";
302 print_partition<GT>("Community 1", ks_S);
303 print_partition<GT>("Community 2", ks_T);
304
305 cout << "\nSTOER-WAGNER RESULT:\n";
306 cout << " Min-cut size: " << sw_result / 2 << "\n";
307 print_partition<GT>("Community 1", sw_S);
308 print_partition<GT>("Community 2", sw_T);
309
310 cout << "\nINTERPRETATION:\n";
311 cout << " Both algorithms identify the two communities correctly.\n";
312 cout << " The Carol-Dave connection is the bridge between groups.\n\n";
313}
314
315// ============================================================================
316// EXAMPLE 4: Algorithm Comparison - Accuracy vs Speed
317// ============================================================================
318
320{
321 cout << "╔════════════════════════════════════════════════════════════════╗\n";
322 cout << "║ EXAMPLE 4: Algorithm Comparison ║\n";
323 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
324
325 cout << "SCENARIO: Compare Karger-Stein vs Stoer-Wagner on the same graph.\n\n";
326
328 GT g;
329
330 // Build two 5-cliques connected by 3 edges
331 const int CLIQUE_SIZE = 5;
332 const int BRIDGE_COUNT = 3;
333
335
336 for (int i = 0; i < CLIQUE_SIZE; ++i)
337 {
338 left[i] = g.insert_node(i);
339 right[i] = g.insert_node(CLIQUE_SIZE + i);
340 }
341
342 // Left clique
343 for (int i = 0; i < CLIQUE_SIZE; ++i)
344 for (int j = i + 1; j < CLIQUE_SIZE; ++j)
345 {
346 g.insert_arc(left[i], left[j], 1);
347 g.insert_arc(left[j], left[i], 1);
348 }
349
350 // Right clique
351 for (int i = 0; i < CLIQUE_SIZE; ++i)
352 for (int j = i + 1; j < CLIQUE_SIZE; ++j)
353 {
354 g.insert_arc(right[i], right[j], 1);
355 g.insert_arc(right[j], right[i], 1);
356 }
357
358 // Bridges
359 for (int i = 0; i < BRIDGE_COUNT; ++i)
360 {
361 g.insert_arc(left[i], right[i], 1);
362 g.insert_arc(right[i], left[i], 1);
363 }
364
365 cout << "GRAPH: Two K" << CLIQUE_SIZE << " cliques connected by "
366 << BRIDGE_COUNT << " edges\n";
367 cout << " Expected min-cut: " << BRIDGE_COUNT << "\n";
368 cout << " Nodes: " << g.get_num_nodes() << ", Edges: "
369 << g.get_num_arcs() / 2 << "\n\n";
370
371 // Run Karger-Stein with varying iterations
372 cout << "KARGER-STEIN (varying iterations):\n";
374
375 for (int iters : {1, 5, 10, 20, 50})
376 {
379 size_t result = ks(g, S, T, cut, iters);
380 cout << " " << setw(2) << iters << " iterations: min-cut = "
381 << result / 2 << "\n";
382 }
383
384 // Run Stoer-Wagner
385 cout << "\nSTOER-WAGNER (deterministic):\n";
389 int result = sw(g, S, T, cut);
390 cout << " Result: min-cut = " << result / 2 << "\n";
391
392 cout << "\nCONCLUSION:\n";
393 cout << " - Karger-Stein converges to correct answer with more iterations\n";
394 cout << " - Stoer-Wagner always gives exact answer in one run\n";
395 cout << " - Choose based on: graph size, accuracy needs, weighted/unweighted\n\n";
396}
397
398// ============================================================================
399// EXAMPLE 5: Practical API Usage Patterns
400// ============================================================================
401
403{
404 cout << "╔════════════════════════════════════════════════════════════════╗\n";
405 cout << "║ EXAMPLE 5: API Usage Patterns ║\n";
406 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
407
409 GT g;
410
411 auto a = g.insert_node("A");
412 auto b = g.insert_node("B");
413 auto c = g.insert_node("C");
414 auto d = g.insert_node("D");
415
416 g.insert_arc(a, b, 1); g.insert_arc(b, a, 1);
417 g.insert_arc(b, c, 1); g.insert_arc(c, b, 1);
418 g.insert_arc(c, d, 1); g.insert_arc(d, c, 1);
419 g.insert_arc(a, d, 1); g.insert_arc(d, a, 1);
420
421 cout << "PATTERN 1: Basic single-run (Karger-Stein)\n";
422 cout << "-------------------------------------------\n";
423 cout << R"(
424 Karger_Stein_Min_Cut<GT> ks;
425 DynList<GT::Node*> S, T;
426 DynList<GT::Arc*> cut;
427 size_t result = ks(g, S, T, cut);
428)";
429
430 {
434 size_t result = ks(g, S, T, cut);
435 cout << " Result: " << result << "\n\n";
436 }
437
438 cout << "PATTERN 2: Multiple iterations for accuracy (Karger-Stein)\n";
439 cout << "-----------------------------------------------------------\n";
440 cout << R"(
441 size_t result = ks(g, S, T, cut, 20);
442)";
443
444 {
448 size_t result = ks(g, S, T, cut, 20);
449 cout << " Result: " << result << "\n\n";
450 }
451
452 cout << "PATTERN 3: Reproducible results with seed\n";
453 cout << "------------------------------------------\n";
454 cout << R"(
455 Karger_Stein_Min_Cut<GT> ks(12345); // Seed = 12345
456 // Or: ks.set_seed(12345);
457)";
458
459 {
464 size_t r1 = ks1(g, S1, T1, cut1);
465 size_t r2 = ks2(g, S2, T2, cut2);
466 cout << " Same seed → same result: " << (r1 == r2 ? "YES" : "NO") << "\n\n";
467 }
468
469 cout << "PATTERN 4: Weighted graph (Stoer-Wagner)\n";
470 cout << "-----------------------------------------\n";
471 cout << R"(
472 Stoer_Wagner_Min_Cut<GT> sw;
473 int weight = sw(g, S, T, cut); // Returns total weight of cut edges
474)";
475
476 {
480 int weight = sw(g, S, T, cut);
481 cout << " Result: " << weight << "\n\n";
482 }
483
484 cout << "PATTERN 5: Just the weight, no partition (Stoer-Wagner)\n";
485 cout << "--------------------------------------------------------\n";
486 cout << R"(
487 int weight = sw.min_cut_weight(g); // Slightly faster
488)";
489
490 {
492 int weight = sw.min_cut_weight(g);
493 cout << " Result: " << weight << "\n\n";
494 }
495
496 cout << "PATTERN 6: Unweighted graph with Stoer-Wagner\n";
497 cout << "----------------------------------------------\n";
498 cout << R"(
499 Stoer_Wagner_Min_Cut<GT, Unit_Weight<GT>> sw;
500 size_t num_edges = sw(g, S, T, cut); // Counts edges, ignores weights
501)";
502
503 {
507 size_t num_edges = sw(g, S, T, cut);
508 cout << " Result: " << num_edges << " edges\n\n";
509 }
510}
511
512// ============================================================================
513// EXAMPLE 6: When to Use Which Algorithm
514// ============================================================================
515
517{
518 cout << "╔════════════════════════════════════════════════════════════════╗\n";
519 cout << "║ EXAMPLE 6: Algorithm Selection Guide ║\n";
520 cout << "╚════════════════════════════════════════════════════════════════╝\n\n";
521
522 cout << "DECISION FLOWCHART:\n";
523 cout << "═══════════════════\n\n";
524
525 cout << " ┌─────────────────────────────────────────┐\n";
526 cout << " │ Do you need the EXACT minimum cut? │\n";
527 cout << " └────────────────┬────────────────────────┘\n";
528 cout << " │\n";
529 cout << " ┌─────────┴─────────┐\n";
530 cout << " │ │\n";
531 cout << " YES NO\n";
532 cout << " │ │\n";
533 cout << " ▼ ▼\n";
534 cout << " ┌──────────────┐ ┌──────────────────────┐\n";
535 cout << " │ STOER-WAGNER │ │ Is the graph large? │\n";
536 cout << " │ Deterministic│ │ (n > 100) │\n";
537 cout << " └──────────────┘ └──────────┬───────────┘\n";
538 cout << " │\n";
539 cout << " ┌─────────┴─────────┐\n";
540 cout << " │ │\n";
541 cout << " YES NO\n";
542 cout << " │ │\n";
543 cout << " ▼ ▼\n";
544 cout << " ┌──────────────┐ ┌──────────────┐\n";
545 cout << " │ KARGER-STEIN │ │ STOER-WAGNER │\n";
546 cout << " │ O(n² log³ n) │ │ Simple cases │\n";
547 cout << " └──────────────┘ └──────────────┘\n\n";
548
549 cout << "COMPARISON TABLE:\n";
550 cout << "═════════════════\n\n";
551
552 cout << " ┌────────────────┬───────────────────┬───────────────────┐\n";
553 cout << " │ Criterion │ Karger-Stein │ Stoer-Wagner │\n";
554 cout << " ├────────────────┼───────────────────┼───────────────────┤\n";
555 cout << " │ Time │ O(n² log³ n) │ O(nm + n² log n) │\n";
556 cout << " │ Space │ O(n + m) │ O(n²) │\n";
557 cout << " │ Deterministic? │ No (randomized) │ Yes │\n";
558 cout << " │ Weighted? │ No │ Yes │\n";
559 cout << " │ Exact? │ High probability │ Always │\n";
560 cout << " │ Large graphs │ ✓ Better │ OK │\n";
561 cout << " │ Small graphs │ OK │ ✓ Better │\n";
562 cout << " └────────────────┴───────────────────┴───────────────────┘\n\n";
563
564 cout << "PRACTICAL RECOMMENDATIONS:\n";
565 cout << "══════════════════════════\n\n";
566
567 cout << " 1. NETWORK RELIABILITY → Stoer-Wagner (exact answer matters)\n";
568 cout << " 2. BANDWIDTH ANALYSIS → Stoer-Wagner (needs weights)\n";
569 cout << " 3. COMMUNITY DETECTION → Either (approximate OK)\n";
570 cout << " 4. LARGE SOCIAL GRAPH → Karger-Stein (faster)\n";
571 cout << " 5. VLSI DESIGN → Stoer-Wagner (precision critical)\n\n";
572}
573
574// ============================================================================
575// Main
576// ============================================================================
577
578int main()
579{
580 cout << "\n";
581 cout << "████████████████████████████████████████████████████████████████████\n";
582 cout << "██ ██\n";
583 cout << "██ MINIMUM CUT ALGORITHMS - EDUCATIONAL EXAMPLES ██\n";
584 cout << "██ Karger-Stein (Randomized) & Stoer-Wagner (Deterministic) ██\n";
585 cout << "██ ██\n";
586 cout << "████████████████████████████████████████████████████████████████████\n";
587 cout << "\n";
588
595
596 cout << "════════════════════════════════════════════════════════════════════\n";
597 cout << " All examples completed successfully!\n";
598 cout << "════════════════════════════════════════════════════════════════════\n\n";
599
600 return 0;
601}
Karger-Stein randomized min-cut algorithm (alias for Karger.H fast method).
Stoer-Wagner deterministic min-cut algorithm.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
Karger's randomized minimum cut algorithm.
Definition Karger.H:158
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Stoer-Wagner deterministic minimum cut algorithm.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
void example_weighted_bandwidth()
void example_community_detection()
void print_cut_edges(GT &g, const DynList< typename GT::Arc * > &cut)
void example_algorithm_comparison()
void print_partition(const string &name, const DynList< typename GT::Node * > &partition)
void example_network_reliability()
int main()
void example_algorithm_selection()
void example_api_patterns()
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::pair< TgtContainer< typename SrcContainer::Item_Type >, TgtContainer< typename SrcContainer::Item_Type > > partition(const SrcContainer &c, std::function< bool(const typename SrcContainer::Item_Type &)> operation)
Partition a container into two based on a predicate.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
Net::Flow_Type min_cut(Net &net, DynSetTree< typename Net::Node * > &vs, DynSetTree< typename Net::Node * > &vt, DynList< typename Net::Arc * > &cuts, DynList< typename Net::Arc * > &cutt)
Compute max flow and the corresponding minimum cut.
Definition tpl_net.H:1864
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Generic graph and digraph implementations.