/** Solves A*x = B using SVD * @param A :: [input] The matrix A * @param B :: [input] The vector B * @return :: The solution x */ std::vector<double> MaxEnt::solveSVD(const DblMatrix &A, const DblMatrix &B) { size_t dim = A.size().first; gsl_matrix *a = gsl_matrix_alloc(dim, dim); gsl_matrix *v = gsl_matrix_alloc(dim, dim); gsl_vector *s = gsl_vector_alloc(dim); gsl_vector *w = gsl_vector_alloc(dim); gsl_vector *x = gsl_vector_alloc(dim); gsl_vector *b = gsl_vector_alloc(dim); // Need to copy from DblMatrix to gsl matrix for (size_t k = 0; k < dim; k++) for (size_t l = 0; l < dim; l++) gsl_matrix_set(a, k, l, A[k][l]); for (size_t k = 0; k < dim; k++) gsl_vector_set(b, k, B[k][0]); // Singular value decomposition gsl_linalg_SV_decomp(a, v, s, w); // A could be singular or ill-conditioned. We can use SVD to obtain a least // squares // solution by setting the small (compared to the maximum) singular values to // zero // Find largest sing value double max = gsl_vector_get(s, 0); for (size_t i = 0; i < dim; i++) { if (max < gsl_vector_get(s, i)) max = gsl_vector_get(s, i); } // Apply a threshold to small singular values const double THRESHOLD = 1E-6; double threshold = THRESHOLD * max; for (size_t i = 0; i < dim; i++) if (gsl_vector_get(s, i) > threshold) gsl_vector_set(s, i, gsl_vector_get(s, i)); else gsl_vector_set(s, i, 0); // Solve A*x = B gsl_linalg_SV_solve(a, v, s, b, x); // From gsl_vector to vector std::vector<double> delta(dim); for (size_t k = 0; k < dim; k++) delta[k] = gsl_vector_get(x, k); gsl_matrix_free(a); gsl_matrix_free(v); gsl_vector_free(s); gsl_vector_free(w); gsl_vector_free(x); gsl_vector_free(b); return delta; }