【发布时间】:2014-09-25 13:02:52
【问题描述】:
我问了一个基本上是背包问题的问题 - 我需要找到几个不同的对象数组的组合,以提供最佳输出。因此,例如,相对于每个对象的“成本”限制,来自对象的最高总“价值”。我在这里收到的答案如下 -
a.product(b,c)
.select{ |arr| arr.reduce(0) { |sum,h| sum + h[:cost] } < 30 }
.max_by{ |arr| arr.reduce(0) { |sum,h| sum + h[:value] } }
效果很好,但是当我进入 6 个数组,每个数组有大约 40 个选项时,可能的组合会超过 400 万个,并且处理时间太长。我对代码进行了一些更改,使处理速度更快 -
#creating the array doesn't take too long
combinations = a.product(b,c,d,e)
possibles = []
combinations.each do |array_of_objects|
#max_cost is a numeric parameter, and I can't have the same exact object used twice
if !(array_of_objects.sum(&:salary) > max_cost) or !(array_of_objects.uniq.count < array_of_objects.count)
possibles << array_of_objects
end
end
possibles.max_by{ |ar| ar.sum(&:std_proj) }
将它分成两个单独的数组对性能有很大帮助,因为我只需要检查 max_by 以了解符合标准的许多不太可能的组合。
有人看到优化此代码的方法吗?由于我通常处理数万或数百万个组合,因此任何一点点都会有很大帮助。谢谢。
【问题讨论】:
-
有没有人看到优化上述代码以使其处理速度更快的方法?有时代码中有数百万种可能的组合,所以任何一点点都可以提供帮助。
-
数组从何而来?也许你应该在数据库查询中这样做?
-
数组确实来自数据库,但它们不是瓶颈。就是代码中的处理。
-
你的previous question 清楚地表明你有一个背包问题,有一个额外的要求,使它成为NP-complete。在优化方面,“关闭”只算马蹄铁。尽可能聪明地枚举,你无法逃避这样一个事实,即组合的数量随着数组的数量和大小呈指数增长。您无法解决您提到的大小问题(8 个数组,50 个元素)。
-
@sawa,如果您无法在令人满意的时间内计算出最优值,那么请务必使用启发式方法来尝试获得“好的”解决方案。然而,这不是我们这里所拥有的。上面的代码解决了一个没有附带条件的背包问题。然而,为此,有一个更有效的直接动态编程解决方案(请参阅上一个问题)。然而,OP 想要添加一个额外的条件,有效地使得不可能获得感兴趣的问题大小的最佳解决方案,但他对启发式方法不感兴趣。
标签: ruby arrays optimization knapsack-problem