如何在反转奇异矩阵时使Armadillo函数不打印错误?

时间:2015-03-09 19:36:12

标签: c++ r rcpp armadillo

一个伙伴和我正在研究R包并使用RcppArmadillo包来处理一些较重的矩阵代数。到目前为止它已经非常甜蜜,但我们在矩阵求逆方面遇到了一些问题。简而言之,程序正在搜索特定类型的矩阵,并且必须检查在循环的每次迭代中是否存在更新的矩阵的逆(逆本身也是必需的)。现在我们正在使用函数inv(A, B),它返回一个布尔值,指示矩阵B是否可逆(如果不是,A设置为0x0矩阵,否则为A = inv(B))。如果此函数没有打印错误,那将是很好的,因为返回的布尔值给循环提供正确进行所需的信息。似乎错误只是打印而不是“抛出”,如下面的程序所示:

#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

int main(int argc, char** argv)
{
    mat A = randu<mat>(5,5);
    mat B = zeros<mat>(5,5);

    inv(A, B);

    cout << A << "error printed but not fatal" << endl;

    A = inv(B);

    cout << A << "never make it this far" << endl;

    return 0;
}

导致:

Johns-MacBook-Pro:test johnsherrill$ g++ armaExample.cpp -o example -O2 -larmadillo
Johns-MacBook-Pro:test johnsherrill$ ./example

error: inv(): matrix appears to be singular

[matrix size: 0x0]
error printed but not fatal

error: inv(): matrix appears to be singular

terminate called after throwing an instance of 'std::runtime_error'
  what():  inv(): matrix appears to be singular
Abort trap: 6

有没有办法解决这个问题,而无需先单独检查B是否可逆?这种类型的错误也印在R中。

3 个答案:

答案 0 :(得分:4)

最简单的方法是在包含Armadillo标题之前定义ARMA_DONT_PRINT_ERRORS。

例如:

#define ARMA_DONT_PRINT_ERRORS
#include <armadillo>   // or #include <RcppArmadillo.h> if you're using Rcpp

定义描述于 http://arma.sourceforge.net/docs.html#config_hpp

答案 1 :(得分:2)

基于API documentation中的示例,使用arma::set_stream_err2可能是这样的:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
void arma_invert() {

  std::ostream nullstream(0);
  arma::set_stream_err2(nullstream);

  arma::mat A = arma::randu<arma::mat>(5,5);
  arma::mat B = arma::zeros<arma::mat>(5,5);
  bool flag = arma::inv(A, B);

  if (!flag) {
    Rcpp::Rcout << 
      A << "error printed but not fatal" << std::endl;
  } else {
    A = arma::inv(B);
    Rcpp::Rcout <<
      A << "never make it this far" << std::endl; 
  }
}

产生

[matrix size: 0x0]
error printed but not fatal

而不是

error: inv(): matrix appears to be singular

[matrix size: 0x0]
error printed but not fatal

或使用您的CLI示例

#include <iostream>
#include <armadillo>

int main(int argc, char** argv) {

  std::ostream nullstream(0);
  arma::set_stream_err2(nullstream);

  arma::mat A = arma::randu<arma::mat>(5,5);
  arma::mat B = arma::zeros<arma::mat>(5,5);
  bool flag = arma::inv(A, B);

  if (!flag) {
    std::cout <<
      A << "error printed but not fatal" << std::endl;
  } else {
    A = arma::inv(B);
    std::cout <<
      A << "never make it this far" << std::endl;
  }

 return 0;
}

[nathan@nrussell tmp]$ g++ example.cpp -o example -O2 -I /home/nathan/R/x86_64-redhat-linux-gnu-library/3.1/RcppArmadillo/include -lblas -llapack
[nathan@nrussell tmp]$ ./example
[matrix size: 0x0]
error printed but not fatal

答案 2 :(得分:1)

通过浏览犰狳来源,我看到的唯一直接方法是在#define ARMA_PRINT_ERRORS中注释掉armadillo_bits/config.hpp行。