Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
net_utils.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
78#ifndef NET_UTILS_H
79#define NET_UTILS_H
80
81#include <fstream>
82#include <sstream>
83#include <random>
84#include <chrono>
85#include <iomanip>
86#include <tpl_net.H>
87#include <tpl_netcost.H>
88#include <tpl_dynMapTree.H>
89
90namespace Aleph
91{
92
93//==============================================================================
94// NETWORK GENERATORS
95//==============================================================================
96
101{
102 size_t num_nodes = 10;
103 size_t num_arcs = 20;
104 double min_capacity = 1.0;
105 double max_capacity = 100.0;
106 double min_cost = 0.0;
107 double max_cost = 10.0;
108 bool ensure_connected = true;
109 unsigned seed = 0;
110};
111
133template <class Net>
135{
136 using Node = typename Net::Node;
137 using Flow_Type = typename Net::Flow_Type;
138
139 Net net;
140
141 // Initialize RNG
142 unsigned seed = params.seed;
143 if (seed == 0)
144 seed = static_cast<unsigned>(
145 std::chrono::system_clock::now().time_since_epoch().count());
146
147 std::mt19937 gen(seed);
148 std::uniform_real_distribution<double> cap_dist(params.min_capacity,
149 params.max_capacity);
150 std::uniform_int_distribution<size_t> node_dist(0, params.num_nodes - 1);
151
152 // Create nodes
153 std::vector<Node*> nodes(params.num_nodes);
154 for (size_t i = 0; i < params.num_nodes; ++i)
155 nodes[i] = net.insert_node();
156
157 // Set source and sink
158 // Sources and sinks are detected automatically by Net_Graph
159 // based on which nodes have no incoming/outgoing arcs
160
161 // Ensure connectivity: create a path from source to sink
162 if (params.ensure_connected)
163 {
164 for (size_t i = 0; i < params.num_nodes - 1; ++i)
165 {
166 Flow_Type cap = static_cast<Flow_Type>(cap_dist(gen));
167 net.insert_arc(nodes[i], nodes[i + 1], cap);
168 }
169 }
170
171 // Add random arcs
172 size_t arcs_to_add = params.num_arcs;
173 if (params.ensure_connected)
174 arcs_to_add -= (params.num_nodes - 1);
175
176 for (size_t i = 0; i < arcs_to_add; ++i)
177 {
178 size_t src = node_dist(gen);
179 size_t tgt = node_dist(gen);
180
181 // Avoid self-loops
182 if (src == tgt)
183 {
184 tgt = (tgt + 1) % params.num_nodes;
185 }
186
187 Flow_Type cap = static_cast<Flow_Type>(cap_dist(gen));
188 net.insert_arc(nodes[src], nodes[tgt], cap);
189 }
190
191 return net;
192}
193
206template <class Net>
207Net generate_random_network(size_t num_nodes, size_t num_arcs,
208 double min_cap = 1.0, double max_cap = 100.0,
209 unsigned seed = 0)
210{
213 params.num_arcs = num_arcs;
214 params.min_capacity = min_cap;
215 params.max_capacity = max_cap;
216 params.seed = seed;
218}
219
243template <class Net>
244Net generate_grid_network(size_t rows, size_t cols,
245 typename Net::Flow_Type capacity,
246 bool bidirectional = true)
247{
248 using Node = typename Net::Node;
249
250 Net net;
251 std::vector<std::vector<Node*>> nodes(rows, std::vector<Node*>(cols));
252
253 // Create nodes
254 for (size_t i = 0; i < rows; ++i)
255 for (size_t j = 0; j < cols; ++j)
256 nodes[i][j] = net.insert_node();
257
258 // Create horizontal arcs
259 for (size_t i = 0; i < rows; ++i)
260 for (size_t j = 0; j < cols - 1; ++j)
261 {
262 net.insert_arc(nodes[i][j], nodes[i][j+1], capacity);
263 if (bidirectional)
264 net.insert_arc(nodes[i][j+1], nodes[i][j], capacity);
265 }
266
267 // Create vertical arcs
268 for (size_t i = 0; i < rows - 1; ++i)
269 for (size_t j = 0; j < cols; ++j)
270 {
271 net.insert_arc(nodes[i][j], nodes[i+1][j], capacity);
272 if (bidirectional)
273 net.insert_arc(nodes[i+1][j], nodes[i][j], capacity);
274 }
275
276 // Source (top-left) and sink (bottom-right) are detected automatically
277 // since nodes[0][0] has no incoming arcs and nodes[rows-1][cols-1] has no outgoing arcs
278
279 return net;
280}
281
300template <class Net>
301Net generate_bipartite_network(size_t left_size, size_t right_size,
302 double edge_prob = 0.5,
303 unsigned seed = 0)
304{
305 using Node = typename Net::Node;
306 using Flow_Type = typename Net::Flow_Type;
307
308 Net net;
309
310 if (seed == 0)
311 seed = static_cast<unsigned>(
312 std::chrono::system_clock::now().time_since_epoch().count());
313
314 std::mt19937 gen(seed);
315 std::uniform_real_distribution<double> prob_dist(0.0, 1.0);
316
317 // Create source and sink
318 Node* source = net.insert_node();
319 Node* sink = net.insert_node();
320
321 // Create left nodes
322 std::vector<Node*> left_nodes(left_size);
323 for (size_t i = 0; i < left_size; ++i)
324 {
325 left_nodes[i] = net.insert_node();
326 net.insert_arc(source, left_nodes[i], Flow_Type{1});
327 }
328
329 // Create right nodes
330 std::vector<Node*> right_nodes(right_size);
331 for (size_t i = 0; i < right_size; ++i)
332 {
333 right_nodes[i] = net.insert_node();
334 net.insert_arc(right_nodes[i], sink, Flow_Type{1});
335 }
336
337 // Create random edges between left and right
338 for (size_t i = 0; i < left_size; ++i)
339 for (size_t j = 0; j < right_size; ++j)
340 if (prob_dist(gen) < edge_prob)
342
343 // Source and sink are detected automatically
344
345 return net;
346}
347
362template <class Net>
363Net generate_layered_network(const std::vector<size_t>& layer_sizes,
364 typename Net::Flow_Type capacity,
365 double edge_prob = 0.5,
366 unsigned seed = 0)
367{
368 using Node = typename Net::Node;
369
370 Net net;
371
372 if (layer_sizes.size() < 2)
373 return net;
374
375 for (size_t l = 1; l + 1 < layer_sizes.size(); ++l)
377 << "Intermediate layers must be non-empty";
378
379
380 if (seed == 0)
381 seed = static_cast<unsigned>(
382 std::chrono::system_clock::now().time_since_epoch().count());
383
384 std::mt19937 gen(seed);
385 std::uniform_real_distribution<double> prob_dist(0.0, 1.0);
386
387 // Create nodes for each layer
388 std::vector<std::vector<Node*>> layers(layer_sizes.size());
389 for (size_t l = 0; l < layer_sizes.size(); ++l)
390 {
391 layers[l].resize(layer_sizes[l]);
392 for (size_t i = 0; i < layer_sizes[l]; ++i)
393 layers[l][i] = net.insert_node();
394 }
395
396 // Connect adjacent layers
397 for (size_t l = 0; l < layer_sizes.size() - 1; ++l)
398 {
399 // Track which nodes in layer l+1 received at least one incoming arc
400 // so we can guarantee no intermediate node has in-degree 0 (which
401 // would make it an extra source and break is_single_source()).
402 std::vector<bool> reached(layers[l+1].size(), false);
403
404 for (size_t i = 0; i < layers[l].size(); ++i)
405 {
406 bool connected = false;
407 for (size_t j = 0; j < layers[l+1].size(); ++j)
408 if (prob_dist(gen) < edge_prob)
409 {
410 net.insert_arc(layers[l][i], layers[l+1][j], capacity);
411 connected = true;
412 reached[j] = true;
413 }
414
415 // Ensure every node in layer l has at least one outgoing arc
416 if (not connected and not layers[l+1].empty())
417 {
418 size_t j = gen() % layers[l+1].size();
419 net.insert_arc(layers[l][i], layers[l+1][j], capacity);
420 reached[j] = true;
421 }
422 }
423
424 // Ensure every node in layer l+1 has at least one incoming arc;
425 // otherwise it would be an extra source and fail is_single_source().
426 if (not layers[l].empty())
427 for (size_t j = 0; j < layers[l+1].size(); ++j)
428 if (not reached[j])
429 {
430 size_t i = gen() % layers[l].size();
431 net.insert_arc(layers[l][i], layers[l+1][j], capacity);
432 }
433 }
434
435 // Source and sink are detected automatically
436
437 return net;
438}
439
440
441//==============================================================================
442// DOT/GRAPHVIZ EXPORT
443//==============================================================================
444
449{
450 bool show_flow = true;
451 bool show_capacity = true;
452 bool show_cost = false;
454 bool highlight_empty = false;
455 bool use_colors = true;
456 std::string graph_name = "Network";
457 std::string source_color = "green";
458 std::string sink_color = "red";
459 std::string saturated_color = "blue";
460 std::string empty_color = "gray";
461};
462
483template <class Net>
484void export_network_to_dot(const Net& net, const std::string& filename,
486{
487 using Node = typename Net::Node;
488
489 std::ofstream out(filename);
490 if (not out)
491 return;
492
493 // Build node ID map
495 size_t id = 0;
496 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
497 node_ids[it.get_curr()] = id++;
498
499 out << "digraph " << options.graph_name << " {\n";
500 out << " rankdir=LR;\n";
501 out << " node [shape=circle];\n";
502
503 // Export nodes
504 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
505 {
506 Node* p = it.get_curr();
507 out << " " << node_ids[p];
508
509 std::string color;
510 if (net.is_single_source() and p == net.get_source())
511 color = options.source_color;
512 else if (net.is_single_sink() and p == net.get_sink())
513 color = options.sink_color;
514
515 if (not color.empty() and options.use_colors)
516 out << " [style=filled, fillcolor=" << color << "]";
517
518 out << ";\n";
519 }
520
521 // Export arcs
522 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
523 {
524 auto arc = it.get_curr();
525 Node* src = net.get_src_node(arc);
526 Node* tgt = net.get_tgt_node(arc);
527
528 out << " " << node_ids[src] << " -> " << node_ids[tgt];
529
530 // Build label
531 std::ostringstream label;
532 if (options.show_flow or options.show_capacity)
533 {
534 label << "\"";
535 if (options.show_flow)
536 label << arc->flow;
537 if (options.show_flow and options.show_capacity)
538 label << "/";
539 if (options.show_capacity)
540 label << arc->cap;
541 label << "\"";
542 }
543
544 // Build style
545 std::string color;
546 if (options.use_colors)
547 {
548 if (options.highlight_saturated and arc->flow == arc->cap)
549 color = options.saturated_color;
550 else if (options.highlight_empty and arc->flow == 0)
551 color = options.empty_color;
552 }
553
554 out << " [";
555 if (not label.str().empty())
556 out << "label=" << label.str();
557 if (not color.empty())
558 {
559 if (not label.str().empty())
560 out << ", ";
561 out << "color=" << color;
562 }
563 out << "];\n";
564 }
565
566 out << "}\n";
567}
568
578template <class Net>
579std::string network_to_dot_string(const Net& net,
581{
582 using Node = typename Net::Node;
583
584 std::ostringstream out;
585
586 // Build node ID map
588 size_t id = 0;
589 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
590 node_ids[it.get_curr()] = id++;
591
592 out << "digraph " << options.graph_name << " {\n";
593 out << " rankdir=LR;\n";
594 out << " node [shape=circle];\n";
595
596 // Export nodes
597 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
598 {
599 Node* p = it.get_curr();
600 out << " " << node_ids[p];
601
602 std::string color;
603 if (net.is_single_source() and p == net.get_source())
604 color = options.source_color;
605 else if (net.is_single_sink() and p == net.get_sink())
606 color = options.sink_color;
607
608 if (not color.empty() and options.use_colors)
609 out << " [style=filled, fillcolor=" << color << "]";
610
611 out << ";\n";
612 }
613
614 // Export arcs
615 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
616 {
617 auto arc = it.get_curr();
618 Node* src = net.get_src_node(arc);
619 Node* tgt = net.get_tgt_node(arc);
620
621 out << " " << node_ids[src] << " -> " << node_ids[tgt];
622
623 std::ostringstream label;
624 if (options.show_flow or options.show_capacity)
625 {
626 label << "\"";
627 if (options.show_flow)
628 label << arc->flow;
629 if (options.show_flow and options.show_capacity)
630 label << "/";
631 if (options.show_capacity)
632 label << arc->cap;
633 label << "\"";
634 }
635
636 std::string color;
637 if (options.use_colors)
638 {
639 if (options.highlight_saturated and arc->flow == arc->cap)
640 color = options.saturated_color;
641 else if (options.highlight_empty and arc->flow == 0)
642 color = options.empty_color;
643 }
644
645 out << " [";
646 if (not label.str().empty())
647 out << "label=" << label.str();
648 if (not color.empty())
649 {
650 if (not label.str().empty())
651 out << ", ";
652 out << "color=" << color;
653 }
654 out << "];\n";
655 }
656
657 out << "}\n";
658
659 return out.str();
660}
661
662
663//==============================================================================
664// JSON SERIALIZATION
665//==============================================================================
666
693template <class Net>
694void export_network_to_json(const Net& net, const std::string& filename)
695{
696 using Node = typename Net::Node;
697
698 std::ofstream out(filename);
699 if (not out)
700 return;
701
702 // Build node ID map
704 size_t id = 0;
705 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
706 node_ids[it.get_curr()] = id++;
707
708 out << "{\n";
709
710 // Nodes
711 out << " \"num_nodes\": " << net.vsize() << ",\n";
712 out << " \"num_arcs\": " << net.esize() << ",\n";
713
714 // Source and sink
715 if (net.is_single_source())
716 out << " \"source\": " << node_ids[net.get_source()] << ",\n";
717 if (net.is_single_sink())
718 out << " \"sink\": " << node_ids[net.get_sink()] << ",\n";
719
720 // Arcs
721 out << " \"arcs\": [\n";
722 bool first = true;
723 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
724 {
725 if (not first)
726 out << ",\n";
727 first = false;
728
729 auto arc = it.get_curr();
730 out << " {"
731 << "\"src\": " << node_ids[net.get_src_node(arc)] << ", "
732 << "\"tgt\": " << node_ids[net.get_tgt_node(arc)] << ", "
733 << "\"cap\": " << arc->cap << ", "
734 << "\"flow\": " << arc->flow
735 << "}";
736 }
737 out << "\n ]\n";
738 out << "}\n";
739}
740
749template <class Net>
750std::string network_to_json_string(const Net& net)
751{
752 using Node = typename Net::Node;
753
754 std::ostringstream out;
755
756 // Build node ID map
758 size_t id = 0;
759 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
760 node_ids[it.get_curr()] = id++;
761
762 out << "{\n";
763 out << " \"num_nodes\": " << net.vsize() << ",\n";
764 out << " \"num_arcs\": " << net.esize() << ",\n";
765
766 if (net.is_single_source())
767 out << " \"source\": " << node_ids[net.get_source()] << ",\n";
768 if (net.is_single_sink())
769 out << " \"sink\": " << node_ids[net.get_sink()] << ",\n";
770
771 out << " \"arcs\": [\n";
772 bool first = true;
773 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
774 {
775 if (not first)
776 out << ",\n";
777 first = false;
778
779 auto arc = it.get_curr();
780 out << " {"
781 << "\"src\": " << node_ids[net.get_src_node(arc)] << ", "
782 << "\"tgt\": " << node_ids[net.get_tgt_node(arc)] << ", "
783 << "\"cap\": " << arc->cap << ", "
784 << "\"flow\": " << arc->flow
785 << "}";
786 }
787 out << "\n ]\n";
788 out << "}\n";
789
790 return out.str();
791}
792
793
794//==============================================================================
795// DIMACS FORMAT
796//==============================================================================
797
819template <class Net>
820void export_network_to_dimacs(const Net& net, const std::string& filename)
821{
822 using Node = typename Net::Node;
823
824 std::ofstream out(filename);
825 if (not out)
826 return;
827
828 // Build node ID map (1-based for DIMACS)
830 size_t id = 1; // DIMACS is 1-indexed
831 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
832 node_ids[it.get_curr()] = id++;
833
834 // Header
835 out << "c Network exported from Aleph-w\n";
836 out << "p max " << net.vsize() << " " << net.esize() << "\n";
837
838 // Source and sink
839 if (net.is_single_source())
840 out << "n " << node_ids[net.get_source()] << " s\n";
841 if (net.is_single_sink())
842 out << "n " << node_ids[net.get_sink()] << " t\n";
843
844 // Arcs
845 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
846 {
847 auto arc = it.get_curr();
848 out << "a " << node_ids[net.get_src_node(arc)] << " "
849 << node_ids[net.get_tgt_node(arc)] << " "
850 << static_cast<long long>(arc->cap) << "\n";
851 }
852}
853
864template <class Net>
865Net import_network_from_dimacs(const std::string& filename)
866{
867 using Node = typename Net::Node;
868 using Flow_Type = typename Net::Flow_Type;
869
870 Net net;
871 std::ifstream in(filename);
872 if (not in)
873 throw std::runtime_error("Cannot open file: " + filename);
874
875 std::vector<Node*> nodes;
876 size_t source_id = 0, sink_id = 0;
877
878 std::string line;
879 while (std::getline(in, line))
880 {
881 if (line.empty() or line[0] == 'c')
882 continue;
883
884 std::istringstream iss(line);
885 char type;
886 iss >> type;
887
888 if (type == 'p')
889 {
890 std::string problem;
891 size_t n, m;
892 iss >> problem >> n >> m;
893
894 nodes.resize(n + 1); // 1-indexed
895 for (size_t i = 1; i <= n; ++i)
896 nodes[i] = net.insert_node();
897 }
898 else if (type == 'n')
899 {
900 size_t id;
901 char st;
902 iss >> id >> st;
903
904 if (st == 's')
905 source_id = id;
906 else if (st == 't')
907 sink_id = id;
908 }
909 else if (type == 'a')
910 {
911 size_t src, tgt;
912 long long cap;
913 iss >> src >> tgt >> cap;
914
915 net.insert_arc(nodes[src], nodes[tgt],
916 static_cast<Flow_Type>(cap));
917 }
918 }
919
920 // Source and sink nodes are determined by topology in Net_Graph
921 // The DIMACS format's source/sink designations guide network construction
922 (void)source_id; // Suppress unused variable warning
923 (void)sink_id;
924
925 return net;
926}
927
928
929//==============================================================================
930// BENCHMARKING UTILITIES
931//==============================================================================
932
936template <typename Flow_Type>
943
955template <class Net, class Algo>
957benchmark_maxflow(Net& net, Algo algo, const std::string& name)
958{
960 result.algorithm_name = name;
961
962 auto start = std::chrono::high_resolution_clock::now();
963 result.flow_value = algo(net);
964 auto end = std::chrono::high_resolution_clock::now();
965
966 result.elapsed_ms = std::chrono::duration<double, std::milli>(
967 end - start).count();
968
969 return result;
970}
971
975template <typename Flow_Type>
977 const std::vector<MaxFlowBenchmarkResult<Flow_Type>>& results)
978{
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";
984
985 for (const auto& r : results)
986 std::cout << std::left << std::setw(25) << r.algorithm_name
987 << std::setw(15) << r.flow_value
988 << std::setw(15) << std::fixed << std::setprecision(3)
989 << r.elapsed_ms << "\n";
990}
991
992} // namespace Aleph
993
994#endif // NET_UTILS_H
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
WeightedDigraph::Node Node
int num_nodes
Definition btreepic.C:410
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.
Definition htlist.H:1065
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:737
constexpr size_t vsize() const noexcept
Definition graph-dry.H:704
size_t esize() const noexcept
Return the total of arcs of graph.
Definition graph-dry.H:798
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:743
size_t resize(size_t new_size)
Resizes the hash table to a new capacity.
Definition hashDry.H:524
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
double Flow_Type
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Net import_network_from_dimacs(const std::string &filename)
Import network from DIMACS max-flow format.
Definition net_utils.H:865
void export_network_to_dimacs(const Net &net, const std::string &filename)
Export network to DIMACS max-flow format.
Definition net_utils.H:820
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.
Definition net_utils.H:484
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 &params)
Generate a random flow network.
Definition net_utils.H:134
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.
Definition net_utils.H:301
void export_network_to_json(const Net &net, const std::string &filename)
Export network to JSON format.
Definition net_utils.H:694
std::string network_to_json_string(const Net &net)
Export network to JSON string.
Definition net_utils.H:750
MaxFlowBenchmarkResult< typename Net::Flow_Type > benchmark_maxflow(Net &net, Algo algo, const std::string &name)
Run and time a max-flow algorithm.
Definition net_utils.H:957
Net generate_grid_network(size_t rows, size_t cols, typename Net::Flow_Type capacity, bool bidirectional=true)
Generate a grid network.
Definition net_utils.H:244
void print_benchmark_results(const std::vector< MaxFlowBenchmarkResult< Flow_Type > > &results)
Print benchmark results.
Definition net_utils.H:976
std::string network_to_dot_string(const Net &net, const DotExportOptions &options=DotExportOptions())
Generate DOT string for network (instead of file).
Definition net_utils.H:579
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.
Definition net_utils.H:363
static long & color(typename GT::Node *p)
static struct argp_option options[]
Definition ntreepic.C:1886
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
Options for DOT export.
Definition net_utils.H:449
bool highlight_saturated
Highlight saturated arcs.
Definition net_utils.H:453
std::string source_color
Definition net_utils.H:457
std::string empty_color
Definition net_utils.H:460
bool use_colors
Use colors for flow visualization.
Definition net_utils.H:455
bool show_capacity
Show capacity values on arcs.
Definition net_utils.H:451
bool show_flow
Show flow values on arcs.
Definition net_utils.H:450
bool highlight_empty
Highlight empty arcs.
Definition net_utils.H:454
std::string saturated_color
Definition net_utils.H:459
bool show_cost
Show cost values (for cost networks)
Definition net_utils.H:452
Result of running a max-flow algorithm.
Definition net_utils.H:938
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
Definition tpl_net.H:559
constexpr bool is_single_source() const noexcept
Return true if the network has a single source.
Definition tpl_net.H:369
Node * get_source() const
Return an arbitrary source node.
Definition tpl_net.H:548
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.
Definition tpl_net.H:607
Node * get_sink() const
Return an arbitrary sink node.
Definition tpl_net.H:551
typename Arc::Flow_Type Flow_Type
Capacity/flow numeric type.
Definition tpl_net.H:278
constexpr bool is_single_sink() const noexcept
Return true if the network has a single sink.
Definition tpl_net.H:372
NodeT Node
Node type.
Definition tpl_net.H:275
Parameters for random network generation.
Definition net_utils.H:101
double max_capacity
Maximum arc capacity.
Definition net_utils.H:105
size_t num_arcs
Target number of arcs.
Definition net_utils.H:103
bool ensure_connected
Ensure source can reach sink.
Definition net_utils.H:108
double min_cost
Minimum arc cost (for cost networks)
Definition net_utils.H:106
double min_capacity
Minimum arc capacity.
Definition net_utils.H:104
unsigned seed
Random seed (0 = use time)
Definition net_utils.H:109
double max_cost
Maximum arc cost.
Definition net_utils.H:107
size_t num_nodes
Number of nodes.
Definition net_utils.H:102
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
ValueArg< size_t > seed
Definition testHash.C:48
gsl_rng * r
Dynamic key-value map based on balanced binary search trees.
Network flow graph structures.
Maximum flow minimum cost network algorithms.
DynList< int > l