Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_matgraph_test.cc
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
38#include <gtest/gtest.h>
39#include <tpl_matgraph.H>
40#include <tpl_graph.H>
41#include <limits>
42
43using namespace Aleph;
44
45// =============================================================================
46// Type Aliases
47// =============================================================================
48
49// Graph with int node attributes and int arc attributes
53
54// =============================================================================
55// Helper Functions
56// =============================================================================
57
58class MatGraphTestBase : public ::testing::Test
59{
60protected:
62 IntGraph::Node* n0 = nullptr;
63 IntGraph::Node* n1 = nullptr;
64 IntGraph::Node* n2 = nullptr;
65 IntGraph::Node* n3 = nullptr;
66
67 void SetUp() override
68 {
69 // Create a simple graph:
70 // 0 -- 1 -- 2
71 // |
72 // 3
73 n0 = g.insert_node(0);
74 n1 = g.insert_node(1);
75 n2 = g.insert_node(2);
76 n3 = g.insert_node(3);
77
78 g.insert_arc(n0, n1, 10);
79 g.insert_arc(n1, n2, 20);
80 g.insert_arc(n1, n3, 30);
81 }
82};
83
84class DigraphTestBase : public ::testing::Test
85{
86protected:
88 IntDigraph::Node* n0 = nullptr;
89 IntDigraph::Node* n1 = nullptr;
90 IntDigraph::Node* n2 = nullptr;
91
92 void SetUp() override
93 {
94 // Create a simple digraph:
95 // 0 -> 1 -> 2
96 // ^ |
97 // |____|
98 n0 = g.insert_node(0);
99 n1 = g.insert_node(1);
100 n2 = g.insert_node(2);
101
102 g.insert_arc(n0, n1, 10);
103 g.insert_arc(n1, n2, 20);
104 g.insert_arc(n2, n1, 30);
105 }
106};
107
108// =============================================================================
109// matgraph_detail Helper Tests
110// =============================================================================
111
113{
114 // Row-major indexing: i + j*n
118 EXPECT_EQ(matgraph_detail::index_array(3L, 3L, 4L), 15L);
119}
120
126
128{
129 EXPECT_THROW((void)matgraph_detail::checked_index_array(4L, 0L, 4L), std::out_of_range);
130 EXPECT_THROW((void)matgraph_detail::checked_index_array(0L, 4L, 4L), std::out_of_range);
131 EXPECT_THROW((void)matgraph_detail::checked_index_array(-1L, 0L, 4L), std::out_of_range);
132}
133
134// =============================================================================
135// Map_Matrix_Graph Tests
136// =============================================================================
137
139{
140};
141
147
149{
151
152 // Nodes are sorted by pointer, so order may vary
153 EXPECT_NE(mat(0), nullptr);
154 EXPECT_NE(mat(1), nullptr);
155 EXPECT_NE(mat(2), nullptr);
156 EXPECT_NE(mat(3), nullptr);
157}
158
160{
162
163 // Get indices and verify they're valid
164 long idx0 = mat(n0);
165 long idx1 = mat(n1);
166 long idx2 = mat(n2);
167 long idx3 = mat(n3);
168
169 EXPECT_GE(idx0, 0);
170 EXPECT_LT(idx0, 4);
171 EXPECT_GE(idx1, 0);
172 EXPECT_LT(idx1, 4);
173 EXPECT_GE(idx2, 0);
174 EXPECT_LT(idx2, 4);
175 EXPECT_GE(idx3, 0);
176 EXPECT_LT(idx3, 4);
177
178 // All indices should be unique
179 std::set<long> indices{idx0, idx1, idx2, idx3};
180 EXPECT_EQ(indices.size(), 4u);
181}
182
184{
186
187 long i0 = mat(n0);
188 long i1 = mat(n1);
189 long i2 = mat(n2);
190 long i3 = mat(n3);
191
192 // Arc between n0 and n1 should exist (undirected)
193 EXPECT_NE(mat(i0, i1), nullptr);
194 EXPECT_NE(mat(i1, i0), nullptr); // Undirected
195
196 // Arc between n1 and n2
197 EXPECT_NE(mat(i1, i2), nullptr);
198
199 // No direct arc between n0 and n2
200 EXPECT_EQ(mat(i0, i2), nullptr);
201 EXPECT_EQ(mat(i2, i0), nullptr);
202
203 // No arc between n0 and n3
204 EXPECT_EQ(mat(i0, i3), nullptr);
205}
206
208{
210
211 EXPECT_NE(mat(n0, n1), nullptr);
212 EXPECT_NE(mat(n1, n0), nullptr);
213 EXPECT_NE(mat(n1, n2), nullptr);
214 EXPECT_NE(mat(n1, n3), nullptr);
215 EXPECT_EQ(mat(n0, n2), nullptr);
216 EXPECT_EQ(mat(n0, n3), nullptr);
217}
218
224
226{
229
230 EXPECT_EQ(mat2.get_num_nodes(), mat1.get_num_nodes());
231 EXPECT_EQ(&mat2.get_list_graph(), &mat1.get_list_graph());
232}
233
235{
237 IntGraph g2;
238 g2.insert_node(100);
239 g2.insert_node(200);
241
242 mat2 = mat1;
243 EXPECT_EQ(mat2.get_num_nodes(), 4u);
244}
245
247{
249 EXPECT_THROW((void)mat(10), std::out_of_range);
250}
251
252// =============================================================================
253// Matrix_Graph Tests
254// =============================================================================
255
257{
258};
259
261{
262 Matrix_Graph<IntGraph> mat(g, -1);
263 EXPECT_EQ(mat.get_num_nodes(), 4u);
264 EXPECT_EQ(mat.null_value(), -1);
265}
266
268{
269 Matrix_Graph<IntGraph> mat(g, -1);
270
271 // Node attributes are stored by index
272 std::set<int> values;
273 for (size_t i = 0; i < 4; ++i)
274 values.insert(mat(static_cast<long>(i)));
275
276 // Should have node values 0, 1, 2, 3
277 EXPECT_TRUE(values.count(0));
278 EXPECT_TRUE(values.count(1));
279 EXPECT_TRUE(values.count(2));
280 EXPECT_TRUE(values.count(3));
281}
282
284{
285 Matrix_Graph<IntGraph> mat(g, -1);
286
287 // Find indices of nodes
288 long idx0 = -1, idx1 = -1;
289 for (size_t i = 0; i < 4; ++i)
290 {
291 if (mat(static_cast<long>(i)) == 0) idx0 = i;
292 if (mat(static_cast<long>(i)) == 1) idx1 = i;
293 }
294
295 ASSERT_NE(idx0, -1);
296 ASSERT_NE(idx1, -1);
297
298 // Arc between nodes 0 and 1 has weight 10
299 EXPECT_EQ(mat(idx0, idx1), 10);
300 EXPECT_EQ(mat(idx1, idx0), 10); // Undirected
301}
302
304{
305 Matrix_Graph<IntGraph> mat(g, -1);
306
307 long idx0 = -1, idx2 = -1;
308 for (size_t i = 0; i < 4; ++i)
309 {
310 if (mat(static_cast<long>(i)) == 0) idx0 = i;
311 if (mat(static_cast<long>(i)) == 2) idx2 = i;
312 }
313
314 EXPECT_EQ(mat(idx0, idx2), -1);
315}
316
318{
319 Matrix_Graph<IntGraph> mat(g, -1);
320
321 mat(0, 3) = 999;
322 EXPECT_EQ(mat(0, 3), 999);
323}
324
326{
329
330 EXPECT_EQ(mat2.get_num_nodes(), mat1.get_num_nodes());
331 EXPECT_EQ(mat2.null_value(), mat1.null_value());
332}
333
334// =============================================================================
335// Ady_Mat Tests
336// =============================================================================
337
339{
340};
341
347
354
356{
357 Ady_Mat<IntDigraph, int> mat(g, -1);
358
359 EXPECT_NE(mat(0), nullptr);
360 EXPECT_NE(mat(1), nullptr);
361 EXPECT_NE(mat(2), nullptr);
362}
363
365{
366 Ady_Mat<IntDigraph, int> mat(g, -1);
367
368 long i0 = mat(n0);
369 long i1 = mat(n1);
370 long i2 = mat(n2);
371
372 EXPECT_GE(i0, 0);
373 EXPECT_LT(i0, 3);
374 EXPECT_GE(i1, 0);
375 EXPECT_LT(i1, 3);
376 EXPECT_GE(i2, 0);
377 EXPECT_LT(i2, 3);
378}
379
381{
382 Ady_Mat<IntDigraph, int> mat(g, -1);
383
384 mat(0L, 1L) = 100;
385 mat(1L, 2L) = 200;
386
387 EXPECT_EQ(mat(0L, 1L), 100);
388 EXPECT_EQ(mat(1L, 2L), 200);
389}
390
392{
393 Ady_Mat<IntDigraph, int> mat(g, -1);
394
395 mat(n0, n1) = 100;
396 EXPECT_EQ(mat(n0, n1), 100);
397}
398
400{
401 Ady_Mat<IntDigraph, int> mat(g, -1);
402 mat(0L, 0L) = 42;
403
404 const Ady_Mat<IntDigraph, int>& cmat = mat;
405 EXPECT_EQ(cmat(0L, 0L), 42);
406}
407
413
415{
417 mat.set_null_value(-999);
418 EXPECT_EQ(mat.null_value(), -999);
419}
420
421// Operation functor for operate_all_arcs_list_graph
423{
425 IntDigraph::Arc* arc,
426 long i, long j,
427 int& entry)
428 {
429 (void)mat;
430 (void)i;
431 (void)j;
432 entry = arc->get_info();
433 }
434};
435
437{
438 Ady_Mat<IntDigraph, int> mat(g, -1);
440
441 // Check that arc values were copied
442 long i0 = mat(n0), i1 = mat(n1), i2 = mat(n2);
443
444 EXPECT_EQ(mat(i0, i1), 10); // Arc 0->1
445 EXPECT_EQ(mat(i1, i2), 20); // Arc 1->2
446 EXPECT_EQ(mat(i2, i1), 30); // Arc 2->1
447}
448
449// Operation functor for operate_all_arcs_matrix
451{
454 long i, long j,
455 int& entry)
456 {
457 (void)mat;
458 (void)src;
459 (void)tgt;
460 entry = i * 10 + j;
461 }
462};
463
465{
466 Ady_Mat<IntDigraph, int> mat(g, -1);
468
469 EXPECT_EQ(mat(0L, 0L), 0);
470 EXPECT_EQ(mat(0L, 1L), 1);
471 EXPECT_EQ(mat(1L, 0L), 10);
472 EXPECT_EQ(mat(2L, 2L), 22);
473}
474
475// =============================================================================
476// Bit_Mat_Graph Tests
477// =============================================================================
478
480{
481};
482
489
496
503
505{
507
508 EXPECT_NE(mat(0), nullptr);
509 EXPECT_NE(mat(1), nullptr);
510}
511
513{
515
516 long i0 = mat(n0);
517 long i1 = mat(n1);
518
519 EXPECT_GE(i0, 0);
520 EXPECT_LT(i0, 4);
521 EXPECT_GE(i1, 0);
522 EXPECT_LT(i1, 4);
523 EXPECT_NE(i0, i1);
524}
525
527{
529
530 long i0 = mat(n0), i1 = mat(n1), i2 = mat(n2), i3 = mat(n3);
531
532 // Arc between n0 and n1
533 EXPECT_EQ(static_cast<int>(mat(i0, i1)), 1);
534 EXPECT_EQ(static_cast<int>(mat(i1, i0)), 1);
535
536 // Arc between n1 and n2
537 EXPECT_EQ(static_cast<int>(mat(i1, i2)), 1);
538
539 // Arc between n1 and n3
540 EXPECT_EQ(static_cast<int>(mat(i1, i3)), 1);
541
542 // No arc between n0 and n2
543 EXPECT_EQ(static_cast<int>(mat(i0, i2)), 0);
544}
545
547{
549
550 long i0 = mat(n0), i2 = mat(n2);
551
552 EXPECT_EQ(static_cast<int>(mat(i0, i2)), 0);
553
554 mat(i0, i2) = 1;
555 EXPECT_EQ(static_cast<int>(mat(i0, i2)), 1);
556
557 mat(i0, i2) = 0;
558 EXPECT_EQ(static_cast<int>(mat(i0, i2)), 0);
559}
560
562{
564
565 EXPECT_EQ(static_cast<int>(mat(n0, n1)), 1);
566 EXPECT_EQ(static_cast<int>(mat(n0, n2)), 0);
567}
568
577
579{
582
583 EXPECT_EQ(mat2.get_num_nodes(), mat1.get_num_nodes());
584
585 long i0 = mat1(n0), i1 = mat1(n1);
586 EXPECT_EQ(static_cast<int>(mat2(i0, i1)), static_cast<int>(mat1(i0, i1)));
587}
588
597
599{
601
602 EXPECT_THROW((void)mat(0), std::domain_error);
603 EXPECT_THROW((void)mat(n0), std::domain_error);
604}
605
606// =============================================================================
607// Digraph Tests
608// =============================================================================
609
611{
612};
613
615{
617
618 long i0 = mat(n0), i1 = mat(n1), i2 = mat(n2);
619
620 // 0 -> 1 exists
621 EXPECT_NE(mat(i0, i1), nullptr);
622 // 1 -> 0 does not exist (directed)
623 EXPECT_EQ(mat(i1, i0), nullptr);
624
625 // 1 -> 2 exists
626 EXPECT_NE(mat(i1, i2), nullptr);
627 // 2 -> 1 exists
628 EXPECT_NE(mat(i2, i1), nullptr);
629}
630
632{
634
635 long i0 = mat(n0), i1 = mat(n1), i2 = mat(n2);
636
637 EXPECT_EQ(static_cast<int>(mat(i0, i1)), 1);
638 EXPECT_EQ(static_cast<int>(mat(i1, i0)), 0);
639 EXPECT_EQ(static_cast<int>(mat(i1, i2)), 1);
640 EXPECT_EQ(static_cast<int>(mat(i2, i1)), 1);
641}
642
643// =============================================================================
644// Edge Cases
645// =============================================================================
646
648{
649 IntGraph g;
650 g.insert_node(42);
651
653 EXPECT_EQ(mat.get_num_nodes(), 1u);
654 EXPECT_EQ(mat(0L, 0L), nullptr); // No self-loop
655
657 EXPECT_EQ(amat.get_num_nodes(), 1u);
658 amat(0L, 0L) = 100;
659 EXPECT_EQ(amat(0L, 0L), 100);
660}
661
663{
664 IntGraph g;
665 auto* n0 = g.insert_node(0);
666 auto* n1 = g.insert_node(1);
667 auto* n2 = g.insert_node(2);
668 (void)n0; (void)n1; (void)n2;
669 // No arcs
670
672 EXPECT_EQ(mat.get_num_nodes(), 3u);
673
674 for (long i = 0; i < 3; ++i)
675 for (long j = 0; j < 3; ++j)
676 EXPECT_EQ(mat(i, j), nullptr);
677}
678
680{
681 IntGraph g;
683 for (int i = 0; i < 4; ++i)
684 nodes[i] = g.insert_node(i);
685
686 // Add all edges
687 for (int i = 0; i < 4; ++i)
688 for (int j = i + 1; j < 4; ++j)
689 g.insert_arc(nodes[i], nodes[j], i * 10 + j);
690
692 EXPECT_EQ(mat.get_num_nodes(), 4u);
693
694 // All pairs should have arcs (undirected)
695 for (long i = 0; i < 4; ++i)
696 for (long j = 0; j < 4; ++j)
697 if (i != j)
698 EXPECT_NE(mat(i, j), nullptr);
699}
700
702{
703 IntDigraph g;
704 auto* n = g.insert_node(0);
705 g.insert_arc(n, n, 99); // Self-loop
706
708 long idx = mat(n);
709 EXPECT_NE(mat(idx, idx), nullptr);
710 EXPECT_EQ(mat(idx, idx)->get_info(), 99);
711}
712
713// =============================================================================
714// Performance / Stress Tests
715// =============================================================================
716
718{
719 constexpr int N = 100;
720
721 IntDigraph g;
722 std::vector<IntDigraph::Node*> nodes(N);
723
724 for (int i = 0; i < N; ++i)
725 nodes[i] = g.insert_node(i);
726
727 // Create chain: 0 -> 1 -> 2 -> ... -> N-1
728 for (int i = 0; i < N - 1; ++i)
729 g.insert_arc(nodes[i], nodes[i + 1], i);
730
732 EXPECT_EQ(mat.get_num_nodes(), static_cast<size_t>(N));
733
735 amat.operate_all_arcs_list_graph<InitFromArc>();
736
737 // Verify chain structure
738 for (int i = 0; i < N - 1; ++i)
739 {
740 long si = amat(nodes[i]);
741 long ti = amat(nodes[i + 1]);
742 EXPECT_EQ(amat(si, ti), i);
743 }
744}
745
746int main(int argc, char** argv)
747{
748 ::testing::InitGoogleTest(&argc, argv);
749 return RUN_ALL_TESTS();
750}
int main()
Auxiliary adjacency matrix with custom entry type.
void operate_all_arcs_list_graph()
Apply operation to all arcs from the graph.
void set_null_value(const Entry_Type &null) noexcept
Set the null value.
size_t get_num_nodes() const noexcept
Get number of nodes (matrix dimension)
void operate_all_arcs_matrix()
Apply operation to all matrix entries.
const Entry_Type & null_value() const noexcept
Get the null value.
GT & get_list_graph() noexcept
Get reference to underlying graph.
Bit matrix for graph connectivity.
size_t get_num_nodes() const noexcept
Get number of nodes (matrix dimension)
GT * get_list_graph() noexcept
Get pointer to associated graph (nullptr if none)
void set_list_graph(GT &g)
Associate with a graph.
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3848
typename BaseGraph::Arc Arc
Definition graph-dry.H:3852
typename BaseGraph::Node Node
Definition graph-dry.H:3851
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Adjacency matrix mapped to an adjacency list graph.
GT & get_list_graph() noexcept
Get reference to underlying graph.
size_t get_num_nodes() const noexcept
Get number of nodes (matrix dimension)
Adjacency matrix storing copies of graph attributes.
const Arc_Type & null_value() const noexcept
Get the null value indicating no arc.
size_t get_num_nodes() const noexcept
Get number of nodes (matrix dimension)
IntDigraph::Node * n2
IntDigraph::Node * n0
void SetUp() override
IntDigraph::Node * n1
IntGraph::Node * n2
IntGraph::Node * n3
void SetUp() override
IntGraph::Node * n1
IntGraph::Node * n0
#define TEST(name)
#define N
Definition fib.C:294
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
long index_array(long i, long j, long n) noexcept
Convert 2D matrix indices to 1D array index.
long checked_index_array(long i, long j, long n)
Validate and convert indices to linear index.
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
void operator()(Ady_Mat< IntDigraph, int > &mat, IntDigraph::Node *src, IntDigraph::Node *tgt, long i, long j, int &entry)
void operator()(Ady_Mat< IntDigraph, int > &mat, IntDigraph::Arc *arc, long i, long j, int &entry)
Generic graph and digraph implementations.
Adjacency matrix representations for graphs.
TEST_F(MapMatrixGraphTest, Constructor)