Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
test_acyclique_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 TestAcycliqueTest : 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 Acyclicity Tests
39// =============================================================================
40
42{
44
45 // Empty graph behavior: library returns false (no nodes to check)
47}
48
57
59{
60 g.insert_node(1);
61 g.insert_node(2);
62
64
66}
67
69{
70 auto n1 = g.insert_node(1);
71 auto n2 = g.insert_node(2);
72 g.insert_arc(n1, n2);
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
96{
97 auto n1 = g.insert_node(1);
98 auto n2 = g.insert_node(2);
99 auto n3 = g.insert_node(3);
100 auto n4 = g.insert_node(4);
101 auto n5 = g.insert_node(5);
102
103 // Tree structure: n1 is root, n2 and n3 are children, n4 and n5 are grandchildren
104 g.insert_arc(n1, n2);
105 g.insert_arc(n1, n3);
106 g.insert_arc(n2, n4);
107 g.insert_arc(n2, n5);
108
110
112}
113
114// =============================================================================
115// Cycle Detection Tests
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 g.insert_arc(n2, n3);
126 g.insert_arc(n3, n1); // Closes cycle
127
129
131}
132
134{
135 auto n1 = g.insert_node(1);
136 auto n2 = g.insert_node(2);
137 auto n3 = g.insert_node(3);
138 auto n4 = g.insert_node(4);
139
140 g.insert_arc(n1, n2);
141 g.insert_arc(n2, n3);
142 g.insert_arc(n3, n4);
143 g.insert_arc(n4, n1); // Closes cycle
144
146
148}
149
151{
152 auto n = g.insert_node(1);
153 g.insert_arc(n, n); // Self-loop
154
156
158}
159
161{
162 const size_t n = 100;
163 std::vector<Node*> nodes;
164
165 for (size_t i = 0; i < n; ++i)
166 nodes.push_back(g.insert_node(i));
167
168 for (size_t i = 0; i < n - 1; ++i)
169 g.insert_arc(nodes[i], nodes[i + 1]);
170
171 g.insert_arc(nodes[n - 1], nodes[0]); // Close cycle
172
174
176}
177
178// =============================================================================
179// Has_Cycle Tests
180// =============================================================================
181
183{
185
186 // Empty graph: Has_Cycle returns true (inverse of Is_Graph_Acyclique)
188}
189
191{
192 auto n1 = g.insert_node(1);
193 auto n2 = g.insert_node(2);
194 auto n3 = g.insert_node(3);
195
196 g.insert_arc(n1, n2);
197 g.insert_arc(n2, n3);
198
200
202}
203
205{
206 auto n1 = g.insert_node(1);
207 auto n2 = g.insert_node(2);
208 auto n3 = g.insert_node(3);
209
210 g.insert_arc(n1, n2);
211 g.insert_arc(n2, n3);
212 g.insert_arc(n3, n1);
213
215
217}
218
220{
221 // Component 1: acyclic
222 auto n1 = g.insert_node(1);
223 auto n2 = g.insert_node(2);
224 g.insert_arc(n1, n2);
225
226 // Component 2: has cycle
227 auto n3 = g.insert_node(3);
228 auto n4 = g.insert_node(4);
229 auto n5 = g.insert_node(5);
230 g.insert_arc(n3, n4);
231 g.insert_arc(n4, n5);
232 g.insert_arc(n5, n3);
233
235
237}
238
239// =============================================================================
240// Complex Structure Tests
241// =============================================================================
242
244{
245 // Create a complex undirected graph without cycles (tree structure)
246 auto n1 = g.insert_node(1);
247 auto n2 = g.insert_node(2);
248 auto n3 = g.insert_node(3);
249 auto n4 = g.insert_node(4);
250 auto n5 = g.insert_node(5);
251 auto n6 = g.insert_node(6);
252
253 // Tree: no multiple paths between nodes
254 g.insert_arc(n1, n2);
255 g.insert_arc(n1, n3);
256 g.insert_arc(n2, n4);
257 g.insert_arc(n2, n5);
258 g.insert_arc(n3, n6);
259
261
263}
264
266{
267 auto n1 = g.insert_node(1);
268 auto n2 = g.insert_node(2);
269 auto n3 = g.insert_node(3);
270 auto n4 = g.insert_node(4);
271
272 // Diamond structure
273 g.insert_arc(n1, n2);
274 g.insert_arc(n1, n3);
275 g.insert_arc(n2, n4);
276 g.insert_arc(n3, n4);
277
278 // Add back edge to create cycle
279 g.insert_arc(n4, n1);
280
282
284}
285
286// =============================================================================
287// Disconnected Components Tests
288// =============================================================================
289
291{
292 // Component 1
293 auto n1 = g.insert_node(1);
294 auto n2 = g.insert_node(2);
295 g.insert_arc(n1, n2);
296
297 // Component 2
298 auto n3 = g.insert_node(3);
299 auto n4 = g.insert_node(4);
300 g.insert_arc(n3, n4);
301
303
305}
306
308{
309 // Acyclic component
310 auto n1 = g.insert_node(1);
311 auto n2 = g.insert_node(2);
312 g.insert_arc(n1, n2);
313
314 // Cyclic component
315 auto n3 = g.insert_node(3);
316 auto n4 = g.insert_node(4);
317 auto n5 = g.insert_node(5);
318 g.insert_arc(n3, n4);
319 g.insert_arc(n4, n5);
320 g.insert_arc(n5, n3);
321
323
325}
326
327// =============================================================================
328// Edge Cases
329// =============================================================================
330
332{
333 auto n1 = g.insert_node(1);
334 auto n2 = g.insert_node(2);
335
336 g.insert_arc(n1, n2);
337 g.insert_arc(n2, n1); // Creates cycle
338
340
342}
343
345{
346 auto center = g.insert_node(0);
347
348 for (int i = 1; i <= 10; ++i)
349 {
350 auto leaf = g.insert_node(i);
351 g.insert_arc(center, leaf);
352 }
353
355
357}
358
359// =============================================================================
360// Num Arcs Parameter Tests
361// =============================================================================
362
364{
365 auto n1 = g.insert_node(1);
366 auto n2 = g.insert_node(2);
367 auto n3 = g.insert_node(3);
368
369 g.insert_arc(n1, n2);
370 g.insert_arc(n2, n3);
371
373
374 EXPECT_TRUE(checker(g, 2)); // Explicit arc count
375}
376
378{
379 auto n1 = g.insert_node(1);
380 auto n2 = g.insert_node(2);
381 auto n3 = g.insert_node(3);
382
383 g.insert_arc(n1, n2);
384 g.insert_arc(n2, n3);
385 g.insert_arc(n3, n1);
386
388
389 EXPECT_FALSE(checker(g, 3));
390}
391
393{
394 auto n1 = g.insert_node(1);
395 auto n2 = g.insert_node(2);
396
397 g.insert_arc(n1, n2);
398 g.insert_arc(n2, n1);
399
401
402 EXPECT_TRUE(checker(g, 2));
403}
404
405// =============================================================================
406// Stress Tests
407// =============================================================================
408
410{
411 const size_t n = 500;
412 std::vector<Node*> nodes;
413
414 for (size_t i = 0; i < n; ++i)
415 nodes.push_back(g.insert_node(i));
416
417 for (size_t i = 0; i < n - 1; ++i)
418 g.insert_arc(nodes[i], nodes[i + 1]);
419
421
423}
424
426{
427 auto root = g.insert_node(0);
428 int node_count = 1;
429
430 // Create binary tree with 127 nodes (depth 7)
431 std::vector<Node*> current_level = {root};
432
433 for (int depth = 0; depth < 6; ++depth)
434 {
435 std::vector<Node*> next_level;
436
437 for (auto parent : current_level)
438 {
439 auto left = g.insert_node(node_count++);
440 auto right = g.insert_node(node_count++);
441
442 g.insert_arc(parent, left);
443 g.insert_arc(parent, right);
444
445 next_level.push_back(left);
446 next_level.push_back(right);
447 }
448
449 current_level = next_level;
450 }
451
453
455}
456
457// =============================================================================
458// Arc Count Optimization Tests
459// =============================================================================
460
462{
463 const size_t n = 10;
464 std::vector<Node*> nodes;
465
466 for (size_t i = 0; i < n; ++i)
467 nodes.push_back(g.insert_node(i));
468
469 // Add n or more arcs => must have cycle
470 for (size_t i = 0; i < n; ++i)
471 g.insert_arc(nodes[i], nodes[(i + 1) % n]);
472
474
475 // Should detect cycle via arc count optimization
477}
478
480{
481 const size_t n = 10;
482 std::vector<Node*> nodes;
483
484 for (size_t i = 0; i < n; ++i)
485 nodes.push_back(g.insert_node(i));
486
487 // Add exactly n-1 arcs (tree)
488 for (size_t i = 0; i < n - 1; ++i)
489 g.insert_arc(nodes[i], nodes[i + 1]);
490
492
494}
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
Determines whether a graph contains cycles.
Determines whether a graph is acyclic (contains no cycles).
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
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
DynList< T > maps(const C &c, Op op)
Classic map operation.
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(TestAcycliqueTest, EmptyGraphIsAcyclic)
Generic graph and digraph implementations.
DAG (acyclic) graph testing.