一维嵌套算法

问题描述 投票:6回答:4

将1维长度嵌套到预定义的库存长度中的有效算法是什么?

例如,如果您需要以下数量和长度的钢筋,

  • 5 x 2米
  • 5 x 3米
  • 5 x 4米

这些可以从10米棒切割。你如何计算切割10米棒的模式,以便使用最小数量的棒?

另外,如何在算法中加入多个库存长度?


我有一些时间来处理这个问题,所以我要写下我是如何解决它的。我希望这对某人有用。我不确定是否可以像这样回答我自己的问题。如果更合适,主持人可以将此更改为答案。

首先感谢所有回答的人。这指出了适当的算法; the cutting stock problem

这篇文章也很有用; "Calculating a cutting list with the least amount of off cut waste"

好的,关于解决方案。

我将在我的解决方案中使用以下术语;

  • 库存:一定长度的材料将被切成小块
  • 切割:从库存中切割出的一段材料。可以从同一块库存中取出多个切口
  • 废物:在完成所有切割后留在一块原料中的材料长度。

解决问题有三个主要阶段,

  1. 确定所有可能的切割组合
  2. 确定可以从每个库存中获取哪些组合
  3. 找到最佳的切割组合组合。

步骤1

N切口有2 ^ N-1个独特的切割组合。这些组合可以表示为二元真值表。

A,B,C是独特的切口;

A B C | Combination
-------------------
0 0 0 | None
0 0 1 | C
0 1 0 | B
0 1 1 | BC
1 0 0 | A
1 0 1 | AC
1 1 0 | AB
1 1 1 | ABC

具有一些按位运算符的for循环可用于快速创建每个剪切组合的分组。

对于大的N值,这可能非常耗时。

在我的情况下,有多个相同的切割实例。这产生了重复的组合。

A B B | Combination
-------------------
0 0 0 | None
0 0 1 | B
0 1 0 | B (same as previous)
0 1 1 | BB
1 0 0 | A
1 0 1 | AB
1 1 0 | AB (same as previous)
1 1 1 | ABB

我能够利用这种冗余来减少计算组合的时间。我将重复的切割分组在一起并计算了该组的独特组合。然后,我将此组合列表附加到第二组中的每个唯一组合以创建新组。

例如,通过切割AABBC,过程如下。

A A | Combination
-------------------
0 1 | A 
1 1 | AA

将此组称为X.

将X附加到B的唯一实例,

B B X | Combination
-------------------
0 0 1 | A 
      | AA
0 1 0 | B
0 1 1 | BA
      | BAA
1 1 0 | BB 
1 1 1 | BBA
      | BBAA

叫这个组Y.

将Y附加到C的唯一实例,

C Y | Combination
-----------------
0 1 | A 
    | AA
    | B
    | BA
    | BAA
    | BB 
    | BBA
    | BBAA 
1 0 | C
1 1 | CA 
    | CAA
    | CB
    | CBA
    | CBAA
    | CBB 
    | CBBA
    | CBBAA 

此示例生成17个唯一组合,而不是31(2 ^ 5-1)。节省了近一半。

确定所有组合后,是时候检查它是如何适合库存的。

第2步

此步骤的目的是将步骤1中确定的切割组合映射到可用的库存大小。

这是一个相对简单的过程。对于每个切割组合,

   calculate the sum of all cut lengths.
   for each item of stock, 
        if the sum of cuts is less than stock length,
            store  stock, cut combination and waste in a data structure.
            Add this structure to a list of some sort.

这将生成有效嵌套剪切组合的列表。存储废物不是严格必要的,因为这可以根据切割长度和库存长度来计算。但是,存储废物会减少步骤3中所需的处理。

第3步

在这一步中,我们将确定产生最少浪费的切割组合。这基于步骤2中生成的有效嵌套列表。

在理想的世界中,我们将计算所有可能性并选择最佳可能性。对于任何非平凡的削减集合,计算它们都需要永远。我们必须满足于非最佳解决方案。有各种算法来完成这项任务。

我选择了一种方法来寻找浪费最少的巢。它将重复此操作,直到所有削减都被计算在内。

从三个列表开始

  • cutList:所有必需剪辑(包括重复剪辑)的列表。
  • nestList:在步骤2中生成的嵌套列表。这是从最低浪费到最高浪费的排序。
  • finalList:最初为空,这将存储将输出给用户的剪切组合列表。

方法

pick nest from nestList with the least waste
  if EVERY cut in the nest is contained in cutList
     remove cuts from cutList
     copy this nest into the finalList
  if some cuts in nest not in cutList
      remove this nest from nestList             
repeat until cutlist is empty

通过这种方法,我设法为一些典型的测试数据总浪费了大约2-4%。希望我能在某个时刻重新审视这个问题并开始实施Delayed column generation算法。这应该会产生更好的结果。

我希望这有助于其他人解决这个问题。

大卫

algorithm
4个回答
8
投票

实际上,还有一个更具体的问题适用:cutting stock problem

切割库存问题是优化问题,或更具体地,整数线性编程问题。它源于工业中的许多应用。想象一下,你在造纸厂工作,你有许多固定宽度的纸卷等待切割,但不同的客户需要不同数量的不同宽度的卷。你是如何切割卷,以尽量减少浪费(剩余的数量)?

这比包装问题更好的原因是因为你试图减少浪费,而不是减少“垃圾箱”的数量。从某种意义上说,垃圾箱包装问题与切割库存问题相反:如何在一定尺寸下将钢材长度重新组装成尽可能少的钢筋?


5
投票

1
投票

谢谢你建议装箱问题的基础。这导致我发表以下帖子,Calculating a cutting list with the least amount of off cut waste。这似乎很好地解决了我的问题


0
投票

解决了与今年类似的问题。我最终使用遗传算法。这对小问题来说太过分了。这个程序写起来有点有趣,但同时又不好玩,回到了16位的日子。

首先,它列出了使用给定长度可以切割10'块原材料的所有方法。每次记录浪费的材料量。 (虽然它是快速的数学运算,但以后存储它们的速度会更快。)然后它查看了所需的部分列表。在一个循环中,它将从切割方式列表中选择一种切割原料的方法,该方法不会切割任何尺寸超过要求的碎片。一个贪婪的算法会选择一个浪费最少的算法,但有时可以通过放松来找到更好的解决方案。最终遗传算法做出了选择,“DNA”是一些切割方式,在过去的解决方案中表现相当不错。

所有这一切都回到了互联网前的日子,在聪明和实验中被破解。这些天可能有一些.NET或java库的东西已经用黑盒子做了 - 但这样不那么有趣,教育也少了,不是吗?

© www.soinside.com 2019 - 2024. All rights reserved.