我正在寻找一种解决方案,以便在更大的集合中找到尽可能接近目标数字的数字子集。例如,我有一组值:
c(55.14, 26.22, 76.69, 37.77, 32.7, 48.71, 7.59, 21.37, 33.54, 3.95, 16.41,
20.56, 24.74, 26.5, 4.72, 32.99, 130.15, 27.27, 20.56, 41.21, 13, 16.41, 88.25,
1.95, 68.2, 34.3, 51.75, 8.93, 8.38, 30.45, 34.89, 42.91, 19.42, 13.62, 9.73,
20.86, 21.5, 37.46, 14.4, 26.61, 55.31, 24.03)
我的目标是1262.2。
如何在完整集中找到最小化目标1262.2与子集之和之差的值的子集?
答案 0 :(得分:6)
让v
成为问题中显示的值的向量。
令x
为包含0-1变量的相同长度的未知向量。
然后在x
上运行这两个整数线性程序,从目标最接近1262.2的解决方案中选择解决方案。 (这里*表示内在产品。)
max(v*x) such that v*x <= 1262.2
min(v*x) such that v*x >= 1262.2
使用Rglpk作为第一个,我们得到了这个,因为我们完全达到1262.2,我们不需要打扰第二个整数线性程序:
library(Rglpk)
ans <- Rglpk_solve_LP(v, t(v), "<=", 1262.2, max = TRUE, types = "B")
,并提供:
> ans[1:3]
$optimum
[1] 1262.2
$solution
[1] 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 1
$status
[1] 0
注意第一个整数线性程序称为背包问题,我们可以使用adagio中的knapsack
来解决它。
library(adadgio)
v100 <- as.integer(100 * v)
knapsack(v100, v100, 126220L)
(虽然在帮助页面上没有提到,背包需要整数参数。)