首页 > 解决方案 > 如何将所有可能的字段划分到R中的矩阵中

问题描述

我有这个领域:

在此处输入图像描述

我想要的是获得该领域的所有潜在描述。但是有一个限制,划界必须只包括相邻的宿舍。这意味着我们无法划分第 1 至第 4 季度和第 2 至第 3 季度。潜在划分的数量由以下公式给出:

|N| = $$(\sum_{i=1}^{Width-MinWidth+1} i)(\sum_{i=1}^{Length-MinLength+1} i)$$ ,

其中 Width 等于字段的宽度,Length 等于字段的长度(在这种情况下,两者都是 2),MinWidth 等于区域的最小宽度,MinLength 等于区域的最小长度(在这种情况下,它们可以是 1或 2)。

因此,如果 MinWidth = 1 且 MinLength = 1,在本例中为 |N| = 9。

我想在相应的矩阵中有这个字段的矩形区域。此示例的相应矩阵必须如下所示:

      [,1] [,2] [,3] [,4]
 [1,]    1    0    0    0
 [2,]    0    1    0    0
 [3,]    0    0    1    0
 [4,]    0    0    0    1
 [5,]    1    1    0    0
 [6,]    0    0    1    1
 [7,]    1    0    1    0
 [8,]    0    1    0    1
 [9,]    1    1    1    1

该矩阵的解释是,第一次划分仅包括第一季度(以及 2,3,4 一起),第二次划分仅包括第二季度(以及 1,3,4 一起),...,第五分度包括第一和第二季度(和 3,4 一起),所以它继续。3x3 字段的矩阵将是 36x9 矩阵,类似于上面的矩阵。

我已经设法建立了一个与 |N| 交互的循环 次(潜在描绘的数量),代码如下:

z <- 0
  for (j in MinWidth:Width) {
    for (l in 0:(Width - 1)) {
      if ((j + l) <= Width) {
        for (i in MinLength:Length) {
          for (k in 0:(Length-1)) {
            if ((k + i) <= Length) {
              z <- z + 1
            }
          }
        }
      }
    }
  }

这个循环的作用是:

它需要四分之一然后检查是否有剩余空间,首先是横向然后纵向,以创建一个区域。j 代表宽度,l 代表剩余可用宽度,i 代表长度,k 代表剩余可用长度。但是我无法为每个循环获得正确的矩阵行。

有什么想法我怎么能在 R 中做到这一点?

标签: rloopsmatrix

解决方案


这是一个有点复杂的解决方案(当然可以优化),因为它确实返回了只有基数 R 的矩阵。只需输入 mat(l,w) 其中 l 和 w 描述字段的长度和宽度:

library(nnls)

expand <- function(x) {
  out = x
  index = which(is.na(x))
  for(i in 1:length(index)) {
    y = x[(index[i]+1):length(x)]
    add = length(x)-length(y)
    out = rbind(out,c(y,rep(NA,add)))
  }
  return(out)
}

check_split <- function(M) {
  check = c()
  for(i in 1:nrow(M)) {
    Y = ifelse(M[i,] == 1,0,1)
    mod = round(coef(nnls(t(M[-i,]),matrix(Y))),10)
    mod[is.na(mod)] = 0
    check = c(check,all(mod %in% c(1,0)))
  }
  return(check)
}

mat <- function(l,w,minL,minW) {
  print(matrix(1:(l*w),byrow=T,nrow=l))

  out = list()
  x=c()
  for(i in 1:(l*w)) {
    if(i%%w == 0){
      x = c(x,i,NA)
    } else {
      x = c(x,i)
    }
  }

  y = expand(x)
  for (m in 1:l) {
    y = expand(x)[1:m,]
    for (n in 0:w) {
      for (i in 1:length(x)) {
        if(m == 1) {
        out = c(out,list(y[i:(i+n)]))
        } else {
          out = c(out,list(y[,i:min((i+n),ncol(y))]))
        }
      }
    }
  }

allCombinations = out[unlist(lapply(out,function(x) !any(is.na(x))))]
allCombinations = lapply(allCombinations,as.matrix,byrow=T)
allCombinations = lapply(allCombinations,function(x) if(ncol(x)==1 & is.null(rownames(x))){t(x)}else{x})

## Account for restrictions
lengths = lapply(allCombinations, nrow)
widths = lapply(allCombinations, ncol)
simple = lapply(allCombinations, function(x) sort(as.vector(x)))[lengths >= minL & widths >= minW]

## Desired matrix
output = do.call(rbind, lapply(simple, function(x) ifelse(1:(l*w) %in% x, 1,0)))

output[check_split(output),]

}

如果有困惑,很乐意回答问题。


推荐阅读