Search code examples
rmatrixpermutation

Return all matrices of a given dimension with a certain number of ones and remaining zeros


Consider the following simplified example, with all possible 2 x 2 matrices with one 1 and the remaining 0s.

library(arrangements)

# define function
generate_matrices <- function(nrow, ncol, ones_count) {
  
  vectors <- permutations(c(
    rep(1, ones_count),
    rep(0, nrow * ncol - ones_count)
  ))
  
  # remove redundancies
  vectors <- vectors[!duplicated(vectors),]
  
  # list of matrices
  out <- list()
  
  for (i in 1:ncol(vectors)) {
    out[[i]] <- matrix(
      data = vectors[,i],
      nrow = nrow,
      ncol = ncol,
      byrow = TRUE
    )
  }
  return(out)
}

Run function to generate all 2 by 2 matrices with one 1:

generate_matrices(nrow = 2, ncol = 2, ones_count = 1)

[[1]]
     [,1] [,2]
[1,]    1    0
[2,]    0    0

[[2]]
     [,1] [,2]
[1,]    0    1
[2,]    0    0

[[3]]
     [,1] [,2]
[1,]    0    0
[2,]    1    0

[[4]]
     [,1] [,2]
[1,]    0    0
[2,]    0    1

When I extend this to a matrix with 5 rows, 4 columns and 4 ones, it errors:

generate_matrices(nrow = 5, ncol = 4, ones_count = 4)
# Error in permutations(c(rep(1, ones_count), rep(0, nrow * ncol - ones_count))) :
# too many results

My guess is that the lines

vectors <- permutations(c(
    rep(1, ones_count),
    rep(0, nrow * ncol - ones_count)
  ))

takes too long to run and/or there is not enough memory on my laptop to store these. Is there a more efficient way to implement this?

It is worth noting that I would like to eventually extend this to the 6 x 5 case with 4 ones, and 8 x 5 case with 8 ones.


Solution

  • You can take combination of indices on which is 1:

    m <- 2
    n <- 2
    k <- 2
    
    createMatrix <- function(m, n, indices){
      
      x <- matrix(0, m, n)
      x[indices] <- 1
      
      x
    }
    
    lapply(
      combn(seq_len(m*n), k, simplify = FALSE), 
      function(x) createMatrix(m, n, x)
    )
    

    where m is number of rows, n number of columns and k number of ones.