Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
random_network_generator.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
41#ifndef RANDOM_NETWORK_GENERATOR_H
42#define RANDOM_NETWORK_GENERATOR_H
43
44#include <random>
45#include <vector>
46#include <queue>
47#include <set>
48#include <tpl_net.H>
49#include <tpl_netcost.H>
50
51namespace Aleph
52{
53namespace Testing
54{
55
60{
61 size_t num_nodes = 10;
62 size_t num_arcs = 20;
63 double density = 0.3;
64 double min_capacity = 1.0;
65 double max_capacity = 100.0;
66 double min_cost = 1.0;
67 double max_cost = 10.0;
68 unsigned seed = 42;
69 bool ensure_connected = true;
70};
71
72// Type trait to detect if a network has cost support
73template<typename Net, typename = void>
74struct has_cost_support : std::false_type {};
75
76template<typename Net>
77struct has_cost_support<Net, std::void_t<decltype(std::declval<typename Net::Arc>().cost)>>
78 : std::true_type {};
79
83template <class Net>
85{
86protected:
88 std::mt19937 rng;
89
90 using Node = typename Net::Node;
91 using Arc = typename Net::Arc;
92
93 // Random number generators
94 std::uniform_real_distribution<double> capacity_dist;
95 std::uniform_real_distribution<double> cost_dist;
96 std::uniform_real_distribution<double> prob_dist{0.0, 1.0};
97
98public:
100 : config(cfg),
101 rng(cfg.seed == 0 ? std::random_device()() : cfg.seed),
102 capacity_dist(cfg.min_capacity, cfg.max_capacity),
103 cost_dist(cfg.min_cost, cfg.max_cost)
104 {}
105
106 virtual ~RandomNetworkGenerator() = default;
107
110 void reseed()
111 {
112 rng.seed(config.seed == 0 ? std::random_device()() : config.seed);
113 }
114
116 void reseed(unsigned new_seed)
117 {
119 rng.seed(new_seed);
120 }
121
122 // Generate a network (fills the provided network reference to avoid copy issues)
123 virtual void generate(Net& out) = 0;
124
125protected:
126 // Helper: get random capacity
128 {
129 return capacity_dist(rng);
130 }
131
132 // Helper: get random cost
133 double random_cost()
134 {
135 return cost_dist(rng);
136 }
137
138 // Helper: random probability [0, 1]
139 double random_prob()
140 {
141 return prob_dist(rng);
142 }
143
144 // Helper: Check if sink is reachable from source
145 bool is_connected(const Net& net, Node* source, Node* sink)
146 {
147 std::set<Node*> visited;
148 std::queue<Node*> q;
149
150 visited.insert(source);
151 q.push(source);
152
153 while (!q.empty())
154 {
155 Node* u = q.front();
156 q.pop();
157
158 if (u == sink)
159 return true;
160
161 for (Out_Iterator<Net> it(u); it.has_curr(); it.next_ne())
162 {
163 Arc* arc = it.get_curr();
164 Node* v = net.get_tgt_node(arc);
165
166 if (visited.count(v) == 0)
167 {
168 visited.insert(v);
169 q.push(v);
170 }
171 }
172 }
173
174 return false;
175 }
176
177 // Helper: Add path from source to sink if needed
178 void ensure_path(Net& net, Node* source, Node* sink,
179 const std::vector<Node*>& nodes)
180 {
181 if (is_connected(net, source, sink))
182 return;
183
184 // Add a path through intermediate nodes
185 Node* prev = source;
186 for (size_t i = 2; i < nodes.size() - 1; ++i)
187 {
188 insert_arc(net, prev, nodes[i]);
189 prev = nodes[i];
190 }
191 insert_arc(net, prev, sink);
192 }
193
194 // Helper: Insert arc with appropriate attributes
195 void insert_arc(Net& net, Node* src, Node* tgt)
196 {
197 if constexpr (has_cost_support<Net>::value)
198 {
199 net.insert_arc(src, tgt, random_capacity(), random_cost());
200 }
201 else
202 {
203 net.insert_arc(src, tgt, random_capacity());
204 }
205 }
206};
207
208
215template <class Net>
217{
219 using typename Base::Node;
220 using Base::config;
221 using Base::random_prob;
222 using Base::insert_arc;
223 using Base::is_connected;
224 using Base::ensure_path;
225
226public:
229
230 void generate(Net& net) override
231 {
232 std::vector<Node*> nodes;
233
234 // Create nodes
235 for (size_t i = 0; i < config.num_nodes; ++i)
236 nodes.push_back(net.insert_node());
237
238 Node* source = nodes[0];
239 Node* sink = nodes[config.num_nodes - 1];
240
241 // Add arcs with probability = density
242 // Skip direct source -> intermediate and intermediate -> source
243 // Skip direct sink connections that would bypass the network
244 for (size_t i = 0; i < config.num_nodes; ++i)
245 {
246 for (size_t j = 0; j < config.num_nodes; ++j)
247 {
248 if (i == j)
249 continue;
250
251 // Don't allow arcs back to source or from sink
252 if (j == 0 || i == config.num_nodes - 1)
253 continue;
254
255 if (random_prob() < config.density)
256 insert_arc(net, nodes[i], nodes[j]);
257 }
258 }
259
260 // Ensure connectivity if requested
262 ensure_path(net, source, sink, nodes);
263 }
264};
265
266
273template <class Net>
275{
277 using typename Base::Node;
278 using Base::config;
279 using Base::random_prob;
280 using Base::insert_arc;
281
284
285public:
287 size_t layers = 4,
288 size_t per_layer = 5)
290 {
291 // Adjust num_nodes to match layers
292 this->config.num_nodes = 2 + (layers - 2) * nodes_per_layer;
293 }
294
295 void generate(Net& net) override
296 {
297 std::vector<std::vector<Node*>> layers(num_layers);
298
299 // Create source (layer 0)
300 layers[0].push_back(net.insert_node());
301
302 // Create intermediate layers
303 for (size_t layer = 1; layer < num_layers - 1; ++layer)
304 {
305 for (size_t i = 0; i < nodes_per_layer; ++i)
307 }
308
309 // Create sink (last layer)
310 layers[num_layers - 1].push_back(net.insert_node());
311
312 // Connect layers: each node in layer i connects to nodes in layer i+1
313 for (size_t layer = 0; layer < num_layers - 1; ++layer)
314 {
315 for (Node* u : layers[layer])
316 {
317 for (Node* v : layers[layer + 1])
318 {
319 if (random_prob() < config.density)
320 insert_arc(net, u, v);
321 }
322 }
323 }
324
325 // Ensure at least one path exists
327 {
328 Node* prev = layers[0][0];
329 for (size_t layer = 1; layer < num_layers; ++layer)
330 {
331 Node* next = layers[layer][0];
332 // Check if connection exists
333 bool has_connection = false;
334 for (Out_Iterator<Net> it(prev); it.has_curr(); it.next_ne())
335 {
336 if (net.get_tgt_node(it.get_curr()) == next)
337 {
338 has_connection = true;
339 break;
340 }
341 }
342 if (!has_connection)
343 insert_arc(net, prev, next);
344 prev = next;
345 }
346 }
347 }
348};
349
350
357template <class Net>
359{
361 using typename Base::Node;
362 using Base::config;
363 using Base::insert_arc;
364
365 size_t rows;
366 size_t cols;
367
368public:
370 size_t r = 5,
371 size_t c = 5)
372 : Base(cfg), rows(r), cols(c)
373 {
374 this->config.num_nodes = r * c;
375 }
376
377 void generate(Net& net) override
378 {
379 std::vector<std::vector<Node*>> grid(rows, std::vector<Node*>(cols));
380
381 // Create grid nodes
382 for (size_t i = 0; i < rows; ++i)
383 for (size_t j = 0; j < cols; ++j)
384 grid[i][j] = net.insert_node();
385
386 // Add horizontal arcs (left to right)
387 for (size_t i = 0; i < rows; ++i)
388 for (size_t j = 0; j < cols - 1; ++j)
389 insert_arc(net, grid[i][j], grid[i][j+1]);
390
391 // Add vertical arcs (top to bottom)
392 for (size_t i = 0; i < rows - 1; ++i)
393 for (size_t j = 0; j < cols; ++j)
394 insert_arc(net, grid[i][j], grid[i+1][j]);
395 }
396};
397
398
405template <class Net>
407{
409 using typename Base::Node;
410 using Base::config;
411 using Base::insert_arc;
412
413 size_t left_size;
415
416public:
418 size_t left = 5,
419 size_t right = 5)
420 : Base(cfg), left_size(left), right_size(right)
421 {
422 this->config.num_nodes = 2 + left + right; // source + left + right + sink
423 }
424
425 void generate(Net& net) override
426 {
427 Node* source = net.insert_node();
428 Node* sink = net.insert_node();
429
430 std::vector<Node*> left_nodes;
431 std::vector<Node*> right_nodes;
432
433 // Create left side
434 for (size_t i = 0; i < left_size; ++i)
435 left_nodes.push_back(net.insert_node());
436
437 // Create right side
438 for (size_t i = 0; i < right_size; ++i)
439 right_nodes.push_back(net.insert_node());
440
441 // Connect source to left side
442 for (Node* u : left_nodes)
443 insert_arc(net, source, u);
444
445 // Connect left to right (complete bipartite)
446 for (Node* u : left_nodes)
447 for (Node* v : right_nodes)
448 insert_arc(net, u, v);
449
450 // Connect right side to sink
451 for (Node* v : right_nodes)
452 insert_arc(net, v, sink);
453 }
454};
455
456
460template <class Net>
461std::unique_ptr<RandomNetworkGenerator<Net>>
462create_generator(const std::string& type, const NetworkGeneratorConfig& config)
463{
464 if (type == "erdos-renyi")
465 return std::make_unique<ErdosRenyiGenerator<Net>>(config);
466 else if (type == "layered")
467 return std::make_unique<LayeredNetworkGenerator<Net>>(config);
468 else if (type == "grid")
469 return std::make_unique<GridNetworkGenerator<Net>>(config);
470 else if (type == "bipartite")
471 return std::make_unique<BipartiteNetworkGenerator<Net>>(config);
472 else
473 throw std::invalid_argument("Unknown generator type: " + type);
474}
475
476} // namespace Testing
477} // namespace Aleph
478
479#endif // RANDOM_NETWORK_GENERATOR_H
bool has_curr() const noexcept
Return true the iterator has an current arc.
Definition tpl_graph.H:1645
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
Filtered iterator for outcoming arcs of a node.
Definition tpl_graph.H:1750
Complete bipartite network generator.
void insert_arc(Net &net, Node *src, Node *tgt)
BipartiteNetworkGenerator(const NetworkGeneratorConfig &cfg, size_t left=5, size_t right=5)
Erdős–Rényi random network generator.
void insert_arc(Net &net, Node *src, Node *tgt)
ErdosRenyiGenerator(const NetworkGeneratorConfig &cfg)
void ensure_path(Net &net, Node *source, Node *sink, const std::vector< Node * > &nodes)
GridNetworkGenerator(const NetworkGeneratorConfig &cfg, size_t r=5, size_t c=5)
void insert_arc(Net &net, Node *src, Node *tgt)
Layered (staged) network generator.
void insert_arc(Net &net, Node *src, Node *tgt)
LayeredNetworkGenerator(const NetworkGeneratorConfig &cfg, size_t layers=4, size_t per_layer=5)
Base class for random network generators.
virtual void generate(Net &out)=0
void reseed(unsigned new_seed)
Reset with a specific seed (also updates config.seed)
std::uniform_real_distribution< double > cost_dist
void insert_arc(Net &net, Node *src, Node *tgt)
std::uniform_real_distribution< double > prob_dist
bool is_connected(const Net &net, Node *source, Node *sink)
void ensure_path(Net &net, Node *source, Node *sink, const std::vector< Node * > &nodes)
RandomNetworkGenerator(const NetworkGeneratorConfig &cfg)
void reseed()
Reset the random number generator to the original seed.
std::uniform_real_distribution< double > capacity_dist
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
std::unique_ptr< RandomNetworkGenerator< Net > > create_generator(const std::string &type, const NetworkGeneratorConfig &config)
Factory function to create generators.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:175
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
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
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
ArcT Arc
Arc type.
Definition tpl_net.H:272
NodeT Node
Node type.
Definition tpl_net.H:275
Random network generator configuration.
bool ensure_connected
Ensure source can reach sink.
double min_cost
Minimum arc cost (for cost networks)
size_t num_arcs
Number of arcs (ignored for some generators)
unsigned seed
Random seed (0 = time-based)
double density
Edge density [0, 1] (for Erdős–Rényi)
Network flow graph structures.
Maximum flow minimum cost network algorithms.