240using namespace Aleph;
245 <<
" [--algorithm <edmonds-karp|dinic|capacity-scaling|hlpp>]"
246 <<
" [--sparse] [--dense] [--help]\n";
247 cout <<
"\nIf no flags are given, all demos are executed.\n";
248 cout <<
"If any flags are given, the program always runs the supply chain demo\n";
249 cout <<
"(using --algorithm if provided) and the large capacities demo.\n";
250 cout <<
"The grid benchmark comparison is run when --sparse or --dense is set.\n";
255 for (
int i = 1; i <
argc; ++i)
256 if (std::strcmp(
argv[i], flag) == 0)
263 for (
int i = 1; i + 1 <
argc; ++i)
264 if (std::strcmp(
argv[i],
opt) == 0)
333 for (
int i = 0; i < rows; ++i)
334 for (
int j = 0; j < cols; ++j)
338 for (
int i = 0; i < rows; ++i)
340 for (
int j = 0; j < cols; ++j)
358template <
typename Algorithm>
362 for (
auto it = net.
get_arc_it(); it.has_curr(); it.next())
363 it.get_curr()->flow = 0;
365 auto start = chrono::high_resolution_clock::now();
367 auto end = chrono::high_resolution_clock::now();
369 double ms = chrono::duration<double, milli>(end - start).count();
384 for (
auto it = net.
get_arc_it(); it.has_curr(); it.next())
386 auto* arc = it.get_curr();
388 if (arc->flow == arc->cap && arc->cap > 0)
saturated++;
395 cout <<
"Max flow value: " << max_flow <<
endl;
407 cout <<
"\n=== Flow Decomposition ===" <<
endl;
408 cout <<
"Breaking down max-flow into individual paths:\n" <<
endl;
415 for (
auto it =
decomp.paths.
get_it(); it.has_curr(); it.next())
417 const auto&
fp = it.get_curr();
423 auto* arc =
ait.get_curr();
425 cout <<
" -> " << tgt->get_info();
440 cout <<
"\n" << string(60,
'=') <<
endl;
442 <<
" Grid Network" <<
endl;
450 cout <<
setw(20) << left <<
"Algorithm"
451 <<
setw(12) << right <<
"Flow"
458 cout <<
setw(20) << left <<
"Edmonds-Karp"
459 <<
setw(12) << right << flow
466 cout <<
setw(20) << left <<
"Ford-Fulkerson"
467 <<
setw(12) << right << flow
475 <<
setw(12) << right << flow
482 cout <<
setw(20) << left <<
"Capacity Scaling"
483 <<
setw(12) << right << flow
491 <<
setw(12) << right << flow
501 cout <<
"\n=== Min-Cut / Max-Flow Duality ===" <<
endl;
502 cout <<
"\nThe Max-Flow Min-Cut Theorem states:" <<
endl;
503 cout <<
" max_flow = min_cut_capacity" <<
endl;
506 cout <<
"\nSaturated edges (candidates for min-cut):" <<
endl;
509 for (
auto it = net.
get_arc_it(); it.has_curr(); it.next())
511 auto* arc = it.get_curr();
512 if (arc->flow == arc->cap && arc->cap > 0)
516 cout <<
" " << src->get_info() <<
" -> " << tgt->get_info()
517 <<
" (cap = " << arc->cap <<
")" <<
endl;
522 cout <<
"\nNote: Not all saturated edges are necessarily in the min-cut," <<
endl;
523 cout <<
"but the min-cut consists only of saturated edges." <<
endl;
528 cout <<
"=== Advanced Maximum Flow Algorithms ===" <<
endl;
529 cout <<
"Comparing Edmonds-Karp, Ford-Fulkerson, Dinic, Capacity Scaling, and HLPP\n" <<
endl;
547 cout <<
"Demo 1: Supply Chain Network" <<
endl;
552 cout <<
"\nNetwork structure:" <<
endl;
558 if (std::strcmp(
chosen,
"dinic") == 0)
560 cout <<
"\nComputing max-flow with Dinic's algorithm..." <<
endl;
563 else if (std::strcmp(
chosen,
"edmonds-karp") == 0)
565 cout <<
"\nComputing max-flow with Edmonds-Karp..." <<
endl;
568 else if (std::strcmp(
chosen,
"capacity-scaling") == 0)
570 cout <<
"\nComputing max-flow with Capacity Scaling..." <<
endl;
573 else if (std::strcmp(
chosen,
"hlpp") == 0)
575 cout <<
"\nComputing max-flow with HLPP..." <<
endl;
580 cout <<
"Unknown --algorithm value: " <<
chosen <<
"\n";
585 cout <<
"\n*** Maximum Flow: " << max_flow <<
" units ***" <<
endl;
601 <<
" grid network\n";
606 cout <<
"\n" << string(60,
'=') <<
endl;
607 cout <<
"Demo 3: Large Capacities (Capacity Scaling Advantage)" <<
endl;
612 cout <<
"\nNetwork with capacities around 1,000,000:" <<
endl;
614 cout <<
setw(20) << left <<
"Algorithm"
615 <<
setw(15) << right <<
"Flow"
621 cout <<
setw(20) << left <<
"Ford-Fulkerson"
628 cout <<
setw(20) << left <<
"Capacity Scaling"
633 cout <<
"\nCapacity Scaling excels with large integer capacities!" <<
endl;
636 cout <<
"\n" << string(60,
'=') <<
endl;
641Algorithm Selection Guide:
643 1. Edmonds-Karp: O(VE²)
644 - Simple, good for small/sparse graphs
645 - Polynomial in graph size
648 - Excellent all-around choice
649 - Works well on most networks
651 3. Capacity Scaling: O(VE log U)
652 - Best for large integer capacities
653 - Scales logarithmically with max capacity
656 - Push-relabel method
657 - Often fastest in practice for dense graphs
660 - Start with Dinic (good balance)
661 - Use Capacity Scaling for very large capacities
662 - Use HLPP for dense graphs if Dinic is slow
WeightedDigraph::Node Node
auto get_arc_it() const noexcept
Obtains an iterator to the arc of graph.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
constexpr size_t get_num_arcs() const noexcept
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 print_flow_stats(Net &net, const string &title)
Print network flow statistics.
pair< FlowType, double > time_algorithm(Net net)
Time a max-flow algorithm execution.
void compare_algorithms(int grid_size)
Compare all algorithms on the same network.
static void usage(const char *prog)
Net build_grid_network(int rows, int cols, FlowType base_cap=10.0)
Build a grid network for stress testing.
Net build_supply_chain()
Build a supply chain network.
static bool has_flag(int argc, char *argv[], const char *flag)
void demonstrate_flow_decomposition(Net &net)
Demonstrate flow decomposition into paths.
void demonstrate_min_cut(Net &net)
Demonstrate min-cut duality.
static const char * get_opt_value(int argc, char *argv[], const char *opt)
Main namespace for Aleph-w library functions.
Net::Flow_Type edmonds_karp_maximum_flow(Net &net)
Maximize flow using the Edmonds-Karp algorithm.
Net::Flow_Type dinic_maximum_flow(Net &net)
Compute maximum flow using Dinic's algorithm.
FlowDecomposition< Net > decompose_flow(const Net &net)
Decompose network flow into paths and cycles.
Net::Flow_Type capacity_scaling_maximum_flow(Net &net)
Compute maximum flow using capacity scaling.
Net::Flow_Type hlpp_maximum_flow(Net &net)
Compute maximum flow using Highest-Label Preflow-Push.
std::pair< First, Second > pair
Alias to std::pair kept for backwards compatibility.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Arc of a flow network implemented with adjacency lists.
Flow network implemented with adjacency lists.
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
Node * get_source() const
Return an arbitrary source node.
Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &flow, const typename Arc::Arc_Type &arc_info=Arc_Type())
Insert a capacitated arc with an initial flow.
Flow_Type flow_value() const
Return the total flow value of the network.
Advanced maximum flow algorithms.
Network flow graph structures.