Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
test_connectivity_test.cc
Go to the documentation of this file.
1
6#include <gtest/gtest.h>
8#include <tpl_graph.H>
9
10using namespace Aleph;
11
12// =============================================================================
13// Type Definitions
14// =============================================================================
15
17using Node = GT::Node;
18using Arc = GT::Arc;
19
20// =============================================================================
21// Test Fixture
22// =============================================================================
23
24class TestConnectivityTest : public ::testing::Test
25{
26protected:
28
29 void SetUp() override
30 {
31 g = GT();
32 }
33
34 void TearDown() override {}
35};
36
37// =============================================================================
38// Basic Connectivity Tests
39// =============================================================================
40
42{
44
45 // Empty graph behavior: library returns false (no nodes to connect)
47}
48
57
59{
60 auto n1 = g.insert_node(1);
61 auto n2 = g.insert_node(2);
62 g.insert_arc(n1, n2);
63
65
67}
68
70{
71 g.insert_node(1);
72 g.insert_node(2);
73
75
77}
78
80{
81 auto n1 = g.insert_node(1);
82 auto n2 = g.insert_node(2);
83 auto n3 = g.insert_node(3);
84 auto n4 = g.insert_node(4);
85
86 g.insert_arc(n1, n2);
87 g.insert_arc(n2, n3);
88 g.insert_arc(n3, n4);
89
91
93}
94
95// =============================================================================
96// Disconnected Graph Tests
97// =============================================================================
98
100{
101 // Component 1
102 auto n1 = g.insert_node(1);
103 auto n2 = g.insert_node(2);
104 g.insert_arc(n1, n2);
105
106 // Component 2 (disconnected)
107 auto n3 = g.insert_node(3);
108 auto n4 = g.insert_node(4);
109 g.insert_arc(n3, n4);
110
112
114}
115
117{
118 // Component 1
119 auto n1 = g.insert_node(1);
120 auto n2 = g.insert_node(2);
121 g.insert_arc(n1, n2);
122
123 // Component 2
124 auto n3 = g.insert_node(3);
125 auto n4 = g.insert_node(4);
126 g.insert_arc(n3, n4);
127
128 // Component 3
129 auto n5 = g.insert_node(5);
130 auto n6 = g.insert_node(6);
131 g.insert_arc(n5, n6);
132
134
136}
137
139{
140 auto n1 = g.insert_node(1);
141 auto n2 = g.insert_node(2);
142 g.insert_node(3);
143
144 g.insert_arc(n1, n2);
145 // n3 is isolated
146
148
150}
151
152// =============================================================================
153// Complex Connected Structures
154// =============================================================================
155
157{
158 const size_t n = 10;
159 std::vector<Node*> nodes;
160
161 for (size_t i = 0; i < n; ++i)
162 nodes.push_back(g.insert_node(i));
163
164 // Make it complete
165 for (size_t i = 0; i < n; ++i)
166 for (size_t j = i + 1; j < n; ++j)
167 g.insert_arc(nodes[i], nodes[j]);
168
170
172}
173
175{
176 const size_t n = 10;
177 std::vector<Node*> nodes;
178
179 for (size_t i = 0; i < n; ++i)
180 nodes.push_back(g.insert_node(i));
181
182 // Create cycle
183 for (size_t i = 0; i < n; ++i)
184 g.insert_arc(nodes[i], nodes[(i + 1) % n]);
185
187
189}
190
192{
193 auto root = g.insert_node(0);
194
195 // Create binary tree
196 std::vector<Node*> current_level = {root};
197 int node_count = 1;
198
199 for (int depth = 0; depth < 4; ++depth)
200 {
201 std::vector<Node*> next_level;
202
203 for (auto parent : current_level)
204 {
205 auto left = g.insert_node(node_count++);
206 auto right = g.insert_node(node_count++);
207
208 g.insert_arc(parent, left);
209 g.insert_arc(parent, right);
210
211 next_level.push_back(left);
212 next_level.push_back(right);
213 }
214
215 current_level = next_level;
216 }
217
219
221}
222
224{
225 auto center = g.insert_node(0);
226
227 for (int i = 1; i <= 20; ++i)
228 {
229 auto leaf = g.insert_node(i);
230 g.insert_arc(center, leaf);
231 }
232
234
236}
237
238// =============================================================================
239// Arc Count Optimization Tests
240// =============================================================================
241
243{
244 const size_t n = 10;
245
246 // Insert n nodes
247 for (size_t i = 0; i < n; ++i)
248 g.insert_node(i);
249
250 // Only insert n-2 arcs (need at least n-1 for connectivity)
251 std::vector<Node*> nodes;
252 for (Node_Iterator<GT> it(g); it.has_curr(); it.next())
253 nodes.push_back(it.get_curr());
254
255 for (size_t i = 0; i < n - 2; ++i)
256 g.insert_arc(nodes[i], nodes[i + 1]);
257
259
260 // Should detect disconnection via arc count optimization
262}
263
265{
266 const size_t n = 10;
267 std::vector<Node*> nodes;
268
269 for (size_t i = 0; i < n; ++i)
270 nodes.push_back(g.insert_node(i));
271
272 // Chain with exactly n-1 arcs
273 for (size_t i = 0; i < n - 1; ++i)
274 g.insert_arc(nodes[i], nodes[i + 1]);
275
277
279}
280
282{
283 const size_t n = 10;
284 std::vector<Node*> nodes;
285
286 for (size_t i = 0; i < n; ++i)
287 nodes.push_back(g.insert_node(i));
288
289 // Create ring (n arcs)
290 for (size_t i = 0; i < n; ++i)
291 g.insert_arc(nodes[i], nodes[(i + 1) % n]);
292
294
296}
297
298// =============================================================================
299// Edge Cases
300// =============================================================================
301
303{
304 const size_t rows = 5;
305 const size_t cols = 5;
306 std::vector<std::vector<Node*>> grid(rows, std::vector<Node*>(cols));
307
308 // Create grid
309 for (size_t i = 0; i < rows; ++i)
310 for (size_t j = 0; j < cols; ++j)
311 grid[i][j] = g.insert_node(i * cols + j);
312
313 // Connect horizontally
314 for (size_t i = 0; i < rows; ++i)
315 for (size_t j = 0; j < cols - 1; ++j)
316 g.insert_arc(grid[i][j], grid[i][j + 1]);
317
318 // Connect vertically
319 for (size_t i = 0; i < rows - 1; ++i)
320 for (size_t j = 0; j < cols; ++j)
321 g.insert_arc(grid[i][j], grid[i + 1][j]);
322
324
326}
327
329{
330 auto n1 = g.insert_node(1);
331 auto n2 = g.insert_node(2);
332 auto n3 = g.insert_node(3);
333 auto n4 = g.insert_node(4);
334
335 // Diamond: n1 -> n2, n3 -> n4
336 // n2, n3 both connect to n4
337 g.insert_arc(n1, n2);
338 g.insert_arc(n1, n3);
339 g.insert_arc(n2, n4);
340 g.insert_arc(n3, n4);
341
343
345}
346
348{
349 // Two triangles connected by a bridge
350 auto n1 = g.insert_node(1);
351 auto n2 = g.insert_node(2);
352 auto n3 = g.insert_node(3);
353 auto n4 = g.insert_node(4);
354 auto n5 = g.insert_node(5);
355 auto n6 = g.insert_node(6);
356
357 // Triangle 1
358 g.insert_arc(n1, n2);
359 g.insert_arc(n2, n3);
360 g.insert_arc(n3, n1);
361
362 // Bridge
363 g.insert_arc(n3, n4);
364
365 // Triangle 2
366 g.insert_arc(n4, n5);
367 g.insert_arc(n5, n6);
368 g.insert_arc(n6, n4);
369
371
373}
374
375// =============================================================================
376// Stress Tests
377// =============================================================================
378
380{
381 const size_t n = 500;
382 std::vector<Node*> nodes;
383
384 for (size_t i = 0; i < n; ++i)
385 nodes.push_back(g.insert_node(i));
386
387 // Create chain
388 for (size_t i = 0; i < n - 1; ++i)
389 g.insert_arc(nodes[i], nodes[i + 1]);
390
392
394}
395
397{
398 const size_t n = 500;
399 std::vector<Node*> nodes;
400
401 for (size_t i = 0; i < n; ++i)
402 nodes.push_back(g.insert_node(i));
403
404 // Create chain but leave last node disconnected
405 for (size_t i = 0; i < n - 2; ++i)
406 g.insert_arc(nodes[i], nodes[i + 1]);
407
409
411}
412
413// =============================================================================
414// Multiple Calls Tests
415// =============================================================================
416
418{
419 auto n1 = g.insert_node(1);
420 auto n2 = g.insert_node(2);
421 g.insert_arc(n1, n2);
422
424
426 EXPECT_TRUE(checker(g)); // Second call should work
427 EXPECT_TRUE(checker(g)); // Third call should work
428}
429
431{
432 auto n1 = g.insert_node(1);
433 auto n2 = g.insert_node(2);
434
436
437 EXPECT_FALSE(checker(g)); // Disconnected
438
439 g.insert_arc(n1, n2);
440
441 EXPECT_TRUE(checker(g)); // Now connected
442}
443
444// =============================================================================
445// Specific Structure Tests
446// =============================================================================
447
449{
450 const size_t n = 20;
451 std::vector<Node*> nodes;
452
453 for (size_t i = 0; i < n; ++i)
454 nodes.push_back(g.insert_node(i));
455
456 for (size_t i = 0; i < n - 1; ++i)
457 g.insert_arc(nodes[i], nodes[i + 1]);
458
460
462}
463
465{
466 auto center = g.insert_node(0);
467 const size_t n = 10;
468 std::vector<Node*> rim;
469
470 for (size_t i = 0; i < n; ++i)
471 rim.push_back(g.insert_node(i + 1));
472
473 // Connect center to all rim nodes
474 for (auto node : rim)
475 g.insert_arc(center, node);
476
477 // Connect rim nodes in a cycle
478 for (size_t i = 0; i < n; ++i)
479 g.insert_arc(rim[i], rim[(i + 1) % n]);
480
482
484}
485
487{
488 // Two complete graphs connected by a path
489 const size_t k1_size = 5;
490 const size_t k2_size = 5;
491
492 std::vector<Node*> k1_nodes, k2_nodes;
493
494 // Create first complete graph
495 for (size_t i = 0; i < k1_size; ++i)
496 k1_nodes.push_back(g.insert_node(i));
497
498 for (size_t i = 0; i < k1_size; ++i)
499 for (size_t j = i + 1; j < k1_size; ++j)
500 g.insert_arc(k1_nodes[i], k1_nodes[j]);
501
502 // Create second complete graph
503 for (size_t i = 0; i < k2_size; ++i)
504 k2_nodes.push_back(g.insert_node(k1_size + i));
505
506 for (size_t i = 0; i < k2_size; ++i)
507 for (size_t j = i + 1; j < k2_size; ++j)
508 g.insert_arc(k2_nodes[i], k2_nodes[j]);
509
510 // Connect them with a bridge
511 g.insert_arc(k1_nodes[0], k2_nodes[0]);
512
514
516}
517
518// =============================================================================
519// Custom Arc Filter Tests
520// =============================================================================
521
523{
524 auto n1 = g.insert_node(1);
525 auto n2 = g.insert_node(2);
526 auto n3 = g.insert_node(3);
527
528 g.insert_arc(n1, n2);
529 g.insert_arc(n2, n3);
530
533
535}
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
void next()
Advances the iterator to the next filtered element.
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
Determines if a graph g is connected.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4060
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
TEST_F(TestConnectivityTest, EmptyGraphIsConnected)
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
Generic graph and digraph implementations.
Graph connectivity testing.