Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the maximum square sub-matrix with all equal elements

Does anybody know how it could be possible to subset the maximum K such that K x K is a submatrix with all identical elements, i.e., all the elements in this submatrix must be the same from a given a N x N matrix? I found many examples in other programming languages except R. I also prefer dplyr if you know.

There is a link to the solution with other languages: https://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-in-a-binary-matrix/

But this link provides a special case when all identical elements are next to each other. It retrieves a maximum block of the same elements, not a submatrix in general. I do not want to limit subsetting with this condition.

like image 765
Mohieddin Jafari Avatar asked Jul 16 '26 19:07

Mohieddin Jafari


1 Answers

Here is a base R implementation to make it.

If you want to search the maximum square sub-matrix within a non-square matrix, you can try the code below:

r <- list()
for (w in rev(seq(min(dim(M))))) {
  for (rs in seq(nrow(M)-w+1)) {
    for (cs in seq(ncol(M)-w+1)) {
      mat <- M[rs-1+(1:w),cs-1+(1:w)]
      u <- unique(c(mat))
      if (all(u!=0) &length(u)==1) r[[length(r)+1]] <- mat
    }
  }
  if (length(r)>0) break
}

such that

> r
[[1]]
     [,1] [,2]
[1,]    3    3
[2,]    3    3

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

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

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

[[5]]
     [,1] [,2]
[1,]    1    1
[2,]    1    1

[[6]]
     [,1] [,2]
[1,]    1    1
[2,]    1    1

[[7]]
     [,1] [,2]
[1,]    3    3
[2,]    3    3

[[8]]
     [,1] [,2]
[1,]    3    3
[2,]    3    3

DATA

M <- structure(c(1L, 3L, 1L, 2L, 1L, 3L, 3L, 2L, 2L, 3L, 3L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 3L, 1L, 3L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 
2L, 2L, 1L, 3L, 1L, 3L, 2L, 2L, 2L, 2L, 3L, 2L, 1L, 3L, 2L, 1L, 
1L, 3L, 2L, 2L, 3L, 3L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 
3L, 3L, 2L, 3L, 3L, 2L, 3L, 3L, 1L, 1L, 1L, 1L, 3L, 2L, 3L, 1L, 
1L, 2L, 1L, 1L, 1L, 1L, 3L, 2L, 1L, 1L, 3L, 3L, 3L, 2L, 2L, 2L, 
3L, 2L, 2L, 3L, 3L, 3L, 1L, 2L, 2L, 1L, 3L, 3L, 2L, 3L, 2L, 1L, 
2L, 1L, 3L, 3L, 1L, 2L, 1L, 3L, 2L, 3L, 3L, 1L, 1L, 2L, 2L, 2L, 
1L, 1L, 1L, 2L, 1L, 3L, 2L, 3L, 3L, 2L, 3L, 3L, 1L, 1L, 2L, 2L, 
1L, 2L, 3L, 3L, 3L, 3L, 3L, 1L, 3L), .Dim = c(15L, 10L))

> M
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1    2    2    1    1    3    2    2    1     3
 [2,]    3    2    1    3    3    1    2    3    1     3
 [3,]    1    2    3    2    3    1    2    2    2     1
 [4,]    2    3    1    2    2    2    3    1    2     1
 [5,]    1    1    3    3    3    1    2    2    2     2
 [6,]    3    3    2    3    3    1    2    1    1     2
 [7,]    3    1    2    2    2    1    3    3    1     1
 [8,]    2    1    2    2    3    1    3    3    1     2
 [9,]    2    1    2    2    3    3    3    1    2     3
[10,]    3    1    3    2    1    2    1    2    1     3
[11,]    3    2    2    1    1    1    2    1    3     3
[12,]    1    1    1    2    1    1    2    3    2     3
[13,]    1    1    3    2    1    3    1    2    3     3
[14,]    1    2    2    2    3    3    3    3    3     1
[15,]    2    2    1    2    2    3    3    3    2     3

EDIT

The approach above is inefficient when with large matrix since all combinations checked. The method below is a R implementation of algorithm stated in https://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-in-a-binary-matrix/, which is is far more efficient.

M <- unname(as.matrix(read.csv(file = "test2.csv")))
S <- matrix(0,nrow = nrow(M),ncol = ncol(M))
S[,1] <- M[,1]
for (i in 1:nrow(S)) {
  for (j in 2:ncol(S)) {
    if (M[i,j]==1) {
      if (i==1) {
        S[i,j] <- M[i,j]
      } else {
        S[i,j] <- min(c(S[i,j-1],S[i-1,j],S[i-1,j-1]))+1
      }
    }
  }
}

inds <- which(S == max(S),arr.ind = TRUE)
w <- seq(max(S))-1
res <- lapply(seq(nrow(inds)), function(k) M[inds[k,"row"]-w,inds[k,"col"]-w])
like image 118
ThomasIsCoding Avatar answered Jul 19 '26 12:07

ThomasIsCoding



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!