11#include <gtest/gtest.h>
87 std::vector<std::vector<Node*>>
nodes(rows, std::vector<Node*>(cols));
91 for (
int i = 0; i < rows; ++i)
92 for (
int j = 0; j < cols; ++j)
96 for (
int i = 0; i < rows; ++i)
97 for (
int j = 0; j < cols - 1; ++j)
101 for (
int i = 0; i < rows - 1; ++i)
102 for (
int j = 0; j < cols; ++j)
111 it.get_curr()->flow = 0;
134 build_diamond_network(net);
198 build_diamond_network(net);
250 build_diamond_network(net);
289 build_diamond_network(net);
385 build_diamond_network(net);
398 build_diamond_network(net);
437 Arc* arc = it.get_curr();
445 double residual = forward ? (arc->cap - arc->flow) : arc->flow;
462 Arc* arc = it.get_curr();
478 return std::abs(max_flow -
min_cut) < 1e-6;
499 build_diamond_network(net);
611 build_diamond_network(net);
633 Arc* arc = it.get_curr();
640 double residual = forward ? (arc->cap - arc->flow) : arc->flow;
659 Arc* arc = it.get_curr();
671 Arc* arc = it.get_curr();
780 build_diamond_network(net);
783 auto flow =
algo(net);
790 build_diamond_network(net);
793 auto flow =
algo(net);
800 build_diamond_network(net);
803 auto flow =
algo(net);
810 build_diamond_network(net);
827 std::cout <<
"\n=== Max Flow Performance Benchmark (Grid "
834 auto start = std::chrono::high_resolution_clock::now();
835 auto flow =
algo(net);
836 auto end = std::chrono::high_resolution_clock::now();
837 double ms = std::chrono::duration<double, std::milli>(end - start).count();
839 std::cout << name <<
": " <<
ms <<
" ms, flow=" << flow <<
"\n";
896 auto arc = it.get_curr();
1062 auto p = it.get_curr();
1066 double in_flow = 0, out_flow = 0;
1069 auto arc =
ait.get_curr();
1071 in_flow += arc->flow;
1073 out_flow += arc->flow;
1077 <<
"Conservation violated at node with in=" << in_flow
1078 <<
" out=" << out_flow;
1099 for (
int i = 0; i <
N; ++i)
1110 for (
int i = 0; i <
N - 1; ++i)
1117 for (
int i = 0; i <
N; ++i)
1129 auto s2 = n.insert_node(0);
1130 auto t2 = n.insert_node(1);
1133 for (
int i = 0; i <
N; ++i)
1135 ca[i] = n.insert_node(10 + i);
1136 cb[i] = n.insert_node(30 + i);
1138 n.insert_arc(
s2,
ca[0], 100);
1139 n.insert_arc(
s2,
cb[0], 100);
1140 for (
int i = 0; i <
N - 1; ++i)
1142 n.insert_arc(
ca[i],
ca[i+1], 50);
1143 n.insert_arc(
cb[i],
cb[i+1], 50);
1145 for (
int i = 0; i <
N; ++i)
1147 n.insert_arc(
ca[i],
cb[i], 10);
1148 n.insert_arc(
cb[i],
ca[i], 10);
1150 n.insert_arc(
ca[
N-1],
t2, 100);
1151 n.insert_arc(
cb[
N-1],
t2, 100);
1216 auto arc = it.get_curr();
1229 const auto& path =
path_it.get_curr();
1244 auto arc = it.get_curr();
1288 if (
decomp.num_cycles() >= 1)
1296 for (
auto it =
cycle.nodes.
get_it(); it.has_curr(); it.next_ne())
1298 for (
auto it =
cycle.arcs.
get_it(); it.has_curr(); it.next_ne())
1302 <<
"Cycle should have nodes.size() == arcs.size() + 1 (closing node)";
1308 <<
"Cycle first and last node should be the same";
1337 if (
decomp.num_cycles() >= 1)
1342 for (
auto it =
cycle.nodes.
get_it(); it.has_curr(); it.next_ne())
1344 for (
auto it =
cycle.arcs.
get_it(); it.has_curr(); it.next_ne())
1348 <<
"Phase-1 cycle should also have nodes.size() == arcs.size() + 1";
1353 <<
"Phase-1 cycle first and last node should be the same";
1429 const int width = 100;
1434 for (
int i = 0; i < width; ++i)
1443 auto s2 =
net2.insert_node(0);
1444 auto t2 =
net2.insert_node(1);
1445 for (
int i = 0; i < width; ++i)
1447 auto mid =
net2.insert_node(10 + i);
1472 template <
class NetT>
1477 <<
"build_random_network requires n >= 3";
1479 using NodeT =
typename NetT::Node;
1480 std::mt19937
rng(seed);
1481 std::uniform_int_distribution<int>
node_dist(0, n - 1);
1482 std::uniform_int_distribution<int>
cap_dist(1, max_cap);
1484 std::vector<NodeT *>
nodes(n);
1485 for (
int i = 0; i < n; ++i)
1486 nodes[i] = net.insert_node(i);
1492 for (
int i = 0; i < m - 2; ++i)
1496 if (u == v) v = (u + 1 < n) ? (u + 1) : 0;
1499 if (u == n - 1) u = n - 2;
1501 if (u == v)
continue;
1507 template <
class NetT>
1509 int count,
int n,
int m,
1510 int max_cap,
unsigned seed)
1513 for (
int i = 0; i <
count; ++i)
1521 for (
unsigned seed = 100; seed < 130; ++seed)
1523 std::vector<TestNet>
nets;
1526 if (
not (
nets[0].is_single_source()
and nets[0].is_single_sink()))
1535 <<
"EK vs Dinic disagree at seed=" << seed;
1537 <<
"EK vs CapScale disagree at seed=" << seed;
1539 <<
"EK vs HLPP disagree at seed=" << seed;
1541 EXPECT_TRUE(
nets[0].check_network()) <<
"EK invalid at seed=" << seed;
1542 EXPECT_TRUE(
nets[1].check_network()) <<
"Dinic invalid at seed=" << seed;
1543 EXPECT_TRUE(
nets[2].check_network()) <<
"CapScale invalid at seed=" << seed;
1544 EXPECT_TRUE(
nets[3].check_network()) <<
"HLPP invalid at seed=" << seed;
1551 for (
unsigned seed = 200; seed < 210; ++seed)
1553 std::vector<TestNet>
nets;
1556 if (
not (
nets[0].is_single_source()
and nets[0].is_single_sink()))
1564 <<
"EK vs Dinic disagree at seed=" << seed;
1566 <<
"EK vs HLPP disagree at seed=" << seed;
1585 auto s = net.insert_node(0);
1586 auto a = net.insert_node(1);
1587 auto b = net.insert_node(2);
1588 auto t = net.insert_node(3);
1589 net.insert_arc(s, a, 10);
1590 net.insert_arc(s, b, 10);
1591 net.insert_arc(a, t, 10);
1592 net.insert_arc(b, t, 10);
1619 auto build = [](
IntNet & net) {
1620 auto s = net.insert_node(0);
1621 auto a = net.insert_node(1);
1622 auto b = net.insert_node(2);
1623 auto c = net.insert_node(3);
1624 auto d = net.insert_node(4);
1625 auto t = net.insert_node(5);
1627 net.insert_arc(s, a, 16);
1628 net.insert_arc(s, c, 13);
1629 net.insert_arc(a, b, 12);
1630 net.insert_arc(a, c, 10);
1631 net.insert_arc(b, t, 20);
1632 net.insert_arc(c, d, 14);
1633 net.insert_arc(d, b, 7);
1634 net.insert_arc(d, t, 4);
1656 for (
unsigned seed = 300; seed < 320; ++seed)
1658 std::vector<IntNet>
nets;
1661 if (
not (
nets[0].is_single_source()
and nets[0].is_single_sink()))
1670 <<
"EK vs Dinic disagree at seed=" << seed;
1672 <<
"EK vs CapScale disagree at seed=" << seed;
1674 <<
"EK vs HLPP disagree at seed=" << seed;
1688 auto build = [](
IntNet & net) {
1689 auto s = net.insert_node(0);
1690 auto a = net.insert_node(1);
1691 auto b = net.insert_node(2);
1692 auto c = net.insert_node(3);
1693 auto t = net.insert_node(4);
1695 net.insert_arc(s, a, 3);
1696 net.insert_arc(s, b, 2);
1697 net.insert_arc(a, b, 1);
1698 net.insert_arc(a, c, 3);
1699 net.insert_arc(b, c, 1);
1700 net.insert_arc(c, t, 4);
1718 auto arc = it.get_curr();
1722 if (arc->flow == arc->cap)
1732 ::testing::InitGoogleTest(&
argc,
argv);
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
WeightedDigraph::Node Node
bool has_curr() const noexcept
Check if there is a current valid item.
static Array create(size_t n)
Create an array with n logical elements.
bool has_curr() const noexcept
Return true the iterator has an current arc.
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
T & front()
Return a modifiable reference to the oldest item in the queue.
bool is_empty() const noexcept
Return true if this is empty.
T & insert(const T &item)
Insert a new item by copy.
T & get_last() const
Return the last item of the list.
T & get_first() const
Return the first item of the list.
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).
Filtered iterator for incoming arcs of a node.
Filtered iterator on the nodes of a graph.
Filtered iterator for outcoming arcs of a node.
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
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
Net build_grid_network(int rows, int cols, FlowType base_cap=10.0)
Build a grid network for stress testing.
Main namespace for Aleph-w library functions.
FlowStatistics< typename Net::Flow_Type > compute_flow_statistics(const Net &net)
Compute statistics about the current flow in a network.
Net::Flow_Type edmonds_karp_maximum_flow(Net &net)
Maximize flow using the Edmonds-Karp algorithm.
size_t size(Node *root) noexcept
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.
Net::Flow_Type ford_fulkerson_maximum_flow(Net &net)
Maximize flow using the Ford-Fulkerson algorithm.
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.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Filtered iterator on all the arcs of a graph.
Functor wrapper for capacity scaling.
Functor wrapper for flow decomposition.
Functor wrapper for Dinic's algorithm.
Functor wrapper for HLPP.
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.
bool check_network() const
Validate flow-conservation and capacity constraints.
bool is_source(Node *node) const noexcept
Return true if node is a 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.
bool is_sink(Node *node) const noexcept
Return true if node is a sink.
Advanced maximum flow algorithms.
void verify_flow_conservation(const Net &net)
Node * build_antiparallel_network(TestNet &net)
bool verify_max_flow_min_cut(Net &net, double max_flow)
double compute_min_cut_capacity(Net &net)
Network flow graph structures.