240using namespace Aleph;
244 cout <<
"Usage: " <<
prog
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();
379 cout <<
"\n=== " << title <<
" ===" <<
endl;
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;
398 cout <<
"Utilization: " << fixed << setprecision(1)
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();
418 cout <<
"Path " <<
path_num++ <<
" (flow = " << fp.flow <<
"): ";
421 for (
auto ait = fp.arcs.get_it();
ait.has_curr();
ait.next())
423 auto* arc =
ait.get_curr();
425 cout <<
" -> " << tgt->get_info();
432 cout <<
"Total flow: " <<
decomp.total_flow() <<
endl;
440 cout <<
"\n" << string(60,
'=') <<
endl;
442 <<
" Grid Network" <<
endl;
443 cout << string(60,
'=') <<
endl;
450 cout << setw(20) << left <<
"Algorithm"
451 << setw(12) << right <<
"Flow"
452 << setw(15) <<
"Time (ms)" <<
endl;
453 cout << string(47,
'-') <<
endl;
458 cout << setw(20) << left <<
"Edmonds-Karp"
459 << setw(12) << right << flow
460 << setw(15) << fixed << setprecision(3) <<
time <<
endl;
466 cout << setw(20) << left <<
"Ford-Fulkerson"
467 << setw(12) << right << flow
468 << setw(15) << fixed << setprecision(3) <<
time <<
endl;
474 cout << setw(20) << left <<
"Dinic"
475 << setw(12) << right << flow
476 << setw(15) << fixed << setprecision(3) <<
time <<
endl;
482 cout << setw(20) << left <<
"Capacity Scaling"
483 << setw(12) << right << flow
484 << setw(15) << fixed << setprecision(3) <<
time <<
endl;
490 cout << setw(20) << left <<
"HLPP"
491 << setw(12) << right << flow
492 << setw(15) << fixed << setprecision(3) <<
time <<
endl;
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;
546 cout << string(60,
'=') <<
endl;
547 cout <<
"Demo 1: Supply Chain Network" <<
endl;
548 cout << string(60,
'=') <<
endl;
552 cout <<
"\nNetwork structure:" <<
endl;
553 cout <<
" Nodes: " <<
supply.get_num_nodes() <<
endl;
554 cout <<
" Arcs: " <<
supply.get_num_arcs() <<
endl;
557 const char* chosen =
algo ?
algo :
"dinic";
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;
600 cout <<
"\nBenchmarking on " <<
grid <<
"x" <<
grid
601 <<
" grid network\n";
606 cout <<
"\n" << string(60,
'=') <<
endl;
607 cout <<
"Demo 3: Large Capacities (Capacity Scaling Advantage)" <<
endl;
608 cout << string(60,
'=') <<
endl;
612 cout <<
"\nNetwork with capacities around 1,000,000:" <<
endl;
614 cout << setw(20) << left <<
"Algorithm"
615 << setw(15) << right <<
"Flow"
616 << setw(15) <<
"Time (ms)" <<
endl;
617 cout << string(50,
'-') <<
endl;
621 cout << setw(20) << left <<
"Ford-Fulkerson"
622 << setw(15) << right << fixed << setprecision(0) << flow
623 << setw(15) << setprecision(3) <<
time <<
endl;
628 cout << setw(20) << left <<
"Capacity Scaling"
629 << setw(15) << right << fixed << setprecision(0) << flow
630 << setw(15) << setprecision(3) <<
time <<
endl;
633 cout <<
"\nCapacity Scaling excels with large integer capacities!" <<
endl;
636 cout <<
"\n" << string(60,
'=') <<
endl;
637 cout <<
"Summary" <<
endl;
638 cout << 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)
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.
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.
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.
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.
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.