144 seed =
static_cast<unsigned>(
145 std::chrono::system_clock::now().time_since_epoch().count());
148 std::uniform_real_distribution<double>
cap_dist(
params.min_capacity,
150 std::uniform_int_distribution<size_t>
node_dist(0,
params.num_nodes - 1);
154 for (
size_t i = 0; i <
params.num_nodes; ++i)
162 if (
params.ensure_connected)
164 for (
size_t i = 0; i <
params.num_nodes - 1; ++i)
173 if (
params.ensure_connected)
184 tgt = (tgt + 1) %
params.num_nodes;
208 double min_cap = 1.0,
double max_cap = 100.0,
213 params.num_arcs = num_arcs;
215 params.max_capacity = max_cap;
251 std::vector<std::vector<Node*>>
nodes(rows, std::vector<Node*>(cols));
254 for (
size_t i = 0; i < rows; ++i)
255 for (
size_t j = 0; j < cols; ++j)
259 for (
size_t i = 0; i < rows; ++i)
260 for (
size_t j = 0; j < cols - 1; ++j)
268 for (
size_t i = 0; i < rows - 1; ++i)
269 for (
size_t j = 0; j < cols; ++j)
311 seed =
static_cast<unsigned>(
312 std::chrono::system_clock::now().time_since_epoch().count());
315 std::uniform_real_distribution<double> prob_dist(0.0, 1.0);
323 for (
size_t i = 0; i < left_size; ++i)
331 for (
size_t i = 0; i < right_size; ++i)
338 for (
size_t i = 0; i < left_size; ++i)
339 for (
size_t j = 0; j < right_size; ++j)
377 <<
"Intermediate layers must be non-empty";
381 seed =
static_cast<unsigned>(
382 std::chrono::system_clock::now().time_since_epoch().count());
385 std::uniform_real_distribution<double> prob_dist(0.0, 1.0);
404 for (
size_t i = 0; i <
layers[
l].size(); ++i)
406 bool connected =
false;
407 for (
size_t j = 0; j <
layers[
l+1].size(); ++j)
427 for (
size_t j = 0; j <
layers[
l+1].size(); ++j)
489 std::ofstream
out(filename);
499 out <<
"digraph " <<
options.graph_name <<
" {\n";
500 out <<
" rankdir=LR;\n";
501 out <<
" node [shape=circle];\n";
506 Node* p = it.get_curr();
516 out <<
" [style=filled, fillcolor=" <<
color <<
"]";
524 auto arc = it.get_curr();
531 std::ostringstream label;
548 if (
options.highlight_saturated
and arc->flow == arc->cap)
550 else if (
options.highlight_empty
and arc->flow == 0)
555 if (
not label.str().empty())
556 out <<
"label=" << label.str();
559 if (
not label.str().empty())
584 std::ostringstream
out;
592 out <<
"digraph " <<
options.graph_name <<
" {\n";
593 out <<
" rankdir=LR;\n";
594 out <<
" node [shape=circle];\n";
599 Node* p = it.get_curr();
609 out <<
" [style=filled, fillcolor=" <<
color <<
"]";
617 auto arc = it.get_curr();
623 std::ostringstream label;
639 if (
options.highlight_saturated
and arc->flow == arc->cap)
641 else if (
options.highlight_empty
and arc->flow == 0)
646 if (
not label.str().empty())
647 out <<
"label=" << label.str();
650 if (
not label.str().empty())
698 std::ofstream
out(filename);
711 out <<
" \"num_nodes\": " << net.
vsize() <<
",\n";
712 out <<
" \"num_arcs\": " << net.
esize() <<
",\n";
721 out <<
" \"arcs\": [\n";
729 auto arc = it.get_curr();
733 <<
"\"cap\": " << arc->cap <<
", "
734 <<
"\"flow\": " << arc->flow
754 std::ostringstream
out;
763 out <<
" \"num_nodes\": " << net.
vsize() <<
",\n";
764 out <<
" \"num_arcs\": " << net.
esize() <<
",\n";
771 out <<
" \"arcs\": [\n";
779 auto arc = it.get_curr();
783 <<
"\"cap\": " << arc->cap <<
", "
784 <<
"\"flow\": " << arc->flow
824 std::ofstream
out(filename);
835 out <<
"c Network exported from Aleph-w\n";
836 out <<
"p max " << net.
vsize() <<
" " << net.
esize() <<
"\n";
847 auto arc = it.get_curr();
850 <<
static_cast<long long>(arc->cap) <<
"\n";
871 std::ifstream
in(filename);
873 throw std::runtime_error(
"Cannot open file: " + filename);
875 std::vector<Node*>
nodes;
879 while (std::getline(
in, line))
881 if (line.empty()
or line[0] ==
'c')
884 std::istringstream
iss(line);
895 for (
size_t i = 1; i <= n; ++i)
898 else if (type ==
'n')
909 else if (type ==
'a')
913 iss >> src >> tgt >> cap;
936template <
typename Flow_Type>
955template <
class Net,
class Algo>
962 auto start = std::chrono::high_resolution_clock::now();
964 auto end = std::chrono::high_resolution_clock::now();
966 result.
elapsed_ms = std::chrono::duration<double, std::milli>(
967 end - start).count();
975template <
typename Flow_Type>
979 std::cout <<
"\n=== Max-Flow Algorithm Benchmark ===\n";
980 std::cout << std::left << std::setw(25) <<
"Algorithm"
981 << std::setw(15) <<
"Flow"
982 << std::setw(15) <<
"Time (ms)" <<
"\n";
983 std::cout << std::string(55,
'-') <<
"\n";
987 << std::setw(15) <<
r.flow_value
988 << std::setw(15) << std::fixed << std::setprecision(3)
989 <<
r.elapsed_ms <<
"\n";
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
WeightedDigraph::Node Node
Generic key-value map implemented on top of a binary search tree.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
size_t size() const noexcept
Count the number of elements of the list.
Filtered iterator on the nodes of a graph.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
constexpr size_t vsize() const noexcept
size_t esize() const noexcept
Return the total of arcs of graph.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
size_t resize(size_t new_size)
Resizes the hash table to a new capacity.
DynArray< Graph::Node * > nodes
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Net import_network_from_dimacs(const std::string &filename)
Import network from DIMACS max-flow format.
void export_network_to_dimacs(const Net &net, const std::string &filename)
Export network to DIMACS max-flow format.
size_t size(Node *root) noexcept
void export_network_to_dot(const Net &net, const std::string &filename, const DotExportOptions &options=DotExportOptions())
Export network to DOT format for GraphViz visualization.
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 generate_random_network(const NetworkGenParams ¶ms)
Generate a random flow network.
Net generate_bipartite_network(size_t left_size, size_t right_size, double edge_prob=0.5, unsigned seed=0)
Generate a bipartite network for matching.
void export_network_to_json(const Net &net, const std::string &filename)
Export network to JSON format.
std::string network_to_json_string(const Net &net)
Export network to JSON string.
MaxFlowBenchmarkResult< typename Net::Flow_Type > benchmark_maxflow(Net &net, Algo algo, const std::string &name)
Run and time a max-flow algorithm.
Net generate_grid_network(size_t rows, size_t cols, typename Net::Flow_Type capacity, bool bidirectional=true)
Generate a grid network.
void print_benchmark_results(const std::vector< MaxFlowBenchmarkResult< Flow_Type > > &results)
Print benchmark results.
std::string network_to_dot_string(const Net &net, const DotExportOptions &options=DotExportOptions())
Generate DOT string for network (instead of file).
Net generate_layered_network(const std::vector< size_t > &layer_sizes, typename Net::Flow_Type capacity, double edge_prob=0.5, unsigned seed=0)
Generate a layered network.
static long & color(typename GT::Node *p)
static struct argp_option options[]
Filtered iterator on all the arcs of a graph.
bool highlight_saturated
Highlight saturated arcs.
bool use_colors
Use colors for flow visualization.
bool show_capacity
Show capacity values on arcs.
bool show_flow
Show flow values on arcs.
bool highlight_empty
Highlight empty arcs.
std::string saturated_color
bool show_cost
Show cost values (for cost networks)
Result of running a max-flow algorithm.
std::string algorithm_name
Flow network implemented with adjacency lists.
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
constexpr bool is_single_source() const noexcept
Return true if the network has a single source.
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.
Node * get_sink() const
Return an arbitrary sink node.
typename Arc::Flow_Type Flow_Type
Capacity/flow numeric type.
constexpr bool is_single_sink() const noexcept
Return true if the network has a single sink.
Parameters for random network generation.
double max_capacity
Maximum arc capacity.
size_t num_arcs
Target number of arcs.
bool ensure_connected
Ensure source can reach sink.
double min_cost
Minimum arc cost (for cost networks)
double min_capacity
Minimum arc capacity.
unsigned seed
Random seed (0 = use time)
double max_cost
Maximum arc cost.
size_t num_nodes
Number of nodes.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic key-value map based on balanced binary search trees.
Network flow graph structures.
Maximum flow minimum cost network algorithms.