Search code examples
rfunctionmatrixdeterminants

Function to get the determinant of a NxN matrix using laplace expansion in R (Error: argument of length 0)


determinant_laplace <- function(M, k = 1) {
  n <- nrow(M)
  
  det_value <- 0
  sign <- 1
  for (j in 1:n) {
    sub_matrix <- M[-k, -j]
    sub_det <- determinant_laplace(sub_matrix, k = 1)  
    
    det_value <- det_value + sign * M[k, j] * sub_det
    sign <- -sign
  }
  return(det_value)
}
# Example usage
B = matrix(1:9,nrow=3,ncol=3)
B
determinant_laplace(B) 
det(B)

This is what I have so far. When I run it I get a error," Error in 1:n : argument of length 0". I ran it with debugger on and found that n is NULL but I don't know why or how to fix it. Any help would be appreciated.


Solution

  • Update

    As pointed out by @Onyambu in the comment, you should be aware that k=1 can be hard coded within your function (rather than taken as an input argument), since you always start the expansion from the 1st row of matrices during the recursion. That means, we, indeed, are able to simplify the function further.

    Below is an example with further simplification

    determinant_laplace <- function(M) {
      if (length(M) == 1) {
        return(M)
      }
      det_value <- numeric(nrow(M))
      for (j in seq_along(det_value)) {
        det_value[j] <- (-1)^(j - 1) * M[1, j] * Recall(M[-1, -j, drop = FALSE])
      }
      return(sum(det_value))
    }
    

    You are using recursion to compute the matrix determinant and I think you missed two things in your code (see the first two comments and the code below)

    determinant_laplace <- function(M, k = 1) {
      # add a termination condition to finish the recursion
      if (length(M) == 1) {
        return(M)
      }  
      n <- nrow(M)
      det_value <- 0
      sign <- 1
      for (j in 1:n) {
        # option `drop = FALSE` should be specified, otherwise, 1-by-1 matrix would be collapsed into a scalar, which leads to the error you have seen in your original code
        sub_matrix <- M[-k, -j, drop = FALSE]
        sub_det <- determinant_laplace(sub_matrix, k = 1)
        det_value <- det_value + sign * M[k, j] * sub_det
        sign <- -sign
      }
      return(c(det_value)) # Optional: use `c()` to make a scalar output
    }
    

    and a simple test we can try

    > set.seed(1)
    
    > n <- 5
    
    > (B <- matrix(runif(n^2), nrow = n))
              [,1]       [,2]      [,3]      [,4]      [,5]
    [1,] 0.2655087 0.89838968 0.2059746 0.4976992 0.9347052
    [2,] 0.3721239 0.94467527 0.1765568 0.7176185 0.2121425
    [3,] 0.5728534 0.66079779 0.6870228 0.9919061 0.6516738
    [4,] 0.9082078 0.62911404 0.3841037 0.3800352 0.1255551
    [5,] 0.2016819 0.06178627 0.7698414 0.7774452 0.2672207
    
    > determinant_laplace(B)
    [1] -0.05779661
    
    > det(B)
    [1] -0.05779661