Exception throw when using Armadillo and qpOASES

473 views Asked by At

I have a quadratic programming optimization problem that I am solving with qpOASES. In there exists a matrix X that I need to precondition, so I am using Armadillo and the routine arma::pinv from there in order to calculate the Moor-Penrose pseudoinverse.

The problem: I write the matrix X in a file , and then I read it in a separate program (say test.cpp) that does not depend in any way to qpOASES. The routine pinv runs fine.

#include <iostream> 
#include <fstream>
#include <armadillo>                                                  
#include <string>

using namespace std;                                       
using namespace arma;                                      

int main(){


    // Read design matrix.
    int NRows = 199;
    int NFields = 26;
    string flname_in = "chol_out_2_data"; 
    mat  A (NRows,NFields);                              

    for (int i=0; i < NRows; ++i) 
         for (int j=0; j < NFields; ++j)
                    myin >> A(i,j) ;

    // Calculate pseudoinverse  
    mat M;
    pinv(M,A);    // <========= THIS fails when I use flag: -lqpOASES
 }                                          

When I include the same routine in the file where I perform the QP optimization (say true_QP.cpp), I get a runtime error, due to pinv not being able to calculate the pseudo inverse. I've done extensive tests, the file is read in OK and the values are the same.

I've tracked down the problem that is a conflict in the following way: I compiled the program that does not depend in any way on qpOASES (test.cpp - as described above) also with the flag -lqpOASES and then, the code gives run time error.

That is,compile:

g++ test.cpp -o test.xxx -larmadillo

runs fine:

./test.xxx

compile:

g++ test.cpp -o test.xxx -larmadillo -lqpOASES

throws exception (due to failure of calculating pinv):

./test.xxx

Therefore I suspect some conflict - it seems that using -lqpOASES affects some flag in armadillo also? Any ideas? Is there some dependency in LAPACK/BLAS or some flag internally that may change the setup of Armadillo? Thank you for your time.

Here is the documentation for the arma::pinv function: http://arma.sourceforge.net/docs.html#pinv

1

There are 1 answers

1
Foivos On BEST ANSWER

I have resolved the issue by calculating pinv from Eigen, instead of Armadillo.

The function definition I used for Eigen, based on this bug report: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257

is:

template<typename _Matrix_Type_>
Eigen::MatrixXd pinv(const _Matrix_Type_ &a, double epsilon =std::numeric_limits<double>::epsilon())
    {
    Eigen::JacobiSVD< _Matrix_Type_ > svd(a ,Eigen::ComputeThinU | Eigen::ComputeThinV);
    double tolerance = epsilon * std::max(a.cols(), a.rows()) *svd.singularValues().array().abs()(0);

    return
            svd.matrixV() *  (svd.singularValues().array().abs() > tolerance).select(svd.singularValues().array().inverse(), 0).matrix().asDiagonal() * svd.matrixU().adjoint();
}