如何让犰狳函数在反转奇异矩阵时不打印错误?
How do I get an Armadillo function to NOT print an error when inverting a singular matrix?
我和一个伙伴正在开发一个 R 包,并将 RcppArmadillo 包用于一些较重的矩阵代数。到目前为止一切顺利,但我们遇到了一个关于矩阵求逆的小问题。长话短说,程序正在搜索特定类型的矩阵,并且必须检查更新后的矩阵的逆矩阵是否存在于循环的每次迭代中(也需要逆矩阵本身)。现在我们正在使用函数 inv(A, B)
,其中 returns 一个布尔值,指示矩阵 B 是否可逆(如果不是,A 设置为 0x0 矩阵,否则 A = inv(B)
)。如果此函数不打印错误,那对我们来说会很好,因为返回的布尔值为循环提供了正确执行所需的信息。似乎只是打印了一个错误,而不是 "thrown",如以下程序所示:
#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 中。
通过 grep 浏览犰狳源,我看到的唯一直接的方法是在 armadillo_bits/config.hpp
.
中注释掉行 #define ARMA_PRINT_ERRORS
基于 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
最简单的方法是在包含 Armadillo header 之前定义 ARMA_DONT_PRINT_ERRORS。
例如:
#define ARMA_DONT_PRINT_ERRORS
#include <armadillo> // or #include <RcppArmadillo.h> if you're using Rcpp
我和一个伙伴正在开发一个 R 包,并将 RcppArmadillo 包用于一些较重的矩阵代数。到目前为止一切顺利,但我们遇到了一个关于矩阵求逆的小问题。长话短说,程序正在搜索特定类型的矩阵,并且必须检查更新后的矩阵的逆矩阵是否存在于循环的每次迭代中(也需要逆矩阵本身)。现在我们正在使用函数 inv(A, B)
,其中 returns 一个布尔值,指示矩阵 B 是否可逆(如果不是,A 设置为 0x0 矩阵,否则 A = inv(B)
)。如果此函数不打印错误,那对我们来说会很好,因为返回的布尔值为循环提供了正确执行所需的信息。似乎只是打印了一个错误,而不是 "thrown",如以下程序所示:
#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 中。
通过 grep 浏览犰狳源,我看到的唯一直接的方法是在 armadillo_bits/config.hpp
.
#define ARMA_PRINT_ERRORS
基于 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
最简单的方法是在包含 Armadillo header 之前定义 ARMA_DONT_PRINT_ERRORS。
例如:
#define ARMA_DONT_PRINT_ERRORS
#include <armadillo> // or #include <RcppArmadillo.h> if you're using Rcpp