Skip to content

Commit 09c4541

Browse files
atrayeesTolisChal
authored andcommitted
Feature/spectra correlations (GeomScale#306)
1 parent 2b73691 commit 09c4541

File tree

2 files changed

+88
-17
lines changed

2 files changed

+88
-17
lines changed

examples/correlation_matrices/sampler.cpp

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "convex_bodies/spectrahedra/spectrahedron.h"
1818
#include "random_walks/random_walks.hpp"
1919
#include "sampling/sample_correlation_matrices.hpp"
20+
#include "matrix_operations/EigenvaluesProblems.h"
2021

2122
typedef double NT;
2223
typedef Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic> MT;
@@ -89,6 +90,28 @@ void write_to_file(std::string filename, std::vector<PointType> const& randPoint
8990
std::cout.rdbuf(coutbuf);
9091
}
9192

93+
bool is_correlation_matrix(const MT& matrix, const double tol = 1e-8){
94+
//check if all the diagonal elements are ones
95+
for(int i=0 ; i<matrix.rows() ; i++)
96+
{
97+
if(std::abs(matrix(i, i)-1.0) > tol)
98+
{
99+
return false;
100+
}
101+
}
102+
103+
//check if the matrix is positive semidefinite
104+
using NT = double;
105+
using MatrixType = Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic>;
106+
EigenvaluesProblems<NT, MatrixType, Eigen::Matrix<NT, Eigen::Dynamic, 1>> solver;
107+
108+
if(solver.isPositiveSemidefinite(matrix))
109+
{
110+
return true;
111+
}
112+
return false;
113+
}
114+
92115
template<typename WalkType>
93116
void correlation_matrix_uniform_sampling(const unsigned int n, const unsigned int num_points, std::string walkname){
94117

@@ -106,7 +129,7 @@ void correlation_matrix_uniform_sampling(const unsigned int n, const unsigned in
106129
time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
107130
std::cout << "Elapsed time : " << time << " (ms)" << std::endl;
108131

109-
write_to_file<Point>(walkname + "_matrices.txt", randPoints);
132+
write_to_file<Point>(walkname + "_matrices" + std::to_string(n) + ".txt", randPoints);
110133
}
111134

112135
template<typename WalkType>
@@ -126,7 +149,15 @@ void correlation_matrix_uniform_sampling_MT(const unsigned int n, const unsigned
126149
time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
127150
std::cout << "Elapsed time : " << time << " (ms)" << std::endl;
128151

129-
write_to_file<PointMT>(walkname + "_matrices_MT.txt", randPoints);
152+
int valid_points = 0;
153+
for(const auto& points : randPoints){
154+
if(is_correlation_matrix(points.mat)){
155+
valid_points++;
156+
}
157+
}
158+
std::cout << "Number of valid points = " << valid_points << std::endl;
159+
160+
write_to_file<PointMT>(walkname + "_matrices_MT" + std::to_string(n) + ".txt", randPoints);
130161
}
131162

132163
int main(int argc, char const *argv[]){
@@ -146,25 +177,30 @@ int main(int argc, char const *argv[]){
146177
printf("\n");
147178
#endif
148179

149-
unsigned int n = 3, num_points = 5000;
180+
unsigned int num_points = 5000;
181+
182+
std::vector<unsigned int> dimensions = {3, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
150183

151-
old_uniform_sampling<BilliardWalk>(n, num_points);
184+
for(unsigned int n : dimensions){
152185

153-
correlation_matrix_uniform_sampling<BallWalk>(n, num_points, "BallWalk");
186+
old_uniform_sampling<BilliardWalk>(n, num_points);
154187

155-
correlation_matrix_uniform_sampling<RDHRWalk>(n, num_points, "RDHRWalk");
188+
correlation_matrix_uniform_sampling<BallWalk>(n, num_points, "BallWalk");
156189

157-
correlation_matrix_uniform_sampling<BilliardWalk>(n, num_points, "BilliardWalk");
190+
correlation_matrix_uniform_sampling<RDHRWalk>(n, num_points, "RDHRWalk");
158191

159-
correlation_matrix_uniform_sampling<AcceleratedBilliardWalk>(n, num_points, "AcceleratedBilliardWalk");
192+
correlation_matrix_uniform_sampling<BilliardWalk>(n, num_points, "BilliardWalk");
160193

161-
correlation_matrix_uniform_sampling_MT<BallWalk>(n, num_points, "BallWalk");
194+
correlation_matrix_uniform_sampling<AcceleratedBilliardWalk>(n, num_points, "AcceleratedBilliardWalk");
162195

163-
correlation_matrix_uniform_sampling_MT<RDHRWalk>(n, num_points, "RDHRWalk");
196+
correlation_matrix_uniform_sampling_MT<BallWalk>(n, num_points, "BallWalk");
164197

165-
correlation_matrix_uniform_sampling_MT<BilliardWalk>(n, num_points, "BilliardWalk");
198+
correlation_matrix_uniform_sampling_MT<RDHRWalk>(n, num_points, "RDHRWalk");
166199

167-
correlation_matrix_uniform_sampling_MT<AcceleratedBilliardWalk>(n, num_points, "AcceleratedBilliardWalk");
200+
correlation_matrix_uniform_sampling_MT<BilliardWalk>(n, num_points, "BilliardWalk");
201+
202+
correlation_matrix_uniform_sampling_MT<AcceleratedBilliardWalk>(n, num_points, "AcceleratedBilliardWalk");
203+
}
168204

169205
return 0;
170-
}
206+
}

include/matrix_operations/EigenvaluesProblems.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,12 @@ class EigenvaluesProblems<NT, Eigen::Matrix<NT,Eigen::Dynamic,Eigen::Dynamic>, E
167167
Spectra::DenseSymMatProd<NT> op(B);
168168
Spectra::DenseCholesky<NT> Bop(-A);
169169

170-
// Construct generalized eigen solver object, requesting the largest three generalized eigenvalues
170+
// Construct generalized eigen solver object, computing the minimum positive eigenvalue by computing the largest eigenvalue of the inverse Generalized Eigenvalue Problem
171+
// An empirical value of ncv that gives a better performance
172+
// TODO: tune this implementation by tuning the parameters like ncv
173+
int ncv = std::min(std::max(10, matrixDim/20), matrixDim);
171174
Spectra::SymGEigsSolver<NT, Spectra::LARGEST_ALGE, Spectra::DenseSymMatProd<NT>, Spectra::DenseCholesky<NT>, Spectra::GEIGS_CHOLESKY>
172-
geigs(&op, &Bop, 1, 15 < matrixDim ? 15 : matrixDim);
175+
geigs(&op, &Bop, 1, ncv);
173176

174177
// Initialize and compute
175178
geigs.init();
@@ -324,9 +327,12 @@ class EigenvaluesProblems<NT, Eigen::Matrix<NT,Eigen::Dynamic,Eigen::Dynamic>, E
324327
Spectra::DenseSymMatProd<NT> op(B);
325328
Spectra::DenseCholesky<NT> Bop(-A);
326329

327-
// Construct generalized eigen solver object, requesting the largest three generalized eigenvalues
330+
// Construct generalized eigen solver object, requesting the largest generalized eigenvalue
331+
// an empirical value of ncv that gives a better performance
332+
// TODO: tune this implementation by tuning the parameters like ncv
333+
int ncv = std::min(std::max(10, matrixDim/20), matrixDim);
328334
Spectra::SymGEigsSolver<NT, Spectra::LARGEST_ALGE, Spectra::DenseSymMatProd<NT>, Spectra::DenseCholesky<NT>, Spectra::GEIGS_CHOLESKY>
329-
geigs(&op, &Bop, 1, 15 < matrixDim ? 15 : matrixDim);
335+
geigs(&op, &Bop, 1, ncv);
330336

331337
// Initialize and compute
332338
geigs.init();
@@ -439,10 +445,39 @@ class EigenvaluesProblems<NT, Eigen::Matrix<NT,Eigen::Dynamic,Eigen::Dynamic>, E
439445
/// \param[in] B: symmetric matrix
440446
/// \return The minimum positive eigenvalue and the corresponding eigenvector
441447
NT minPosLinearEigenvalue_EigenSymSolver(MT const & A, MT const & B, VT &eigvec) const {
448+
449+
#if defined(SPECTRA_EIGENVALUES_SOLVER)
450+
int matrixDim = A.rows();
451+
NT lambdaMinPositive;
452+
453+
Spectra::DenseSymMatProd<NT> op(B);
454+
Spectra::DenseCholesky<NT> Bop(A);
455+
456+
//construct generalized eigen solver object, requesting the smallest eigenvalue
457+
int ncv = std::min(std::max(10, matrixDim/20), matrixDim);
458+
Spectra::SymGEigsSolver<NT, Spectra::LARGEST_ALGE, Spectra::DenseSymMatProd<NT>, Spectra::DenseCholesky<NT>, Spectra::GEIGS_CHOLESKY>
459+
geigs(&op, &Bop, 1, ncv);
460+
461+
//initialize and compute
462+
geigs.init();
463+
int nconv = geigs.compute();
464+
465+
//retrieve results
466+
VT evalues;
467+
468+
if(geigs.info() == Spectra::SUCCESSFUL){
469+
evalues = geigs.eigenvalues();
470+
eigvec = geigs.eigenvectors().col(0);
471+
}
472+
473+
lambdaMinPositive = NT(1)/evalues(0);
474+
475+
#elif
442476
NT lambdaMinPositive = NT(0);
443477
Eigen::GeneralizedSelfAdjointEigenSolver<MT> ges(B,A);
444478
lambdaMinPositive = 1/ges.eigenvalues().reverse()[0];
445479
eigvec = ges.eigenvectors().reverse().col(0).reverse();
480+
#endif
446481
return lambdaMinPositive;
447482
}
448483
};

0 commit comments

Comments
 (0)