Line data Source code
1 : /**
2 : * Unit tests for the Linear Algebra module's Linear Systems class
3 : */
4 : #include <cmath>
5 : #include <cstdint>
6 : #include <cstdlib>
7 : #include <gtest/gtest.h>
8 : #include <iostream>
9 : #include <openGPMP/linalg/linsys.hpp>
10 : #include <stdexcept>
11 : #include <utility>
12 : #include <vector>
13 :
14 : const double TOLERANCE = 1e-3;
15 :
16 4 : TEST(LinSysTest, SolveGauss) {
17 : std::vector<std::vector<double>> square_mat = {{3.0, 2.0, -4.0, 3.0},
18 : {2.0, 3.0, 3.0, 15.0},
19 6 : {5.0, -3, 1.0, 14.0}};
20 1 : gpmp::linalg::LinSys linSysSquare(square_mat);
21 :
22 : // execute solve_gauss method
23 1 : std::vector<double> solution = linSysSquare.solve_gauss();
24 :
25 : // expected solution for the test matrix
26 1 : std::vector<double> expected_sol = {3, 1, 2};
27 :
28 : // assert solution vector
29 1 : ASSERT_EQ(solution.size(), expected_sol.size());
30 :
31 4 : for (int i = 0; i < solution.size(); i++) {
32 3 : ASSERT_NEAR(solution[i], expected_sol[i], TOLERANCE);
33 : }
34 1 : }
35 :
36 4 : TEST(LinSysTest, DeterminantTest) {
37 : /*std::vector<std::vector<double>> square_mat = {
38 : {3.0, 2.0, -4.0, 3.0},
39 : {2.0, 3.0, 3.0, 15.0},
40 : {5.0, -3.0, 1.0, 14.0},
41 : {1.0, 1.0, 1.0, 6.0}};
42 : */
43 :
44 5 : std::vector<std::vector<double>> square_mat = {{2, 1}, {5, 3}};
45 1 : gpmp::linalg::LinSys linSysSquare(square_mat);
46 :
47 1 : double det = linSysSquare.determinant();
48 :
49 1 : double expectedDet = 1;
50 :
51 1 : ASSERT_DOUBLE_EQ(expectedDet, det);
52 1 : }
53 :
54 4 : TEST(LinSysTest, DeterminantTestB) {
55 : std::vector<std::vector<double>> square_mat = {{4, 4, 3, 1},
56 : {2, 8, 8, 6},
57 : {4, 3, 2, 2},
58 7 : {4, 1, 5, 6}};
59 :
60 1 : gpmp::linalg::LinSys linSysSquare(square_mat);
61 :
62 1 : double det = linSysSquare.determinant();
63 :
64 1 : double expectedDet = -226;
65 :
66 1 : ASSERT_DOUBLE_EQ(expectedDet, det);
67 1 : }
68 :
69 4 : TEST(LinSysTest, LUDecompositionTest) {
70 : // Define a square matrix
71 : std::vector<std::vector<double>> square_mat = {{3.0, 2.0, -4.0, 3.0},
72 : {2.0, 3.0, 3.0, 15.0},
73 : {5.0, -3.0, 1.0, 14.0},
74 7 : {1.0, 1.0, 1.0, 6.0}};
75 :
76 : // expected lower
77 : std::vector<std::vector<double>> L = {{1, 0, 0, 0},
78 : {0.666667, 1, 0, 0},
79 : {1.66667, -3.8, 1, 0},
80 7 : {0.333333, 0.2, 0.0410959, 1}};
81 :
82 : // expected upper
83 : std::vector<std::vector<double>> U = {{3, 2, -4, 3},
84 : {0, 1.66667, 5.66667, 13},
85 : {0, 0, 29.2, 58.4},
86 7 : {0, 0, 0, 0}};
87 :
88 : // Create a LinSys object
89 1 : gpmp::linalg::LinSys linSysSquare(square_mat);
90 :
91 : // execute LU decomposition
92 1 : auto LU_mtx = linSysSquare.lu_decomp();
93 :
94 : // Check the dimensions of L and U
95 1 : ASSERT_EQ(LU_mtx.first.size(), L.size());
96 1 : ASSERT_EQ(LU_mtx.second.size(), U.size());
97 :
98 : // Check each element of L and U against the expected values
99 5 : for (uint32_t i = 0; i < LU_mtx.first.size(); i++) {
100 20 : for (uint32_t j = 0; j < LU_mtx.first[i].size(); j++) {
101 16 : ASSERT_NEAR(LU_mtx.first[i][j], L[i][j], TOLERANCE);
102 16 : ASSERT_NEAR(LU_mtx.second[i][j], U[i][j], TOLERANCE);
103 : }
104 : }
105 1 : }
106 :
107 4 : TEST(LinSysTest, IsSymmetric) {
108 : // symmetric positive-definite matrix
109 : std::vector<std::vector<double>> symmetric_mat = {{4.0, 1.0, 2.0},
110 : {1.0, 5.0, 3.0},
111 6 : {2.0, 3.0, 6.0}};
112 1 : gpmp::linalg::LinSys linSysSymmetric(symmetric_mat);
113 :
114 1 : EXPECT_TRUE(linSysSymmetric.is_symmetric());
115 :
116 : // non-symmetric matrix
117 : std::vector<std::vector<double>> nonSymmetric_mat = {{1.0, 2.0, 3.0},
118 : {2.0, 4.0, 5.0},
119 7 : {3.0, 5.0, 6.0}};
120 2 : gpmp::linalg::LinSys linSysNonSymmetric(nonSymmetric_mat);
121 :
122 1 : EXPECT_FALSE(linSysNonSymmetric.is_symmetric());
123 1 : }
124 :
125 4 : TEST(LinSysTest, FrobeniusNorm) {
126 : std::vector<std::vector<double>> test_mat = {{1.0, 2.0, 3.0},
127 : {4.0, 5.0, 6.0},
128 6 : {7.0, 8.0, 9.0}};
129 1 : gpmp::linalg::LinSys linSys(test_mat);
130 :
131 : // expected Frobenius norm for the test matrix
132 1 : double expected_norm = std::sqrt(1 * 1 + 2 * 2 + 3 * 3 + 4 * 4 + 5 * 5 +
133 : 6 * 6 + 7 * 7 + 8 * 8 + 9 * 9);
134 :
135 1 : EXPECT_DOUBLE_EQ(linSys.frobenius_norm(), expected_norm);
136 1 : }
137 :
138 4 : TEST(LinSysTest, OneNorm) {
139 : std::vector<std::vector<double>> testMat = {{1.0, 2.0, 3.0},
140 : {4.0, 5.0, 6.0},
141 6 : {7.0, 8.0, 9.0}};
142 1 : gpmp::linalg::LinSys linSys(testMat);
143 :
144 : // expected 1-norm for the test matrix
145 1 : double expectedNorm = 18;
146 :
147 1 : EXPECT_DOUBLE_EQ(linSys.one_norm(), expectedNorm);
148 1 : }
149 :
150 4 : TEST(LinSysTest, InfNorm) {
151 : std::vector<std::vector<double>> testMat = {{1.0, 2.0, 3.0},
152 : {4.0, 5.0, 6.0},
153 6 : {7.0, 8.0, 9.0}};
154 1 : gpmp::linalg::LinSys linSys(testMat);
155 :
156 1 : double expectedNorm = 24;
157 :
158 1 : EXPECT_DOUBLE_EQ(linSys.inf_norm(), expectedNorm);
159 1 : }
160 :
161 4 : TEST(LinSysTest, DiagonallyDominant) {
162 : // diagonally dominant matrix
163 : std::vector<std::vector<double>> diagonallyDominantMat = {{4.0, -1.0, 0.0},
164 : {-1.0, 4.0, -1.0},
165 6 : {0.0, -1.0, 3.0}};
166 1 : gpmp::linalg::LinSys LinSysA(diagonallyDominantMat);
167 :
168 1 : EXPECT_TRUE(LinSysA.diagonally_dominant());
169 :
170 : // non-diagonally dominant matrix
171 : std::vector<std::vector<double>> nonDiagonallyDominantMat = {
172 : {1.0, 2.0, 3.0},
173 : {4.0, 5.0, 6.0},
174 7 : {7.0, 8.0, 9.0}};
175 2 : gpmp::linalg::LinSys LinSysB(nonDiagonallyDominantMat);
176 :
177 1 : EXPECT_FALSE(LinSysB.diagonally_dominant());
178 1 : }
179 :
180 4 : TEST(LinSysTest, IsConsistent) {
181 : // create a consistent system
182 : std::vector<std::vector<double>> consistentMat = {{1.0, 2.0, 3.0},
183 : {4.0, 5.0, 6.0},
184 6 : {7.0, 8.0, 9.0}};
185 1 : gpmp::linalg::LinSys linSysConsistent(consistentMat);
186 :
187 1 : EXPECT_TRUE(linSysConsistent.is_consistent());
188 :
189 : // create an inconsistent system
190 : std::vector<std::vector<double>> inconsistentMat = {{0.0, 0.0, 0.0, 1.0},
191 : {0.0, 0.0, 0.0, 2.0},
192 7 : {0.0, 0.0, 0.0, 3.0}};
193 2 : gpmp::linalg::LinSys linSysInconsistent(inconsistentMat);
194 :
195 : // check if the system is inconsistent
196 1 : EXPECT_FALSE(linSysInconsistent.is_consistent());
197 1 : }
198 :
199 4 : TEST(LinSysTest, IsHomogeneous) {
200 : // create a homogeneous system
201 : std::vector<std::vector<double>> homogeneousMat = {{1.0, 2.0, 3.0, 0.0},
202 : {4.0, 5.0, 6.0, 0.0},
203 6 : {7.0, 8.0, 9.0, 0.0}};
204 1 : gpmp::linalg::LinSys LinSysA(homogeneousMat);
205 :
206 1 : EXPECT_TRUE(LinSysA.is_homogeneous());
207 :
208 : // create a non-homogeneous system
209 : std::vector<std::vector<double>> nonHomogeneousMat = {{1.0, 2.0, 3.0, 1.0},
210 : {4.0, 5.0, 6.0, 2.0},
211 7 : {7.0, 8.0, 9.0, 3.0}};
212 2 : gpmp::linalg::LinSys LinSysB(nonHomogeneousMat);
213 :
214 1 : EXPECT_FALSE(LinSysB.is_homogeneous());
215 1 : }
|