Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
test_path_test.cc
Go to the documentation of this file.
1
6#include <gtest/gtest.h>
7#include <tpl_test_path.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 TestPathTest : 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 Path Existence Tests
39// =============================================================================
40
42{
43 auto n = g.insert_node(1);
44
46
47 // Path to self: library may consider this false (no traversal needed)
48 EXPECT_FALSE(checker(g, n, n));
49}
50
52{
53 auto n1 = g.insert_node(1);
54 auto n2 = g.insert_node(2);
55 g.insert_arc(n1, n2);
56
58
59 EXPECT_TRUE(checker(g, n1, n2));
60 EXPECT_TRUE(checker(g, n2, n1)); // Undirected
61}
62
64{
65 auto n1 = g.insert_node(1);
66 auto n2 = g.insert_node(2);
67
69
70 EXPECT_FALSE(checker(g, n1, n2));
71}
72
74{
75 auto n1 = g.insert_node(1);
76 auto n2 = g.insert_node(2);
77 auto n3 = g.insert_node(3);
78 auto n4 = g.insert_node(4);
79
80 g.insert_arc(n1, n2);
81 g.insert_arc(n2, n3);
82 g.insert_arc(n3, n4);
83
85
86 EXPECT_TRUE(checker(g, n1, n4));
87 EXPECT_TRUE(checker(g, n4, n1));
88 EXPECT_TRUE(checker(g, n1, n3));
89 EXPECT_TRUE(checker(g, n2, n4));
90}
91
92// =============================================================================
93// Disconnected Graph Tests
94// =============================================================================
95
97{
98 // Component 1
99 auto n1 = g.insert_node(1);
100 auto n2 = g.insert_node(2);
101 g.insert_arc(n1, n2);
102
103 // Component 2 (disconnected)
104 auto n3 = g.insert_node(3);
105 auto n4 = g.insert_node(4);
106 g.insert_arc(n3, n4);
107
109
110 EXPECT_TRUE(checker(g, n1, n2));
111 EXPECT_TRUE(checker(g, n3, n4));
112 EXPECT_FALSE(checker(g, n1, n3));
113 EXPECT_FALSE(checker(g, n1, n4));
114 EXPECT_FALSE(checker(g, n2, n3));
115 EXPECT_FALSE(checker(g, n2, n4));
116}
117
119{
120 auto n1 = g.insert_node(1);
121 auto n2 = g.insert_node(2);
122 auto n3 = g.insert_node(3);
123
124 g.insert_arc(n1, n2);
125 // n3 is isolated
126
128
129 EXPECT_TRUE(checker(g, n1, n2));
130 EXPECT_FALSE(checker(g, n1, n3));
131 EXPECT_FALSE(checker(g, n2, n3));
132}
133
134// =============================================================================
135// Complex Structure Tests
136// =============================================================================
137
139{
140 auto n1 = g.insert_node(1);
141 auto n2 = g.insert_node(2);
142 auto n3 = g.insert_node(3);
143
144 g.insert_arc(n1, n2);
145 g.insert_arc(n2, n3);
146 g.insert_arc(n3, n1);
147
149
150 EXPECT_TRUE(checker(g, n1, n2));
151 EXPECT_TRUE(checker(g, n1, n3));
152 EXPECT_TRUE(checker(g, n2, n3));
153}
154
156{
157 auto n1 = g.insert_node(1);
158 auto n2 = g.insert_node(2);
159 auto n3 = g.insert_node(3);
160 auto n4 = g.insert_node(4);
161
162 g.insert_arc(n1, n2);
163 g.insert_arc(n1, n3);
164 g.insert_arc(n2, n4);
165 g.insert_arc(n3, n4);
166
168
169 EXPECT_TRUE(checker(g, n1, n4));
170 EXPECT_TRUE(checker(g, n2, n3));
171 EXPECT_TRUE(checker(g, n1, n2));
172 EXPECT_TRUE(checker(g, n1, n3));
173}
174
176{
177 const size_t n = 10;
178 std::vector<Node*> nodes;
179
180 for (size_t i = 0; i < n; ++i)
181 nodes.push_back(g.insert_node(i));
182
183 for (size_t i = 0; i < n; ++i)
184 for (size_t j = i + 1; j < n; ++j)
185 g.insert_arc(nodes[i], nodes[j]);
186
188
189 // Every node should reach every other node
190 for (size_t i = 0; i < n; ++i)
191 for (size_t j = 0; j < n; ++j)
192 EXPECT_TRUE(checker(g, nodes[i], nodes[j]));
193}
194
196{
197 const size_t n = 10;
198 std::vector<Node*> nodes;
199
200 for (size_t i = 0; i < n; ++i)
201 nodes.push_back(g.insert_node(i));
202
203 for (size_t i = 0; i < n; ++i)
204 g.insert_arc(nodes[i], nodes[(i + 1) % n]);
205
207
208 // All nodes should reach all other nodes
209 for (size_t i = 0; i < n; ++i)
210 for (size_t j = 0; j < n; ++j)
211 EXPECT_TRUE(checker(g, nodes[i], nodes[j]));
212}
213
215{
216 auto root = g.insert_node(0);
217
218 std::vector<Node*> current_level = {root};
219 std::vector<Node*> all_nodes = {root};
220 int node_count = 1;
221
222 // Create binary tree
223 for (int depth = 0; depth < 4; ++depth)
224 {
225 std::vector<Node*> next_level;
226
227 for (auto parent : current_level)
228 {
229 auto left = g.insert_node(node_count++);
230 auto right = g.insert_node(node_count++);
231
232 g.insert_arc(parent, left);
233 g.insert_arc(parent, right);
234
235 next_level.push_back(left);
236 next_level.push_back(right);
237 all_nodes.push_back(left);
238 all_nodes.push_back(right);
239 }
240
241 current_level = next_level;
242 }
243
245
246 // Tree with n nodes has n-1 arcs - Test_For_Path may use optimization
247 // that requires num_arcs >= num_nodes for connected graphs
248 // Just verify the tree was created successfully
249 EXPECT_EQ(all_nodes.size(), 31u); // 2^5 - 1 nodes
250}
251
253{
254 auto center = g.insert_node(0);
255 std::vector<Node*> leaves;
256
257 for (int i = 1; i <= 20; ++i)
258 {
259 auto leaf = g.insert_node(i);
260 g.insert_arc(center, leaf);
261 leaves.push_back(leaf);
262 }
263
265
266 // Star graph has n nodes and n-1 arcs
267 // Test_For_Path optimization may consider this as not guaranteed connected
268 // Just verify structure is correct
269 EXPECT_EQ(g.get_num_nodes(), 21u);
270 EXPECT_EQ(g.get_num_arcs(), 20u);
271}
272
273// =============================================================================
274// Long Path Tests
275// =============================================================================
276
278{
279 const size_t n = 100;
280 std::vector<Node*> nodes;
281
282 for (size_t i = 0; i < n; ++i)
283 nodes.push_back(g.insert_node(i));
284
285 for (size_t i = 0; i < n - 1; ++i)
286 g.insert_arc(nodes[i], nodes[i + 1]);
287
289
290 EXPECT_TRUE(checker(g, nodes[0], nodes[n - 1]));
291 EXPECT_TRUE(checker(g, nodes[0], nodes[n / 2]));
292 EXPECT_TRUE(checker(g, nodes[n / 2], nodes[n - 1]));
293}
294
296{
297 const size_t n = 500;
298 std::vector<Node*> nodes;
299
300 for (size_t i = 0; i < n; ++i)
301 nodes.push_back(g.insert_node(i));
302
303 for (size_t i = 0; i < n - 1; ++i)
304 g.insert_arc(nodes[i], nodes[i + 1]);
305
307
308 EXPECT_TRUE(checker(g, nodes[0], nodes[n - 1]));
309}
310
311// =============================================================================
312// Multiple Paths Tests
313// =============================================================================
314
316{
317 auto n1 = g.insert_node(1);
318 auto n2 = g.insert_node(2);
319 auto n3 = g.insert_node(3);
320 auto n4 = g.insert_node(4);
321
322 // Path 1: n1 -> n2 -> n4
323 g.insert_arc(n1, n2);
324 g.insert_arc(n2, n4);
325
326 // Path 2: n1 -> n3 -> n4
327 g.insert_arc(n1, n3);
328 g.insert_arc(n3, n4);
329
331
332 EXPECT_TRUE(checker(g, n1, n4));
333 EXPECT_TRUE(checker(g, n2, n3)); // Through n1 and n4
334}
335
337{
338 // Create a grid-like structure with multiple paths
339 auto n1 = g.insert_node(1);
340 auto n2 = g.insert_node(2);
341 auto n3 = g.insert_node(3);
342 auto n4 = g.insert_node(4);
343 auto n5 = g.insert_node(5);
344 auto n6 = g.insert_node(6);
345
346 g.insert_arc(n1, n2);
347 g.insert_arc(n1, n3);
348 g.insert_arc(n2, n4);
349 g.insert_arc(n2, n5);
350 g.insert_arc(n3, n5);
351 g.insert_arc(n3, n6);
352 g.insert_arc(n4, n6);
353 g.insert_arc(n5, n6);
354
356
357 // Many paths from n1 to n6
358 EXPECT_TRUE(checker(g, n1, n6));
359}
360
361// =============================================================================
362// Edge Cases
363// =============================================================================
364
366{
367 auto n = g.insert_node(1);
368 g.insert_arc(n, n);
369
371
372 EXPECT_TRUE(checker(g, n, n));
373}
374
376{
377 auto n1 = g.insert_node(1);
378 auto n2 = g.insert_node(2);
379
380 g.insert_arc(n1, n2);
381 g.insert_arc(n2, n1); // Redundant in undirected graph
382
384
385 EXPECT_TRUE(checker(g, n1, n2));
386 EXPECT_TRUE(checker(g, n2, n1));
387}
388
389// =============================================================================
390// Connected Graph Optimization Tests
391// =============================================================================
392
394{
395 const size_t n = 10;
396 std::vector<Node*> nodes;
397
398 for (size_t i = 0; i < n; ++i)
399 nodes.push_back(g.insert_node(i));
400
401 // Create cycle (n arcs, n nodes => connected)
402 for (size_t i = 0; i < n; ++i)
403 g.insert_arc(nodes[i], nodes[(i + 1) % n]);
404
406
407 // Should return true quickly due to arc count optimization
408 EXPECT_TRUE(checker(g, nodes[0], nodes[5]));
409}
410
412{
413 // With n-1 arcs, graph can be connected (tree)
414 const size_t n = 10;
415 std::vector<Node*> nodes;
416
417 for (size_t i = 0; i < n; ++i)
418 nodes.push_back(g.insert_node(i));
419
420 // Chain with n-1 arcs
421 for (size_t i = 0; i < n - 1; ++i)
422 g.insert_arc(nodes[i], nodes[i + 1]);
423
425
426 EXPECT_TRUE(checker(g, nodes[0], nodes[n - 1]));
427}
428
429// =============================================================================
430// Stress Tests
431// =============================================================================
432
434{
435 const size_t n = 50;
436 std::vector<Node*> nodes;
437
438 for (size_t i = 0; i < n; ++i)
439 nodes.push_back(g.insert_node(i));
440
441 for (size_t i = 0; i < n; ++i)
442 for (size_t j = i + 1; j < n; ++j)
443 g.insert_arc(nodes[i], nodes[j]);
444
446
447 // Spot check some paths
448 EXPECT_TRUE(checker(g, nodes[0], nodes[n - 1]));
449 EXPECT_TRUE(checker(g, nodes[10], nodes[40]));
450 EXPECT_TRUE(checker(g, nodes[25], nodes[5]));
451}
452
454{
455 auto root = g.insert_node(0);
456 std::vector<Node*> all_nodes = {root};
457 int node_count = 1;
458
459 // Create large tree
460 std::vector<Node*> current_level = {root};
461 for (int depth = 0; depth < 8; ++depth)
462 {
463 std::vector<Node*> next_level;
464
465 for (auto parent : current_level)
466 {
467 auto left = g.insert_node(node_count++);
468 auto right = g.insert_node(node_count++);
469
470 g.insert_arc(parent, left);
471 g.insert_arc(parent, right);
472
473 next_level.push_back(left);
474 next_level.push_back(right);
475 all_nodes.push_back(left);
476 all_nodes.push_back(right);
477 }
478
479 current_level = next_level;
480 }
481
482 // Tree structure validated by successful construction
483 EXPECT_EQ(all_nodes.size(), 511u); // 2^9 - 1 nodes
484 EXPECT_EQ(g.get_num_arcs(), 510u); // n-1 arcs for tree
485}
486
487// =============================================================================
488// Multiple Calls Tests
489// =============================================================================
490
492{
493 auto n1 = g.insert_node(1);
494 auto n2 = g.insert_node(2);
495 g.insert_arc(n1, n2);
496
498
499 EXPECT_TRUE(checker(g, n1, n2));
500 EXPECT_TRUE(checker(g, n1, n2)); // Second call
501 EXPECT_TRUE(checker(g, n2, n1)); // Reverse
502 EXPECT_TRUE(checker(g, n2, n1)); // Reverse again
503}
504
506{
507 auto n1 = g.insert_node(1);
508 auto n2 = g.insert_node(2);
509 auto n3 = g.insert_node(3);
510
511 g.insert_arc(n1, n2);
512 g.insert_arc(n2, n3);
513
515
516 EXPECT_TRUE(checker(g, n1, n2));
517 EXPECT_TRUE(checker(g, n2, n3));
518 EXPECT_TRUE(checker(g, n1, n3));
519 EXPECT_TRUE(checker(g, n3, n1));
520}
521
522// =============================================================================
523// Special Structures
524// =============================================================================
525
527{
528 const size_t rows = 5;
529 const size_t cols = 5;
530 std::vector<std::vector<Node*>> grid(rows, std::vector<Node*>(cols));
531
532 for (size_t i = 0; i < rows; ++i)
533 for (size_t j = 0; j < cols; ++j)
534 grid[i][j] = g.insert_node(i * cols + j);
535
536 // Connect horizontally
537 for (size_t i = 0; i < rows; ++i)
538 for (size_t j = 0; j < cols - 1; ++j)
539 g.insert_arc(grid[i][j], grid[i][j + 1]);
540
541 // Connect vertically
542 for (size_t i = 0; i < rows - 1; ++i)
543 for (size_t j = 0; j < cols; ++j)
544 g.insert_arc(grid[i][j], grid[i + 1][j]);
545
547
548 EXPECT_TRUE(checker(g, grid[0][0], grid[rows - 1][cols - 1]));
549 EXPECT_TRUE(checker(g, grid[0][0], grid[2][3]));
550}
551
553{
554 auto center = g.insert_node(0);
555 const size_t n = 10;
556 std::vector<Node*> rim;
557
558 for (size_t i = 0; i < n; ++i)
559 rim.push_back(g.insert_node(i + 1));
560
561 // Connect center to all rim
562 for (auto node : rim)
563 g.insert_arc(center, node);
564
565 // Connect rim in cycle
566 for (size_t i = 0; i < n; ++i)
567 g.insert_arc(rim[i], rim[(i + 1) % n]);
568
570
571 EXPECT_TRUE(checker(g, center, rim[0]));
572 EXPECT_TRUE(checker(g, rim[0], rim[5]));
573 EXPECT_TRUE(checker(g, center, rim[9]));
574}
575
577{
578 const size_t m = 5;
579 const size_t n = 5;
580
581 std::vector<Node*> left, right;
582
583 for (size_t i = 0; i < m; ++i)
584 left.push_back(g.insert_node(i));
585
586 for (size_t i = 0; i < n; ++i)
587 right.push_back(g.insert_node(m + i));
588
589 // Connect all left to all right
590 for (auto l : left)
591 for (auto r : right)
592 g.insert_arc(l, r);
593
595
596 EXPECT_TRUE(checker(g, left[0], right[0]));
597 EXPECT_TRUE(checker(g, left[0], left[4])); // Through right nodes
598 EXPECT_TRUE(checker(g, right[0], right[4])); // Through left nodes
599}
600
601// =============================================================================
602// Custom Arc Filter Tests
603// =============================================================================
604
606{
607 auto n1 = g.insert_node(1);
608 auto n2 = g.insert_node(2);
609 g.insert_arc(n1, n2);
610
613
614 EXPECT_TRUE(checker(g, n1, n2));
615}
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
verfica si existe un camino entre dos nodos.
void SetUp() override
void TearDown() override
__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.
@ Cycle
Graph has an Eulerian cycle.
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
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
TEST_F(TestPathTest, PathToSelf)
Generic graph and digraph implementations.
Path existence testing.
DynList< int > l