首先我会注意到您要求的最小值严格大于某个目标。一般来说,“严格大于”和“严格小于”约束比“大于或等于”或“小于或等于”约束要困难得多。如果您有所有整数值,那么您可以简单地将您的约束“总和超过 100”转换为“总和大于或等于 101”。我假设你已经为剩下的问题做了这样的转变。
一种方法是将其视为整数优化问题,其中每个数字的二元决策变量y_i 是我们是否包含它。那么我们的目标是最小化数字的总和,可以建模为:
min x_1*y_1 + x_2*y_2 + ... + x_n*y_n
这种情况下的约束是数字的总和至少为 100:
x_1*y_1 + x_2*y_2 + ... + x_n*y_n >= 100
一般来说,这是一个难题(请注意,它至少与子集和问题一样难,即 NP 完全问题)。然而,现代优化求解器可能对您的问题实例足够有效。
要测试免费求解器对该问题的可扩展性,请考虑使用 R 中的 lpSolve 包实现以下实现(如果问题可行,则返回所选子集,否则返回 NA):
library(lpSolve)
min.subset <- function(x, min.sum) {
mod <- lp("min", x, matrix(x, nrow=1), ">=", min.sum, all.bin=TRUE)
if (mod$status == 0) {
which(mod$solution >= 0.999)
} else {
NA
}
}
min.subset(1:10, 43.5)
# [1] 2 3 4 5 6 7 8 9
min.subset(1:10, 88)
# [1] NA
为了测试可扩展性,我将从[1, 2, ..., 1000] 中随机选择n 元素,将目标总和设置为元素总和的一半。运行时是:
- 使用
n=100,它在 0.01 秒内运行
- 使用
n=1000,运行时间为 0.1 秒
- 使用
n=10000,运行时间为 8.7 秒
看来您可以解决超过 10k 个元素(使用所选分布)的问题,而无需太多计算挑战。如果您的问题对于我在这里使用的免费求解器来说太大了,您可以考虑 Gurobi 或 cplex,这两个商业求解器可免费用于学术用途,但在其他方面不是免费的。