This can be solved as a transfer problem or an integer programming problem. We also show a single-line solution that uses only the R base, which generates random matrices for which each row and each column of columns are summed to 1, filtering and returning those that satisfy the additional restrictions that each element of the solution matrix is ββless than or equal to the corresponding temp2 element.
1) transportation problem Using lp.transport in lpSolve, we can solve it in one statement:
library(lpSolve) res <- lp.transport(as.matrix(temp2), "max", rep("=", 8), rep(1, 8), rep("=", 8), rep(1, 8), integers = 0:1) res ## Success: the objective function is 8 soln <- array(res$solution, dim(temp2)) # verify all(colSums(soln)==1) && all(rowSums(soln)==1) && all(temp2>=soln) && all(soln %in% 0:1) ## [1] TRUE
2) integer programming
If X is the solution, we specified the row and column restrictions, but did not specify the restrictions X <= temp2, since they will be satisfied automatically, since no solution puts 1, where temp2 0 can have a maximum goal of 8.
library(lpSolve) n <- nrow(temp2) obj <- unlist(temp2) const_row <- t(sapply(1:n, function(i) c(row(temp2)) == i)) # each row sums to 1 const_col <- t(sapply(1:n, function(i) c(col(temp2)) == i)) # each col sums to 1 const.mat <- rbind(const_row, const_col) res <- lp("max", obj, const.mat, "=", 1, all.bin = TRUE) res ## Success: the objective function is 8 soln <- array(res$solution, dim(temp2)) # verify all(colSums(soln)==1) && all(rowSums(soln)==1) && all(temp2>=soln) && all(soln %in% 0:1) ## [1] TRUE
(Note that with the same argument we could ease the problem to the linear programming problem if we add 0 <= soln [i, j] <= 1 constraints, since the same argument allowed us to omit soln [i, j] <= temp2 [i, j] limits the maximization, as a result of which the soln elements will be 0 or 1.)
2a) This approach is longer, but explicitly indicates the limitations of X <= temp2:
n <- nrow(temp2) obj <- numeric(n*n) const1 <- diag(n*n) # soln[i,j] <= temp2[i,j] const2 <- t(sapply(1:n, function(i) c(row(temp2)) == i)) # each row sums to 1 const3 <- t(sapply(1:n, function(i) c(col(temp2)) == i)) # each col sums to 1 const.mat <- rbind(const1, const2, const3) const.dir <- rep(c("<=", "="), c(n*n, 2*n)) const.rhs <- c(unlist(temp2), rep(1, 2*n)) res <- lp("max", obj, const.mat, const.dir, const.rhs, all.bin = TRUE) res ## Success: the objective function is 0 soln <- array(res$solution, dim(temp2)) # verify all(colSums(soln)==1) && all(rowSums(soln)==1) && all(temp2>=soln) && all(soln %in% 0:1) ## [1] TRUE
2b) Note that if X is a solution matrix, then in X <= temp2 only the positions of X corresponding to zeros in temp2 actually limit, so we could eliminate any restriction corresponding to 1 in temp2 in (2a) solution. With this change, all restrictions become limitations of equality.
n <- nrow(temp2) obj <- numeric(n*n) const1 <- diag(n*n)[unlist(temp2) == 0, ] const2 <- t(sapply(1:n, function(i) c(row(temp2)) == i)) # each row sums to 1 const3 <- t(sapply(1:n, function(i) c(col(temp2)) == i)) # each col sums to 1 const.mat <- rbind(const1, const2, const3) const.dir <- "=" const.rhs <- c(numeric(nrow(const1)), rep(1, 2*n)) res <- lp("max", obj, const.mat, const.dir, const.rhs, all.bin = TRUE) res ## Success: the objective function is 0 soln <- array(res$solution, dim(temp2)) # verify all(colSums(soln)==1) && all(rowSums(soln)==1) && all(temp2>=soln) && all(soln %in% 0:1) ## [1] TRUE
In fact, we could go further and remove the variables corresponding to the null elements of temp2 .
3) r2dtable Here we use rd2table to generate 10,000 8x8 tables whose rows and columns sum to 1 and then filter them to pick out only those satisfying the X < temp2 constrainsts. With rd2table to generate 10,000 8x8 tables whose rows and columns sum to 1 and then filter them to pick out only those satisfying the X < temp2 constrainsts. With temp2` of the question, and showing a random seed, found 3 solutions. If with different inputs he does not find solutions, try to create a larger number of random sentences. This approach does not use any packages.
set.seed(123) # for reproducibility Filter(function(x) all(x <= temp2), r2dtable(10000, rep(1, 8), rep(1, 8)))
giving:
[[1]] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 1 0 0 [3,] 0 1 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 1 [5,] 0 0 0 0 0 0 1 0 [6,] 0 0 1 0 0 0 0 0 [7,] 0 0 0 1 0 0 0 0 [8,] 0 0 0 0 1 0 0 0 [[2]] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 1 0 0 [3,] 0 1 0 0 0 0 0 0 [4,] 0 0 0 0 1 0 0 0 [5,] 0 0 0 1 0 0 0 0 [6,] 0 0 1 0 0 0 0 0 [7,] 0 0 0 0 0 0 1 0 [8,] 0 0 0 0 0 0 0 1 [[3]] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 0 0 0 0 0 0 0 [2,] 0 1 0 0 0 0 0 0 [3,] 0 0 0 0 0 1 0 0 [4,] 0 0 0 0 1 0 0 0 [5,] 0 0 1 0 0 0 0 0 [6,] 0 0 0 0 0 0 1 0 [7,] 0 0 0 1 0 0 0 0 [8,] 0 0 0 0 0 0 0 1