3

可重现的例子:

我用R中的lpSolveAPI描述了一个简单的0/1- Knapsack问题,它应该返回 2 个解决方案:

library(lpSolveAPI)

lp_model= make.lp(0, 3)
set.objfn(lp_model, c(100, 100, 200))
add.constraint(lp_model, c(100,100,200), "<=", 350)
lp.control(lp_model, sense= "max")
set.type(lp_model, 1:3, "binary")

lp_model
solve(lp_model)
get.variables(lp_model)
get.objective(lp_model)
get.constr.value((lp_model))
get.total.iter(lp_model)
get.solutioncount(lp_model)

问题:

get.solutioncount(lp_model)表明只1找到了解决方案:

> lp_model
Model name: 
           C1   C2   C3         
Maximize  100  100  200         
R1        100  100  200  <=  350
Kind      Std  Std  Std         
Type      Int  Int  Int         
Upper       1    1    1         
Lower       0    0    0         
> solve(lp_model)
[1] 0
> get.variables(lp_model)
[1] 1 0 1
> get.objective(lp_model)
[1] 300
> get.constr.value((lp_model))
[1] 350
> get.total.iter(lp_model)
[1] 6
> get.solutioncount(lp_model)
[1] 1

我希望有 2 个解决方案:1 0 10 1 1.

我试图通过lpSolvenum.bin.solns参数,但解决方案的数量仍然存在。solve(lp_model, num.bin.solns=2)1

问题:

我怎样才能得到两个正确的解决方案?我更喜欢使用lpSolveAPI,因为 API 非常好。如果可能的话,我想避免直接使用lpSolve

4

1 回答 1

5

看起来那是坏了。以下是针对您的特定型号的 DIY 方法:

# first problem
rc<-solve(lp_model)
sols<-list()
obj0<-get.objective(lp_model)
# find more solutions
while(TRUE) {
   sol <- round(get.variables(lp_model))
   sols <- c(sols,list(sol))
   add.constraint(lp_model,2*sol-1,"<=", sum(sol)-1)
   rc<-solve(lp_model)
   if (rc!=0) break;
   if (get.objective(lp_model)<obj0-1e-6) break;
}
sols

这个想法是通过添加约束来切断当前的整数解。然后解决。当不再是最佳或目标开始恶化时停止。是一些数学背景。

您现在应该看到:

> sols
[[1]]
[1] 1 0 1

[[2]]
[1] 0 1 1

更新

在下面的评论中,有人询问为什么切割系数的形式为2*sol-1。再看看推导。这是一个反例:

           C1   C2        
Maximize    0   10        
R1          1    1  <=  10
Kind      Std  Std        
Type      Int  Int        
Upper       1    1        
Lower       0    0       

使用“我的”削减这将产生:

> sols
[[1]]
[1] 0 1

[[2]]
[1] 1 1

而使用建议的“错误”削减只会:

> sols
[[1]]
[1] 0 1
于 2015-12-12T21:25:05.520 回答