【问题标题】:How to find a combination of elements that sum up just above threshold value如何找到总和略高于阈值的元素组合
【发布时间】:2016-01-03 16:09:22
【问题描述】:

我有一个问题陈述:如果您有一个元素数组 {x1,x2,x3,...x10},请找到元素组合,使其总和高于阈值(例如阈值值为 100)。

所以如果存在x2+x5+x8 = 105x3+x5+x8=103x4+x5 = 101这样的组合,那么算法应该输出X4、X5。

背包算法发出的值接近但位于阈值较小的一侧(此处为 100)。我想要相反,即大于 100 的选定元素的最小总和。

是否有任何算法集或任何算法的任何特殊情况可以解决这个问题?

【问题讨论】:

  • 您可以尝试硬币找零算法的变体。优化的硬币变化可用于在 O(n) 空间中查找数字数组的所有子集的各个总和。但是跟踪哪个子集形成了那个特定的总和是很棘手的。见算法简化版here

标签: algorithm optimization mathematical-optimization genetic-algorithm knapsack-problem


【解决方案1】:

假设X 是所有x_i 的总和。然后等效地,您要求您的x_i 的最小子集,其总和最多为X - 100(因为这些x_i 的补充将是您问题的最佳解决方案)。所以所有的背包理论都可以在这里应用。

在实践中(非常大的实例),我建议使用 this 形式的 Nemhauser-Ullman 泛化,它可以解决具有数百万个对象的实例。

【讨论】:

    【解决方案2】:

    首先我会注意到您要求的最小值严格大于某个目标。一般来说,“严格大于”和“严格小于”约束比“大于或等于”或“小于或等于”约束要困难得多。如果您有所有整数值,那么您可以简单地将您的约束“总和超过 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,这两个商业求解器可免费用于学术用途,但在其他方面不是免费的。

    【讨论】:

    • 嘿@Josiber,我正在尝试用java实现它,如果你能提供你的实现的任何sudo代码或视频教程链接真的会很有帮助,再次感谢你的努力。!!!!!!
    • @ArghoChatterjee 我鼓励您尝试自己实施它并发布一个新问题,如果您遇到任何实施问题。
    猜你喜欢
    • 1970-01-01
    • 2020-06-04
    • 2016-12-11
    • 2018-11-19
    • 2021-09-25
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多