Algorithm 如何分配存储桶中的元素数量,使其在一个范围内-算法

Algorithm 如何分配存储桶中的元素数量,使其在一个范围内-算法,algorithm,optimization,mathematical-optimization,knapsack-problem,np,Algorithm,Optimization,Mathematical Optimization,Knapsack Problem,Np,我一直在解决一个问题,比如说我有50个元素 n1,n2,n3,n50 现在我有一个有限数量的桶,比如说5个桶,这个桶只能容纳100到150个范围(这只是桶中元素的总和),但既不能小于100,也不能大于150 哪种算法最适合解决此问题,以便使用所有5个存储桶,并且使用所有元素(n1、n2、n3…) 如果未使用bucket或遗漏了任何元素,则算法只返回“InvalidConditionsFound” 我试过背包,它给你一个尽可能接近给定数字的组合,但如何使它在一个范围内,并确保它明智地选择,使所有的

我一直在解决一个问题,比如说我有50个元素
n1,n2,n3,n50

现在我有一个有限数量的桶,比如说5个桶,这个桶只能容纳100到150个范围(这只是桶中元素的总和),但既不能小于100,也不能大于150

哪种算法最适合解决此问题,以便使用所有5个存储桶,并且使用所有元素
(n1、n2、n3…)

如果未使用bucket或遗漏了任何元素,则算法只返回“InvalidConditionsFound”


我试过背包,它给你一个尽可能接近给定数字的组合,但如何使它在一个范围内,并确保它明智地选择,使所有的桶都装满了,而不是两个桶装满了150,另一个桶只有50,比如说,一种方法是将其建模为一个整数程序。假设有“m”个数字y_1、y_2、…、y_m和“n”个桶。定义变量x_ij,每个试图分配的数字都有一个索引“i”,每个bucket都有一个索引“j”。这些是二进制变量,指示每个数字是否分配给每个桶

现在有两组逻辑约束。首先,您需要将每个数字恰好分配给一个bucket。您可以为每个数字“i”添加以下约束:

每个铲斗“j”上也有范围限制:

我用从
[1,2,…,10]
中随机抽样的
m
权重、桶的可接受范围
[100150]
和桶的总数
n=上限(5.5*m/125)
进行了测试。我看到了以下运行时扩展:

  • m=100,n=5
    :0.1秒
  • m=200,n=9:0.6秒
  • m=300,n=14
    :2.2秒
  • m=400,n=18
    :16.9秒
对于一打桶和几百个权重(以及这种权重向量结构)的问题,似乎可以使用自由解算器精确地解决这个问题。当然,您的复杂度结果表明,它无法有效地解决巨大的问题,但您可能能够解决您感兴趣的大小的实例。可通过以下方式进一步优化:

  • 使用商业解算器,如Gurobi或cplex(两者一般都不是免费的,但可免费用于学术用途)
  • 以稀疏格式输入约束矩阵

  • 听起来像是一个k-划分问题,通常被称为,因为这个问题是NP完全的,所以不会有一个“有效”的解决方案。然而,如果你在互联网上四处看看,我相信你可以找到大量的代码示例,这样你和你的(*cough*)“同事们”就可以解决这个问题。

    桶范围是指必须包含在其中的总和,还是指桶中各个数字的范围?我是否正确地认为只有满足约束条件(即每个桶在100和150之间;使用所有元素),但除此之外,不要求找到“最佳”解决方案。你尝试过什么?它的性能如何,或者如果不起作用,在什么情况下会出现问题?你有代码吗?嘿,你能告诉我你的问题中元素和桶的最大数量是多少吗?嗨@TimBiegeleisen,这是bucketI中的数字之和。我不相信经典的箱子包装支持非零下限对于分配给每个箱子的数量,尽管许多变体中可能有一个允许这些限制。嗨@Glubus,我不明白这是一个简单的分区问题。请你解释一下。背包是箱子包装问题的一个特例,如果我没有错的话,那么你是不是打算建议使用背包?我已经实现了但是它没有达到问题中提到的情景Hey Argho,不可否认,我没有做足够的研究来为你的问题提供一个直接的解决方案(我目前正在工作,所以我不能真正深入研究)。但是,我觉得您的问题看起来像垃圾箱包装问题,因此我希望您可以通过操纵不同问题的现有解决方案来找到或创建解决方案。我建议您阅读不同问题的问题/解决方案,并了解您是否可以为自己的问题找到解决方案。如果我有时间今晚我自己来试一试。如果你觉得你需要一个更快的解决方案,而你又不想阅读论文之类的东西,看看@josilber的答案,这是一种不同的方法,但将你的问题建模为一个整数问题可能行得通!嘿@Josiber,如果你能提供任何sudo代码或视频教程,我正在尝试用java实现它您的实现链接将非常有帮助,再次感谢您的努力。!!@ArghoChatterjee我鼓励您尝试自己实现它,并在遇到任何实现问题时发布一个新问题。
    x_i1 + x_i2 + ... + x_in = 1
    
    100 <= y_1 x_1j + y_2 x_2j + ... + y_m x_mj <= 150
    
    library(lpSolve)
    range.assign <- function(weights, n, min.sum, max.sum) {
      m <- length(weights)
      one.mat <- t(sapply(1:m, function(i) c(replicate(n, 1*((1:m) == i)))))
      w.mat <- t(sapply(1:n, function(j) c(rep(0, m*(j-1)), weights, rep(0, m*(n-j)))))
      mod <- lp(objective.in = rep(0, n*m),
                const.mat = rbind(one.mat, w.mat, w.mat),
                const.dir = rep(c("=", ">=", "<="), c(m, n, n)),
                const.rhs = rep(c(1, min.sum, max.sum), c(m, n, n)),
                all.bin=TRUE)
      if (mod$status == 0) {
        apply(matrix(mod$solution, nrow=m), 1, function(x) which(x >= 0.999))
      } else {
        rep(NA, m)
      }
    }
    range.assign(1:5, 2, 5, 10)
    # [1] 1 1 1 1 2
    range.assign(1:5, 2, 5, 6)
    # [1] NA NA NA NA NA