公平地将集合S划分为k个分区

时间:2011-06-23 14:27:29

标签: algorithm set heuristics data-partitioning np-hard

存在包含N个整数的集合S,每个整数具有值1 <= X <= 10 ^ 6。问题是将集合S划分为k个分区。分区的值是其中存在的元素的总和。分区将以这样的方式完成,集合S的总值在k个分区之间公平分配。 fair 的数学含义也需要定义(例如,目标可以是最小化分区值与集合S的平均值的标准偏差(即,和(S) / k))的

e.g。 S = {10,15,12,13,30,5},k = 3

一个好的分区是{30},{10,15},{12,13,5}

错误的分区是{30,5},{10,15},{12,13}

第一个问题是在数学上表达一个分区的条件要好于另一个分区。 第二个问题是如何解决问题。问题是NP-Hard。有任何启发式吗?

在我试图解决的问题中,N&lt; =(k * logX)^ 2,K从2变为7。

=============================================== ===================================

根据其他相关的SO问题,评估分布有两个合理的功能:

a)使用最大值最小化分区的值。

再想一想,这不是一个好的指标。考虑一组{100,40,40}被分成三个子集。该指标不区分以下两个分布,即使一个明显优于另一个。

分发1:{100},{40},{40}和分发2:{100},{40,40},{}

b)最小化给定分区中任何两个值的差异的最大值,即最小化max | A-B |任何A,B

3 个答案:

答案 0 :(得分:6)

我认为一个好的指标是:

let the result set be s1,s2,...,sk
let MAX be max{sum(si) for each i}
f({s1,...,sk}) = Sigma(MAX-sum(si)) for each i)

好处:完美的分配将永远为0!
缺点:如果没有perferct解决方案,最好的结果将不会产生0。

这个问题的贪心启发式将是:

sorted<-sort(S) (let's say sorted[0] is the highest)
s1=s2=...=sk= {}
for each x in sorted:
   s <- find_min() (*)
   s.add(x)

其中find_min()产生s,使得每个si的sum(s)&lt; = sum(si)。

这个解决方案将产生f(上面定义的度量),使得f(sol) <= (k-1)*max{S}(从这里它是这个边界的证据):


声明:对于每个子集s,MAX- sum(s) <= max{S}
证明 - 通过归纳:在每一步,对于临时解决方案都是如此。
在每一步中,让MAX在迭代开始时(加法之前)为max {sum(si)}!

base: the set of subsets at start is {},{},.. MAX=sum(si)=0 for each si. 
step: assume the assumption is true for iteration i, we'll show it is also true for iteration i+1:
let s be the set that x was added to, then MAX-sum(s) <= max{S} (induction assumption).
if sum(s) + x <= MAX: we are done, MAX was not changed.
else: we sorted the elements at start, so x <= max{S}, and thus if s was chosen
   (sum(si) >= sum(s) for each si) and sum(s) + x > MAX then: for each si, sum(si) + x >=
   sum(s) + x, so sum(s)+x - sum(si) <= x <= max{S}. since sum(s)+x will be the MAX next 
   iteration, we are done.

因为对于每个集合MAX-sum(si) <= max{S}(显然,对于最大集合,MAX-sum(si)=0),在整体Sigma(MAX-sum(si)) <= (k-1)*max{S},正如所承诺的那样。

编辑: 我有一些空余时间,所以我编写了由我和@Akhil建议的两种启发式算法,两个指标,首先,两个结果都是结论性的(根据Wilcoxon的成对测试)但是哪个更好是由您选择的指标定义的,令人惊讶的是,试图最小化f()(@ Akhil`s)的算法对于同样的f得分较低,但对于第二个指标得分较高。 @Akhil's metrics graph

@Amit's metrics graph

答案 1 :(得分:1)

一种启发式方法是尽可能均匀地在袋子中散布较大的重量,留下足够小的重量,现在你留下一个具有大量自由度的子问题。如有必要,重复进入子子问题。这种启发式假设您的分布不是太几何,例如{1000} and {100, 10, 1},并略微假设您的惩罚函数将惩罚零指派或非常大的异常值。

例如:

distributeFairly(numbers, bins):
    distributeFairlySubproblem(numbers, bins):
        n = len(numbers)
        numElementsToDefer = min(-n//3,20*k)  # modify as appropriate, e.g. to avoid len(toPlace)<len(toDefer)

        toDefer = numbers[-numElementsToDefer:]
        toPlace = numbers[:-numElementsToDefer]

        newBins = shoveThemIn(toPlace, copy(bins))
        return distributeFairlySubproblem(toDefer, newBins)

    initialGuess = distributeFairlySubproblem(sorted(numbers,reverse=True), [[]]*k)
    return anneal(initialGuess)

答案 2 :(得分:1)

让度量最小化max(sum(si) - sum(sj))其中si和sj是集合S的结果分区中的任意两个子集。

假设我们有一个分布D,我们需要在分布D中包含另一个元素x。将它添加到子集s中,以使上面的度量最小化。

无法证明任何界限,但直觉说它会给出最佳的近似值?有资格证明自己的人吗?