二进制矩阵与约束的所有可能组合

时间:2017-10-30 03:58:12

标签: r dataframe

我的问题中有三家商店,销售3种产品,如附图所示。商店由s1到s3表示,产品由p1到p3表示。商店和产品之间的界线表示商店销售产品。

map of stores and products

我按stores<-c("s1","s2","s3")定义商店,products <- c("p1","p2","p3")定义商品。

我必须生成商店的所有可能组合 - 产品映射。我的主要限制是:每家商店至少销售一种产品,每种产品至少由一家商店出售。

当前矩阵将如下所示

   p1 p2 p3
s1 1  0  0
s2 0  0  1
s3 0  1  0

对于这个矩阵,我需要找出所有可能的二元组合,这样,colsums和rowums最小为1(对于约束)。

任何建议,如何实现这一目标。我的实际问题有> 20家商店和产品。

编辑:为混乱道歉。让我试着说出我想要的解决方案。直观地说,我正在寻找从图片中显示的当前配置开始添加商店和产品之间的线。我将需要所有可能的矩阵,它们满足rowSum和colSum的约束。

Existing matrix
   p1 p2 p3
s1 1  0  0
s2 0  0  1
s3 0  1  0

Desired example matrices (addition of one link)
   p1 p2 p3
s1 1  0  1
s2 0  0  1
s3 0  1  0

   p1 p2 p3
s1 1  1  0
s2 0  0  1
s3 0  1  0

等。

不需要的矩阵:第一行的总和为0,即s1不销售任何产品。

   p1 p2 p3
s1 0  0  0
s2 0  0  1
s3 0  1  0

3 个答案:

答案 0 :(得分:2)

我们想要描述商店(行)和产品(列)之间的映射(交互)的所有可能组合。在交互矩阵中,交互由1编码,其缺席为0。约束是列和行总和大于1

这是一个有趣的组合问题;我列举所有可能的组合的方法效率不高;我确信有更高效的实现可以考虑矩阵的可能对称性。看到其他解决方案很有意思......

在下文中,我使用了函数gtools::permutations

matrixCombn <- function(nrow, ncol) {
    # All possible column combinations for a matrix of dimension dim
    # Here we assume two different values c(1, 0)
    require(gtools);
    columns <- t(permutations(n = 2, r = nrow, v = c(1, 0), repeats.allowed = TRUE));
    columns <- columns[, colSums(columns) > 0];

    # Construct all possible combinations of dim column vectors and
    # impose constraint that row and column sum >= 1
    ret <- lapply(as.data.frame(t(permutations(ncol(columns), ncol, repeats.allowed = TRUE))), function(x) {
        m.cand <- columns[, x];
        if (all(rowSums(m.cand) > 0) & all(colSums(m.cand) > 0)) m.cand else NULL;
    })
    ret <- Filter(Negate(is.null), ret);
    return(ret);
}

# Example for 3x3 interaction matrix design
ret <- matrixCombn(3, 3);

这为我们提供了265种独特的组合

length(ret);
# [1] 265 

例如,这是第3个

ret[1:3];
#$V6
#     [,1] [,2] [,3]
#[1,]    0    0    1
#[2,]    0    0    1
#[3,]    1    1    0

#$V7
#     [,1] [,2] [,3]
#[1,]    0    0    1
#[2,]    0    0    1
#[3,]    1    1    1

#$V11
#     [,1] [,2] [,3]
#[1,]    0    0    1
#[2,]    0    1    0
#[3,]    1    0    0

对于3x2交互矩阵设计,我们得到

ret <- matrixCombn(3, 2);
length(ret);
# [1] 25

使用前3个组合

ret[1:3];
#$V6
#     [,1] [,2]
#[1,]    0    1
#[2,]    0    1
#[3,]    1    0

#$V7
#     [,1] [,2]
#[1,]    0    1
#[2,]    0    1
#[3,]    1    1

#$V12
#     [,1] [,2]
#[1,]    0    1
#[2,]    1    0
#[3,]    0    1

答案 1 :(得分:0)

您可以像这样生成笛卡尔积

stores<-c("s1","s2","s3")
products <- c("p1","p2","p3")

expand.grid(stores,products)

   Var1 Var2
1   s1   p1
2   s2   p1
3   s3   p1
4   s1   p2
5   s2   p2
6   s3   p2
7   s1   p3
8   s2   p3
9   s3   p3

获得此数据框后,您可以通过添加列

来定义哪个商店销售哪个产品
dt <- cbind(expand.grid(stores,products), val = sample(0:1,9, replace = T))

> dt
  Var1 Var2 val
1   s1   p1   1
2   s2   p1   1
3   s3   p1   1
4   s1   p2   0
5   s2   p2   0
6   s3   p2   1
7   s1   p3   0
8   s2   p3   1
9   s3   p3   0

然后,您可以使用reshape

reshape(dt, idvar = "Var1", timevar = "Var2", direction = "wide")

  Var1 val.p1 val.p2 val.p3
1   s1      1      0      0
2   s2      1      0      1
3   s3      1      1      0

答案 2 :(得分:0)

您可以添加列名并替换您喜欢的值。这适用于我:

#No. of columns
n   <- 3  

#Values 
vec <- c(0, 1)  

#function returns a column vector that is a stack of the columns of x
lst <- lapply(numeric(n), function(x) vec) 

# 'expand.grid' creates a data frame that is the cartesian product of its 
#arguments 
preditction <- as.matrix(expand.grid(lst)) 

#Creating a prediction matrix that meets the condition- "**My main constraint 
#is : each store will sell at least one product and each product will be 
#sold by at least one store**."

preditction_matrix <- subset.matrix(x= preditction,
                                    subset = rowSums(preditction) > 0)
View(preditction_matrix)