我正在尝试通过使用线性规划来解决优化问题。我有一个我知道多种营养素含量的产品清单。然后的目标是找到能够为特定营养需求提供最接近解决方案的产品组合。在R中,我编写了一个能够解决此问题的脚本。
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个?
总是先写下数学模型。对于低级输入格式尤其如此。从构思到编码的步骤太大了。
所以您基本上有:
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更易于使用。