Условная случайная матрица с 0 и 1 на основе сумм строк и столбцов - PullRequest
4 голосов
/ 21 октября 2019

Я пытаюсь построить матрицу в R с 1 и 0, но матрица должна быть сгенерирована, только если выполнены условия для сумм строк и столбцов. например:

1 0 1 1
0 1 1 0
1 1 1 1
1 0 1 0

Я хочу создать матрицу с rowsums = c(3, 2, 4, 2) и colsums = c(3, 2, 4, 2).

Ответы [ 2 ]

2 голосов
/ 21 октября 2019

Подходя к этому как к проблеме lp, на которую phiver также ссылается в ссылке, предоставленной Стефаном Лораном в комментарии:

library(lpSolve)
library(data.table)

nr <- 4
nc <- 4
ne <- nr * nr

v <- vector("integer", ne)
colvec <- replace(v, seq_along(v) <= nr, 1L)
rowvec <- replace(v, seq_along(v) %% nc == 1, 1L)

colconstr <- c(3, 2, 4, 2)
rowconstr <- c(3, 2, 4, 2)

const.mat <- do.call(rbind, c(
    data.table::shift(colvec, seq(0L, ne - nc, nc), fill=0L),
    data.table::shift(rowvec, 0L:(nr-1L), fill=0L)))
const.rhs <- c(colconstr, rowconstr)

s <- lpSolve::lp("min", runif(ne), const.mat, 
    rep("==", nrow(const.mat)), const.rhs, all.bin=TRUE)$solution
matrix(s, nrow=nr)

пример вывода:

     [,1] [,2] [,3] [,4]
[1,]    1    0    1    1
[2,]    1    0    1    0
[3,]    1    1    1    1
[4,]    0    1    1    0
2 голосов
/ 21 октября 2019

Возможно, есть более элегантное решение, но оно работает, не требует много времени для запуска и не требует никакого пакета:

repeat {
  repeat {
    repeat {
      repeat {
        repeat {
          x <- sample(0:1, 4, replace = T)
          if(sum(x) == 3) {
            break
          }
        }
        repeat {
          y <- sample(0:1, 4, replace = T)
          if(sum(y) == 2) {
            break
          }
        }
        repeat {
          z <- sample(0:1, 4, replace = T)
          if(sum(z) == 4) {
            break
          }
        }
        repeat {
          u <- sample(0:1, 4, replace = T)
          if(sum(u) == 2) {
            break
          }
        }
        if(sum(x[1], y[1], z[1], u[1]) == 3) {
          break
        }
      }
      if(sum(x[2], y[2], z[2], u[2]) == 2) {
        break
      }
    }
    if(sum(x[3], y[3], z[3], u[3]) == 4) {
      break
    }
  }
  if(sum(x[4], y[4], z[4], u[4]) == 2) {
    print(matrix(c(x, y, z, u), 4, 4, byrow = T))
    break
  }
}
...