[Rcpp-devel] Detecting Singular Matrices in RcppArmadillo

Dirk Eddelbuettel edd at debian.org
Sat Jan 29 01:32:26 CET 2022


On 28 January 2022 at 13:25, Alex Ilich wrote:
| Thank you Neal and Dirk. Based on these comments I think using arma::rcond

Ah, yes, of course. Should have remembered arma::rcond.

| to get the reciprocal of the condition factor, and checking if that is zero
| rather than the determinant may be the route to go. At least for this
| example that works.
| 
| library(Rcpp)
| 
| cppFunction(depends="RcppArmadillo", "NumericVector C_OLS(arma::mat X,
| arma::mat Y){
|   arma::mat Xt = trans(X);
|   arma::mat XtX = Xt * X;
|   double rcf = rcond(XtX);
|   Rcout << rcf; //print reciprocal of condition factor
|   if(rcf==0){

Re-read Neal's first email.  You probably do not want zero (apart from all
the R FAQ 7.31 reasons to not compare a double with equality :wink: )

Dirk

|     NumericVector B2(X.n_cols, NA_REAL);
|     return B2;
|   } else{
|     arma::mat XtX_inv= inv(XtX);
|     NumericVector B = Rcpp::as<Rcpp::NumericVector>(wrap(XtX_inv * (Xt *
| Y)));
|     return B;
|   }}")
| 
| X<- matrix(data=c(-250, -250, -250, -250, -250, -250, 250, 200, 150,
|                   100, 50, 0, 1, 1, 1, 1, 1, 1), ncol=3, nrow=6)
| 
| 
| X2<- X
| 
| X2[1,2]<- X[1,2] + 5.684342e-14 #Add a slight numeric precision issue
| 
| Y<- matrix(1:6, ncol=1)
| 
| C_OLS(X,Y)
| # 0[1] NA NA NA
| 
| C_OLS(X2,Y)
| # 0[1] NA NA NA
| 
| 
| 
| On Fri, Jan 28, 2022 at 11:53 AM Alex Ilich <alexilich93 at gmail.com> wrote:
| 
| > Hi, I have some code I've written to calculate regression parameters using
| > ordinarily least squares using RcppArmadillo. This is meant to be performed
| > iteratively over many small subsets (sliding window over spatial raster
| > data) so I'd like to automatically detect when the regression can't be
| > performed and just return a vector of NA's. Currently I check to see if the
| > determinant is 0 in order to see if the XtX matrix can be inverted and it
| > seems to work in the vast majority of cases but I did run into a case where
| > a small amount of precision error was introduced and for some reason this
| > causes the determinant to be non-zero in C++ however, the matrix still is
| > considered singular (uninvertible) leading to an error. I was wondering if
| > anyone had any suggestions? Maybe there's a minimum value non-zero value
| > where it's considered essentially singular that I could use instead of 0,
| > or maybe there's a way to return a vector of NAs if an error is detected
| > rather than stopping execution and printing an error message. I've also
| > seen that pinv can be used, but from some tests I ran it's substantially
| > slower, so I'd like to avoid using that. I've included some example code
| > below. Any suggestions would be greatly appreciated.
| >
| > Thanks,
| > Alex
| >
| > library(Rcpp)
| > cppFunction(depends="RcppArmadillo", "NumericVector C_OLS(arma::mat X,
| > arma::mat Y){
| >   arma::mat Xt = trans(X);
| >   arma::mat XtX = Xt * X;
| >   double d = det(XtX);
| >   Rcout << d; //print determinant
| >   if(d==0){
| >     NumericVector B2(X.n_cols, NA_REAL);
| >     return B2;
| >   } else{
| >     arma::mat XtX_inv= inv(XtX);
| >     NumericVector B = Rcpp::as<Rcpp::NumericVector>(wrap(XtX_inv * (Xt *
| > Y)));
| >     return B;
| >   }}")
| >
| > X<- matrix(data=c(-250, -250, -250, -250, -250, -250, 250, 200, 150,
| >                   100, 50, 0, 1, 1, 1, 1, 1, 1), ncol=3, nrow=6)
| >
| >
| > X2<- X
| >
| > X2[1,2]<- X[1,2] + 5.684342e-14 #Add a slight numeric precision issue
| >
| > Y<- matrix(1:6, ncol=1)
| >
| > #Determinant of XtX in R is 0 for both
| > det(t(X) %*% X) ==0 #TRUE
| > det(t(X2) %*% X2) ==0 #TRUE
| >
| > C_OLS(X,Y) #Determinant is 0 in C++ and correctly returns a vector of NA's
| > #0[1] NA NA NA
| >
| > C_OLS(X2,Y) #Determinant is not 0 in C++ so the if statement is not
| > triggered but the matrix is still uninvertible
| > # 4.57764e-05
| > # error: inv(): matrix is singular
| > # Error in C_OLS(X2, Y) : inv(): matrix is singular
| >
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
-- 
https://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list