首页 > 解决方案 > 如何在 LPSolve 中实现二元约束?

问题描述

我正在尝试通过使用线性规划来解决优化问题。我有一份我知道多种营养素含量的产品清单。然后,目标是找到最接近特定营养素需求的产品组合。在 RI 中写了一个脚本可以解决这个问题。

library(lpSolveAPI)

# Required nutrients
nitrogen = 1500
phosphate = 530

# Product properties (sample dataset, this will later be expanded with more products and nutrients)
products <- data.frame(
  p1 = c(0.2, 0.1),
  p2 = c(0.8, 0),
  p3 = c(0.15, 0.2),
  p4 = c(0.1, 0.25),
  p5 = c(0, 0.4)
)

# Create model
model <- make.lp(nrow = 2, ncol = ncol(products))

# Add the products as decisions
for (p in 1:ncol(products)) {
  set.column(model, p, products[, p])
}

# Set the required amount as constraint 
set.constr.value(model, rhs = c(nitrogen, phosphate))
set.constr.type(model, types = c(2,2))

# Set the objective function
set.objfn(model, rep(1, ncol(products)))
lp.control(model, sense='min')

solve(model)
get.objective(model)

但是,我现在想添加一个限制,即不能使用超过一定数量(例如 2 个)的产品。我正在考虑添加一个二进制约束,但不知道如何实现它。我能够发现的唯一选择是将决策变量设置为二进制,但这不能选择使用产品的多个单元。

那么如何添加限制以不使用超过 2 或 3 个产品?

标签: roptimizationconstraintslinear-programminglpsolve

解决方案


总是先写下数学模型。尤其是低级输入格式的情况。从想法到代码的步骤太大了。

所以你基本上有:

min sum(j, x(j))
st  sum(j, a(i,j)*x(j)) >= b(i)  for i=1,2
    x(j) >= 0      

现在您要计算非零变量。这需要额外的二进制变量和 x(j) 的一些界限。

min sum(j, x(j))
st  sum(j, a(i,j)*x(j)) >= b(i)  for i=1,2
    x(j) <= U(j)*y(j)
    sum(j, y(j)) <= 2 (or 3)
    y(j) ∈ {0,1} 
    0 <= x(j) <= U(j)      

我会把它留给你把它转录成代码。请注意,当模型变得有点复杂时,CVXR 或 OMPR 可能比 LpSolveAPI 更易于使用。


推荐阅读