v2.0.0
Loading...
Searching...
No Matches
linalg.cpp
Go to the documentation of this file.
1//=============================================================================================================
27
28//=============================================================================================================
29// INCLUDES
30//=============================================================================================================
31
32#include "linalg.h"
33
34//=============================================================================================================
35// EIGEN INCLUDES
36//=============================================================================================================
37
38#include <Eigen/Eigen>
39
40//=============================================================================================================
41// QT INCLUDES
42//=============================================================================================================
43
44#include <QDebug>
45
46//=============================================================================================================
47// USED NAMESPACES
48//=============================================================================================================
49
50using namespace UTILSLIB;
51using namespace Eigen;
52
53//=============================================================================================================
54// DEFINE MEMBER METHODS
55//=============================================================================================================
56
57VectorXd Linalg::combine_xyz(const VectorXd& vec)
58{
59 if (vec.size() % 3 != 0) {
60 qWarning("Linalg::combine_xyz: Input must be a row or column vector with 3N components.");
61 return VectorXd();
62 }
63
64 MatrixXd tmp = MatrixXd(vec.transpose());
65 SparseMatrix<double> s = make_block_diag(tmp, 3);
66
67 SparseMatrix<double> sC = s * s.transpose();
68 VectorXd comb(sC.rows());
69
70 for (qint32 i = 0; i < sC.rows(); ++i)
71 comb[i] = sC.coeff(i, i);
72
73 return comb;
74}
75
76//=============================================================================================================
77
78double Linalg::getConditionNumber(const MatrixXd& A,
79 VectorXd& s)
80{
81 JacobiSVD<MatrixXd> svd(A);
82 s = svd.singularValues();
83
84 double c = s.maxCoeff() / s.minCoeff();
85
86 return c;
87}
88
89//=============================================================================================================
90
91double Linalg::getConditionSlope(const MatrixXd& A,
92 VectorXd& s)
93{
94 JacobiSVD<MatrixXd> svd(A);
95 s = svd.singularValues();
96
97 double c = s.maxCoeff() / s.mean();
98
99 return c;
100}
101
102//=============================================================================================================
103
104void Linalg::get_whitener(MatrixXd& A,
105 bool pca,
106 QString ch_type,
107 VectorXd& eig,
108 MatrixXd& eigvec)
109{
110 SelfAdjointEigenSolver<MatrixXd> t_eigenSolver(A);
111
112 eig = t_eigenSolver.eigenvalues();
113 eigvec = t_eigenSolver.eigenvectors().transpose();
114
115 Linalg::sort<double>(eig, eigvec, false);
116 qint32 rnk = Linalg::rank(A);
117
118 for (qint32 i = 0; i < eig.size() - rnk; ++i)
119 eig(i) = 0;
120
121 qInfo("Setting small %s eigenvalues to zero.", ch_type.toUtf8().constData());
122 if (!pca)
123 qInfo("Not doing PCA for %s", ch_type.toUtf8().constData());
124 else {
125 qInfo("Doing PCA for %s.", ch_type.toUtf8().constData());
126 eigvec = eigvec.bottomRows(rnk).eval(); // eval: resizing eigvec frees the rows being read
127 }
128}
129
130//=============================================================================================================
131
132void Linalg::get_whitener(MatrixXd& A,
133 bool pca,
134 const std::string& ch_type,
135 VectorXd& eig,
136 MatrixXd& eigvec)
137{
138 SelfAdjointEigenSolver<MatrixXd> t_eigenSolver(A);
139
140 eig = t_eigenSolver.eigenvalues();
141 eigvec = t_eigenSolver.eigenvectors().transpose();
142
143 Linalg::sort<double>(eig, eigvec, false);
144 qint32 rnk = Linalg::rank(A);
145
146 for (qint32 i = 0; i < eig.size() - rnk; ++i)
147 eig(i) = 0;
148
149 qInfo("Setting small %s eigenvalues to zero.", ch_type.c_str());
150 if (!pca)
151 qInfo("Not doing PCA for %s", ch_type.c_str());
152 else {
153 qInfo("Doing PCA for %s.", ch_type.c_str());
154 eigvec = eigvec.bottomRows(rnk).eval(); // eval: resizing eigvec frees the rows being read
155 }
156}
157
158//=============================================================================================================
159
160VectorXi Linalg::intersect(const VectorXi& v1,
161 const VectorXi& v2,
162 VectorXi& idx_sel)
163{
164 std::vector<int> tmp;
165
166 std::vector<std::pair<int, int>> t_vecIntIdxValue;
167
168 for (qint32 i = 0; i < v1.size(); ++i)
169 tmp.push_back(v1[i]);
170
171 std::vector<int>::iterator it;
172 for (qint32 i = 0; i < v2.size(); ++i) {
173 it = std::search(tmp.begin(), tmp.end(), &v2[i], &v2[i] + 1);
174 if (it != tmp.end())
175 t_vecIntIdxValue.push_back(std::pair<int, int>(v2[i], it - tmp.begin()));
176 }
177
178 std::sort(t_vecIntIdxValue.begin(), t_vecIntIdxValue.end(), Linalg::compareIdxValuePairSmallerThan<int>);
179
180 VectorXi p_res(t_vecIntIdxValue.size());
181 idx_sel = VectorXi(t_vecIntIdxValue.size());
182
183 for (quint32 i = 0; i < t_vecIntIdxValue.size(); ++i) {
184 p_res[i] = t_vecIntIdxValue[i].first;
185 idx_sel[i] = t_vecIntIdxValue[i].second;
186 }
187
188 return p_res;
189}
190
191//=============================================================================================================
192
193SparseMatrix<double> Linalg::make_block_diag(const MatrixXd& A,
194 qint32 n)
195{
196 qint32 ma = A.rows();
197 qint32 na = A.cols();
198 float bdn = static_cast<float>(na) / n;
199
200 if (bdn - std::floor(bdn)) {
201 qWarning("Linalg::make_block_diag: Width of matrix must be an even multiple of n.");
202 return SparseMatrix<double>();
203 }
204
205 typedef Eigen::Triplet<double> T;
206 std::vector<T> tripletList;
207 tripletList.reserve(static_cast<size_t>(bdn * ma * n));
208
209 for (qint32 i = 0; i < static_cast<qint32>(bdn); ++i) {
210 qint32 current_col = i * n;
211 qint32 current_row = i * ma;
212
213 for (qint32 r = 0; r < ma; ++r)
214 for (qint32 c = 0; c < n; ++c)
215 tripletList.push_back(T(r + current_row, c + current_col, A(r, c + current_col)));
216 }
217
218 SparseMatrix<double> bd(static_cast<int>(std::floor(ma * bdn + 0.5f)), na);
219 bd.setFromTriplets(tripletList.begin(), tripletList.end());
220
221 return bd;
222}
223
224//=============================================================================================================
225
226qint32 Linalg::rank(const MatrixXd& A,
227 double tol)
228{
229 JacobiSVD<MatrixXd> t_svdA(A);
230 VectorXd s = t_svdA.singularValues();
231 double t_dMax = s.maxCoeff();
232 t_dMax *= tol;
233 qint32 sum = 0;
234 for (qint32 i = 0; i < s.size(); ++i)
235 sum += s[i] > t_dMax ? 1 : 0;
236 return sum;
237}
Eigen::JacobiSVD< Eigen::Matrix3f > svd(S, Eigen::ComputeFullU|Eigen::ComputeFullV)
Static linear-algebra helpers: SVD-based conditioning, block-diagonal assembly, sorted index pairs.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
static bool compareIdxValuePairSmallerThan(const std::pair< int, T > &lhs, const std::pair< int, T > &rhs)
Definition linalg.h:372
static Eigen::VectorXd combine_xyz(const Eigen::VectorXd &vec)
Definition linalg.cpp:57
static Eigen::VectorXi sort(Eigen::Matrix< T, Eigen::Dynamic, 1 > &v, bool desc=true)
Definition linalg.h:298
static qint32 rank(const Eigen::MatrixXd &A, double tol=1e-8)
Definition linalg.cpp:226
static void get_whitener(Eigen::MatrixXd &A, bool pca, QString ch_type, Eigen::VectorXd &eig, Eigen::MatrixXd &eigvec)
static Eigen::VectorXi intersect(const Eigen::VectorXi &v1, const Eigen::VectorXi &v2, Eigen::VectorXi &idx_sel)
Definition linalg.cpp:160
static double getConditionNumber(const Eigen::MatrixXd &A, Eigen::VectorXd &s)
Definition linalg.cpp:78
static double getConditionSlope(const Eigen::MatrixXd &A, Eigen::VectorXd &s)
Definition linalg.cpp:91
static Eigen::SparseMatrix< double > make_block_diag(const Eigen::MatrixXd &A, qint32 n)
Definition linalg.cpp:193