Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
random_network_generator_test.cc
Go to the documentation of this file.
1/* Tests for random network generator
2 *
3 * Demonstrates the use of random network generators for comprehensive testing
4 */
5
6#include <gtest/gtest.h>
8#include <tpl_net.H>
9#include <tpl_netcost.H>
10#include <tpl_maxflow.H>
11#include <tpl_mincost.H>
12
13using namespace Aleph;
14using namespace Aleph::Testing;
15
16namespace
17{
20}
21
22
23//==============================================================================
24// Erdős–Rényi Generator Tests
25//==============================================================================
26
28{
30 config.num_nodes = 10;
31 config.density = 0.3;
32 config.seed = 42;
33
35 TestNet net;
36 gen.generate(net);
37
38 EXPECT_EQ(net.vsize(), 10);
39 EXPECT_GT(net.esize(), 0);
40}
41
43{
45 config.num_nodes = 20;
46 config.density = 0.2;
47 config.ensure_connected = true;
48 config.seed = 123;
49
51 TestNet net;
52 gen.generate(net);
53
54 // Try to compute max flow - should succeed if connected
55 auto flow = dinic_maximum_flow(net);
56
57 EXPECT_GT(flow, 0.0); // Should find some flow
58}
59
61{
63 config.num_nodes = 15;
64 config.seed = 456;
65
66 // Low density
67 config.density = 0.1;
70 gen_low.generate(net_low);
71 size_t arcs_low = net_low.esize();
72
73 // High density
74 config.density = 0.8;
77 gen_high.generate(net_high);
78 size_t arcs_high = net_high.esize();
79
80 // Higher density should produce more arcs
82}
83
84
85//==============================================================================
86// Layered Generator Tests
87//==============================================================================
88
90{
92 config.density = 0.5;
93 config.seed = 789;
94
96 TestNet net;
97 gen.generate(net);
98
99 // Should have source + 2*5 intermediate + sink = 12 nodes
100 EXPECT_EQ(net.vsize(), 12);
101 EXPECT_GT(net.esize(), 0);
102}
103
105{
107 config.density = 0.6;
108 config.ensure_connected = true;
109 config.seed = 111;
110
112 TestNet net;
113 gen.generate(net);
114
115 // Consolidate multiple sources/sinks into single super-source/sink if needed
116 if (!net.is_single_source())
117 net.make_super_source();
118 if (!net.is_single_sink())
119 net.make_super_sink();
120
121 auto flow = edmonds_karp_maximum_flow(net);
122
123 EXPECT_GT(flow, 0.0);
124}
125
126
127//==============================================================================
128// Grid Generator Tests
129//==============================================================================
130
132{
134 config.seed = 222;
135
137 TestNet net;
138 gen.generate(net);
139
140 EXPECT_EQ(net.vsize(), 25); // 5x5 grid
141
142 // Grid should have (rows * (cols-1)) + ((rows-1) * cols) arcs
143 // = 5*4 + 4*5 = 20 + 20 = 40
144 EXPECT_EQ(net.esize(), 40);
145}
146
148{
150 config.min_capacity = 10.0;
151 config.max_capacity = 20.0;
152 config.seed = 333;
153
155 TestNet net;
156 gen.generate(net);
157
158 auto flow = dinic_maximum_flow(net);
159
160 EXPECT_GT(flow, 0.0);
161}
162
164{
166 config.seed = 444;
167
168 // Small grid
171 gen_small.generate(net_small);
172
173 // Larger grid
176 gen_large.generate(net_large);
177
178 EXPECT_EQ(net_small.vsize(), 9);
179 EXPECT_EQ(net_large.vsize(), 100);
180}
181
182
183//==============================================================================
184// Bipartite Generator Tests
185//==============================================================================
186
188{
190 config.seed = 555;
191
193 TestNet net;
194 gen.generate(net);
195
196 // source + sink + left + right = 2 + 5 + 5 = 12
197 EXPECT_EQ(net.vsize(), 12);
198}
199
201{
203 config.min_capacity = 1.0;
204 config.max_capacity = 1.0; // Unit capacity for matching
205 config.seed = 666;
206
208 TestNet net;
209 gen.generate(net);
210
211 auto flow = hlpp_maximum_flow(net);
212
213 // Maximum matching should be at most min(6, 6) = 6
214 EXPECT_LE(flow, 6.0);
215 EXPECT_GT(flow, 0.0);
216}
217
218
219//==============================================================================
220// Cost Network Generator Tests
221//==============================================================================
222
224{
226 config.num_nodes = 15;
227 config.density = 0.3;
228 config.min_cost = 1.0;
229 config.max_cost = 50.0;
230 config.ensure_connected = true;
231 config.seed = 777;
232
234 CostNet net;
235 gen.generate(net);
236
237 // Consolidate sources/sinks if needed
238 if (!net.is_single_source())
239 net.make_super_source();
240 if (!net.is_single_sink())
241 net.make_super_sink();
242
243 // Compute min-cost flow
244 auto [flow, cost] = successive_shortest_paths(net);
245
246 EXPECT_GT(flow, 0.0);
247 EXPECT_GT(cost, 0.0);
248}
249
251{
253 config.density = 0.5;
254 config.min_cost = 1.0;
255 config.max_cost = 10.0;
256 // Use small network and unit capacities to keep SSP iterations reasonable
257 // SSP has O(V * U * ...) complexity where U is max flow value
258 // In Debug mode with Clang, even small networks can be slow
259 config.min_capacity = 1.0;
260 config.max_capacity = 1.0; // Unit capacity for minimal iterations
261 config.ensure_connected = true;
262 config.seed = 888;
263
264 // Small network: 3 layers with 2 nodes per intermediate layer
265 // Total: 1 (source) + 2 (intermediate) + 1 (sink) = 4 nodes
267 CostNet net;
268 gen.generate(net);
269
270 // Consolidate sources/sinks if needed
271 if (!net.is_single_source())
272 net.make_super_source();
273 if (!net.is_single_sink())
274 net.make_super_sink();
275
276 auto [flow, cost] = successive_shortest_paths(net);
277
278 EXPECT_GT(flow, 0.0);
279 EXPECT_GT(cost, 0.0);
280}
281
282
283//==============================================================================
284// Stress Tests with Random Networks
285//==============================================================================
286
288{
290 config.num_nodes = 20;
291 config.density = 0.3;
292 config.ensure_connected = true;
293
294 // Generate and test 10 different random networks
295 for (int i = 0; i < 10; ++i)
296 {
297 config.seed = 1000 + i;
298
300
301 // Test Edmonds-Karp
302 gen.reseed(); // Reset RNG to get reproducible network
304 gen.generate(net1);
306
307 // Test Dinic on identical network
308 gen.reseed(); // Reset RNG to generate identical network
310 gen.generate(net2);
312
313 // Both should give same result (within floating-point tolerance)
315
316 // Both should find positive flow
317 EXPECT_GT(flow_ek, 0.0);
318 EXPECT_GT(flow_dinic, 0.0);
319
320 // Networks should be valid after max flow
321 EXPECT_TRUE(net1.check_network());
322 EXPECT_TRUE(net2.check_network());
323 }
324}
325
327{
329 config.min_capacity = 5.0;
330 config.max_capacity = 50.0;
331 config.seed = 999;
332
333 for (int size = 5; size <= 15; size += 5)
334 {
336 TestNet net;
337 gen.generate(net);
338
339 EXPECT_EQ(net.vsize(), size_t(size * size));
340
341 // Grid networks are inherently single-source, single-sink
344
345 auto flow = capacity_scaling_maximum_flow(net);
346
347 EXPECT_GT(flow, 0.0);
348 }
349}
350
352{
354 config.num_nodes = 25;
355 config.ensure_connected = true;
356 config.seed = 1111;
357
358 for (double density = 0.1; density <= 0.9; density += 0.2)
359 {
360 config.density = density;
361
363 TestNet net;
364 gen.generate(net);
365
366 // Consolidate sources/sinks if needed
367 if (!net.is_single_source())
368 net.make_super_source();
369 if (!net.is_single_sink())
370 net.make_super_sink();
371
372 auto flow = dinic_maximum_flow(net);
373
374 // More density generally means more flow capacity
375 EXPECT_GT(flow, 0.0);
376 }
377}
378
379
380//==============================================================================
381// Factory Tests
382//==============================================================================
383
385{
387 config.num_nodes = 10;
388 config.density = 0.3;
389 config.seed = 1234;
390
391 auto gen_er = create_generator<TestNet>("erdos-renyi", config);
392 EXPECT_NE(gen_er, nullptr);
394 gen_er->generate(net_er);
395 EXPECT_GT(net_er.vsize(), 0);
396
397 auto gen_layered = create_generator<TestNet>("layered", config);
398 EXPECT_NE(gen_layered, nullptr);
400 gen_layered->generate(net_layered);
401 EXPECT_GT(net_layered.vsize(), 0);
402
403 auto gen_grid = create_generator<TestNet>("grid", config);
404 EXPECT_NE(gen_grid, nullptr);
406 gen_grid->generate(net_grid);
407 EXPECT_GT(net_grid.vsize(), 0);
408
409 auto gen_bipartite = create_generator<TestNet>("bipartite", config);
410 EXPECT_NE(gen_bipartite, nullptr);
412 gen_bipartite->generate(net_bipartite);
413 EXPECT_GT(net_bipartite.vsize(), 0);
414}
415
417{
419
420 EXPECT_THROW(create_generator<TestNet>("invalid-type", config),
421 std::invalid_argument);
422}
423
424
425int main(int argc, char** argv)
426{
427 ::testing::InitGoogleTest(&argc, argv);
428 return RUN_ALL_TESTS();
429}
int main()
Complete bipartite network generator.
Erdős–Rényi random network generator.
Layered (staged) network generator.
constexpr size_t vsize() const noexcept
Definition graph-dry.H:698
size_t esize() const noexcept
Return the total of arcs of graph.
Definition graph-dry.H:792
#define TEST(name)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Net::Flow_Type edmonds_karp_maximum_flow(Net &net)
Maximize flow using the Edmonds-Karp algorithm.
Definition tpl_net.H:1551
size_t size(Node *root) noexcept
Net::Flow_Type dinic_maximum_flow(Net &net)
Compute maximum flow using Dinic's algorithm.
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< typename Net::Flow_Type, typename Net::Flow_Type > successive_shortest_paths(Net &net)
Compute minimum cost maximum flow using Successive Shortest Paths.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Random network generators for testing flow algorithms.
Arc of a flow network implemented with adjacency lists.
Definition tpl_net.H:115
Arc type for maximum flow minimum cost networks.
Definition tpl_netcost.H:93
Capacitated flow network with costs associated to arcs.
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
void make_super_source()
Convert a multi-source network into a single super-source network.
Definition tpl_net.H:458
void make_super_sink()
Convert a multi-sink network into a single super-sink network.
Definition tpl_net.H:493
constexpr bool is_single_source() const noexcept
Return true if the network has a single source.
Definition tpl_net.H:369
constexpr bool is_single_sink() const noexcept
Return true if the network has a single sink.
Definition tpl_net.H:372
Random network generator configuration.
bool ensure_connected
Ensure source can reach sink.
double min_cost
Minimum arc cost (for cost networks)
unsigned seed
Random seed (0 = time-based)
double density
Edge density [0, 1] (for Erdős–Rényi)
Advanced maximum flow algorithms.
Advanced minimum cost flow algorithms.
Network flow graph structures.
Maximum flow minimum cost network algorithms.