假设我有一组对象S
。有一个算法f
,给定一组S
在其上构建某些数据结构D
:f(S) = D
。如果S
很大和/或包含截然不同的对象,则D
变大,到不可用的程度(即不适合分配的内存)。为了解决这个问题,我将S
拆分为几个非交叉子集:S = S1 + S2 + ... + Sn
并为每个子集构建Di
。使用n
结构的效率低于使用结构,但至少这样我可以适应内存约束。由于f(S)
的大小增长速度超过S
本身,因此Di
的组合大小远小于D
的大小。
然而,仍然希望减少n
,即子集的数量;或减少Di
的组合大小。为此,我需要以每个S
包含“相似”对象的方式拆分Si
,因为如果输入对象“足够相似”,f
将产生较小的输出结构彼此。
问题是虽然S
中对象的“相似性”和f(S)
的大小确实相关,但除了评估f(S)
和{之外,没有办法计算后者。 {1}}不是很快。
我目前的算法是将f
中的每个下一个对象迭代地添加到S
中的一个中,这样就可以最小化(在此阶段)组合Si
的增加尺寸:
Di
这给出了实际有用的结果,但肯定远非最佳(即最小可能的组合尺寸)。此外,这是慢。为了加快速度,我仅为for x in S:
i = such i that
size(f(Si + {x})) - size(f(Si))
is min
Si = Si + {x}
size(f(Si + {x})) - size(f(Si))
计算i
,x
与Si
中已有的对象“足够相似”。
对这类问题有任何标准方法吗?
我知道分支和边界算法系列,但它不能在这里应用,因为它会非常慢。我的猜测是,在合理的时间内计算S
到Si
的最佳分布是不可能的。但是有一些常见的迭代改进算法吗?
修改
正如评论所指出的,我从未定义过“相似性”。事实上,我想要的只是分割Si
这样的子集Di = f(Si)
,其中sum f(Si)
的总大小最小或至少足够小。 “相似性”仅被定义为这样,遗憾的是简单地无法计算。我确实有一个简单的近似,但它只是 - 近似。
所以,我需要的是一种(可能是启发式的)算法,它可以最小化{{1}},因为有没有计算后者的简单方法 - 只有近似值我用来抛弃那些不太可能取得好成绩。
答案 0 :(得分:1)
关于缓慢我发现在类似的问题中,一个足够好的解决方案是通过选择固定数量的随机候选者来计算匹配。
是的,结果不是最好的(通常比你实施的完整“贪婪”解决方案更糟糕)但是根据我的经验并不太糟糕你可以决定速度......它甚至可以在一个规定的时间(即在分配的时间到期之前一直搜索)。
我使用的另一个选择是继续搜索,直到我看到暂时没有改善。
为了超越贪婪的逻辑,你可以保留一个N“x”元素的队列,并试图将它们同时打包成“k”组(k