如何在R

时间:2018-12-11 09:59:24

标签: combinatorics linear-programming

我要解决的问题与本文中的问题基本相同:

https://stats.stackexchange.com/questions/339935/python-library-for-combinatorial-optimization

并且我当前的实现确实使用了基于遗传算法的优化器。

但是,我想将其作为二进制线性编程问题解决(至少尝试,即使它看起来很“ NP-hard”)。

我的问题是如何以最佳方式制定LP,因为我不确定我做对了吗。

以下是我正在处理的内容的简化版本,但是它准确显示了问题所在。

我们通过组合处理,使m * n个对象(在本例中为6个),其中包含m(3)个类型为'R1'的对象(例如{A,B,C})和n(2)个类型为'R2的对象'(例如{X,Y})。
对6个对象{AX,AY,BX,BY,CX,CY}进行评估,每个对象都按此顺序获得得分D,在这种情况下为{0.8,0.7,0.5,0.9,0.4,0.0}。

CL <- cbind(expand.grid(R2=LETTERS[24:25],R1=LETTERS[1:3],stringsAsFactors = FALSE),D=c(0.8,0.7,0.5,0.9,0.4,0.0))

现在我们要选择2个 distinct R1和1个R2,以使D的总和最大。

在此示例中,答案为R1 = {A,B},R2 = {Y}。

但是,不能得出这样的结论,例如,平均R最高的2个R1和R2。
它适用于R1,但​​不适用于R2:

aggregate(D~R1,CL,mean)
#  R1    D
#1  A 0.75
#2  B 0.70
#3  C 0.20
aggregate(D~R2,CL,mean)
#  R2         D
#1  X 0.5666667
#2  Y 0.5333333

我知道如何将其表达为线性规划问题;只是我不确定我的公式是否有效,因为基本上会导致m n + m + n变量和2 (m + n)+2约束的问题。
主要困难在于,我需要以某种方式计算选择的不同R1和R2的数量,除了下面将要说明的以外,我不知道有其他方法可以做到(并且在我的另一篇文章{{3}中也有介绍}。

这就是我要做的:

CL["Entry"] <- seq_len(dim(CL)[[1]])

R1.mat <- table(CL$R1,CL$Entry)
R2.mat <- table(CL$R2,CL$Entry)

N_R1 <- dim(R1.mat)[[1]]
N_R2 <- dim(R2.mat)[[1]]
N_Entry <- dim(CL)[[1]]

constr.mat <- NULL
dir <- NULL
rhs <- NULL

constr.mat <- rbind(constr.mat,cbind(R1.mat,-diag(table(CL$R1)),matrix(0,N_R1,N_R2)))
dir <- c(dir,rep("<=",N_R1))
rhs <- c(rhs,rep(0,N_R1))

constr.mat <- rbind(constr.mat,cbind(R2.mat,matrix(0,N_R2,N_R1),-diag(table(CL$R2))))
dir <- c(dir,rep("<=",N_R2))
rhs <- c(rhs,rep(0,N_R2))

constr.mat <- rbind(constr.mat,constr.mat)
dir <- c(dir,rep(">=",N_R1+N_R2))
rhs <- c(rhs,1-table(CL$R1),1-table(CL$R2))

constr.mat <- rbind(constr.mat,c(rep(0,N_Entry),rep(1,N_R1),rep(0,N_R2)))
dir <- c(dir,"==")
rhs <- c(rhs,2)

constr.mat <- rbind(constr.mat,c(rep(0,N_Entry),rep(0,N_R1),rep(1,N_R2)))
dir <- c(dir,"==")
rhs <- c(rhs,1)

obj <- c(aggregate(D~Entry,CL,c)[["D"]],rep(0,N_R1+N_R2))

例如lpSolve可以解决的问题:

sol <- lp("max", obj, constr.mat, dir, rhs, all.bin = TRUE,num.bin.solns = 1, use.rw=FALSE, transpose.constr=TRUE)
sol$solution
#[1] 0 1 0 1 0 0 1 1 0 0 1

显示已选择产品{AY,BY},对应于R1 = {A,B}和R2 = {Y}:

CL[as.logical(sol$solution[1:N_Entry]),]
#  R2 R1   D Entry
#2  Y  A 0.7     2
#4  Y  B 0.9     4

我发现在大问题上lpSolve被卡住了很长时间; Rsymphony似乎表现更好。
但是,我的主要问题是:制定LP的这种方式有效吗?我应该采取其他方式吗?

谢谢!


编辑

同时,针对一个有点相关的问题,我here指出,如果将一组“成本”(在此示例中为负)添加到“目标”的目标向量上,则只有一组约束可能就足够了。不同的R1和R2'变量。
所以这里,而不是:

obj <- c(aggregate(D~Entry,CL,c)[["D"]],rep(0,N_R1+N_R2))

我会做的:

obj <- c(aggregate(D~Entry,CL,c)[["D"]],rep(-1,N_R1+N_R2))

这将使 m + n 约束变得不必要。
即使对于较小的 m,n 来说,仍然仍然是一个巨大的问题,因此,如果有人可以建议如何做得更好...
我看过lp.transport,但这仅限于2个维度(例如,仅R1和R2,而不是R1,R2,R3),而且我认为您不能限制不同对象的数量这类求解器中的每个类别。

0 个答案:

没有答案