我在矩形容器中最佳放置具有不同尺寸和数量的矩形对象时遇到问题。这个问题可以通过2D bin打包算法完美解决,但只能在空容器上解决。对我来说,几乎总是不是这样。我的容器可以有一个没有物体放置的受限制的地方。 Packing example
当然,我不是第一个遇到这种问题的人,我希望有人已经为此制定了一个很好的解决方案。一切都很好:书籍参考,文章,代码片段等。 正式算法优先考虑神经网络和这类事物。
答案 0 :(得分:0)
解决这个问题的一种可能方法是使用整数线性编程。有不同的模型,但这里有一个简单的模型(有一点问题,但如果有必要,你可以对此进行改进)。
将问题拆分为主问题和子问题,主问题如下所示:
minimize sum(p)
s.t.
for all i: sum[j] p[j]*count[j,i] >= n[i]
p[i] >= 0 (and integer, don't add this constraint)
其中:
p
是决策变量,决定使用特定"包装的实例数量#34;将可用物品放入容器中。显然有太多这些要提前列出,但它们可以动态生成。count[j,i]
是打包j
包含项i
的次数。n[i]
是我们想要商品i
的次数。>=
,因为包装一些额外的物品是可以的,它可以让我们使用更少的不同包装(否则主要问题需要特殊的"故意不理想"填料能够实现约束)。从每个项目的几个哑包装开始,这样肯定有一些解决方案,尽管它可能很糟糕。您甚至可以将一个项放在容器中,即使不使用求解器来解决子问题也是如此,但是无论如何都必须解决子问题,因此您可以在此处重复使用它。
子问题是找出可以改进主问题的当前解决方案的包装。因此,考虑主问题行C
的双重成本(有多种不同的项目)并解决
maximize y.C
s.t.
1) for all i: y[i] <= n[i]
2) for all i: y[i] = sum[j] P[j] if j is a placement of item i
3) for all cells (a,b): sum[j] P[j] (if j covers a,b) <= 1
4) for all existing packings e: e.y <= sum(e) - 1
y >= 0 and integer
P boolean
其中,
y
是P
选项后面的隐含变量,y[i]
是项目i
出现在包装中的次数。P
是真正的决策变量,决定是否使用特定项目的特定展示位置。您的示例问题中有62个不同的项目展示位置,包括轮换。如果主要问题是常规线性程序,则不会重新创建列,但它是一个整数程序,并且在分支约束4之后需要明确防止重新创建。例如,在&#34; low&#34;分支(回想一下,这意味着我们采用了一些具有小数值k
并将其限制为f
的变量<= ⌊f⌋
,子问题尝试做的第一件事就是重新创建与k
对应的相同包装,以便可以将其添加到主问题中以撤消损坏&#34;。这与我们需要的完全相反。因此必须禁止重新创建列。
约束4不是一个很好的方法,因为现在的子问题将尝试生成所有等效的包,这要归功于对称性。例如,在对该包装的变量进行四舍五入后:
它生成如下的等效包装:
等。有很多这些,并且它们都没有意义,因为它并不重要(对于主问题的客观值,当考虑整数约束时) where 1x3件,重要的是包装包含1x3件和14件1x1件。
理想情况下,约束4将被更复杂的东西所取代,这些东西禁止将等效包装到之前的任何东西,但是其他主要工作的东西是首先尝试高分支。至少在这个例子中,这很好。
在此示例中,在添加允许主问题最佳的列(但在任何分支之前仍为小数)之后,目标值为5.5882352941176467。这已经意味着我们知道我们至少需要6个容器,因为这是最佳的小数值,证明它不能用5来完成,并且不能选择分数个容器。
快速找到一个包含6个容器的解决方案,即
其中包括所有部件以及额外的1x4件和3件额外的1x1件。
该算法不依赖于碎片或容器的形状,除了它们必须可以表示为网格上的单元格。容器可以在整个地方都有孔,这些部件可能更像俄罗斯方块,甚至还有断开的部件。缺点是它需要的放置列表与容器的大小有很大关系。