さまざまなサイズの長方形を、かなり最適な方法で可能な最小の長方形にパックするには、どのアルゴリズムを使用できますか?


273

私は可能な限り最小のスペースにパックする必要がある長方形のオブジェクトの束を得ました(このスペースの寸法は2の累乗でなければなりません)。

アイテムを可能な限り特定のスペースにパックするさまざまなパッキングアルゴリズムを知っていますが、この場合、そのスペースの大きさを計算するアルゴリズムも必要です。

たとえば、Iveが次の長方形を取得したとしましょう

  • 128 * 32
  • 128 * 64
  • 64 * 32
  • 64 * 32

それらは128 * 128スペースに詰めることができます

 _________________
| 128 * 32 |
| ________________ |
| 128 * 64 |
| |
| |
| ________________ |
| 64 * 32 | 64 * 32 |
| _______ | ________ |

ただし、160 * 32と64 * 64もある場合、256 * 128のスペースが必要です。

 ________________________________
| 128 * 32 | 64 * 64 | 64 * 32 |
| ________________ | | _______ |
| 128 * 64 | | 64 * 32 |
| | _______ | _______ |
| | |
| ________________ | ___ |
| 160 * 32 | |
| ____________________ | ___________ |

一連の四角形をパックし、コンテナーに必要なサイズを決定できる(2の累乗で、各次元の指定された最大サイズ内にある)アルゴリズムは何ですか?


6
2番目のソリューションは最適ではありませんか?128×224にすべきではないでしょうか。
Mantas

「この空間の次元は2のべき乗である必要があります」したがって、違いはありません。これは、2のべき乗ではないことは、基礎となるハードウェアによって無条件にサポートされると想定できないためです。
ファイアランサー

2
とにかくそれは結局アルゴリズムをより単純にしました(ntoなら64x32、次に64x64、128x64などを試してください):)
Fire Lancer


ここに1つのタイプのブルートフォースソリューションを配置します。stackoverflow.com/a/47698424/1641247
Sean

回答:


67

迅速でダーティな最初のパスソリューションは、他に何もない場合の比較として、常に最初から優れたソリューションです。

大から小への貪欲な配置。

残っている最大の長方形をパック領域に入れます。どこにも収まらない場合は、パック領域をできるだけ広げない場所に配置してください。最小の長方形で終わるまで繰り返します。

完璧ではありませんが、簡単で素晴らしいベースラインです。それでも元の例は完全にパックされ、2番目の例でも同等の答えが得られます。


1
私はちょっとした紙の上でそのようなもので遊んでいました、今はほとんどの場合、長方形などを回転させなくてもかなり最適に見えます
Fire Lancer '31

1
私はそれを実装し、それを介して大量のテストデータを実行しましたが、少し無駄なデータを残すだけでかなり良い仕事をしているようです。ここで、使用可能なスペースを介して各四角形の線形検索よりも効率的になるように実装を書き換える必要があります。各ピクセルが(既存のすべての四角形に対して)ブロックされているかどうかを確認します...
Fire Lancer

4
最適なソリューションは、jair.org / media / 3735 / live
Jim

2
これがどれほど最適に機能するかを想像するのに苦労しました。だから私はそれを(正方形の形で)コード化しました、そして結果は素晴らしいです。これがデモアニメーションです。imgur.com
Attila

@JimBalter正方形のスペースは賢い...おそらく...速度とスケーラビリティの点で?あんまり?
Arek Bal

86

ソリューションの調査については、ARCプロジェクトのこのページを参照してください。実装の複雑さ/時間と最適性の間にはトレードオフがありますが、幅広いアルゴリズムから選択できます。

アルゴリズムの抜粋は次のとおりです。

  1. First-Fit Decreeasing Height(FFDH)アルゴリズム
    FFDHは、Rが適合する最初のレベルに次のアイテムR(高さを上げない)をパックします。Rに対応できるレベルがない場合、新しいレベルが作成されます。
    FFDHの時間の複雑さ:O(n・log n)。
    近似比:FFDH(I)<=(17/10)・OPT(I)+1; 17/10の漸近境界はタイトです。

  2. Next-Fit Decreeasing Height(NFDH)アルゴリズム
    NFDHは、Rが適合する場合、現在のレベルに次のアイテムR(増加しない高さ)をパックします。それ以外の場合、現在のレベルは「クローズ」され、新しいレベルが作成されます。
    時間の複雑さ:O(n・log n)。
    近似比:NFDH(I)<= 2・OPT(I)+1; 2の漸近境界はタイトです。

  3. 高さの最適な減少高さ(BFDH)アルゴリズム
    BFDHは、Rを収容できるものの中で、次のアイテムR(増加しない高さ)をRにパックします。Rに対応できるレベルがない場合、新しいレベルが作成されます。

  4. 左下(BL)アルゴリズム
    BL増加しない幅でアイテムを最初に注文します。BLは、次のアイテムを収まるように一番下の近くにパックし、次にパックされたアイテムとオーバーラップせずに移動できるように左の近くにパックします。BLはレベル指向のパッキングアルゴリズムではないことに注意してください。
    時間の複雑さ:O(n ^ 2)。
    近似比:BL(I)<= 3・OPT(I)。

  5. ベイカーのアップダウン(UD)アルゴリズム
    UDはBLとNFDHの一般化の組み合わせを使用します。ストリップとアイテムの幅は、ストリップがユニット幅になるように正規化されます。UDは、増加しない幅でアイテムを並べ替え、アイテムを5つのグループに分割します。各グループは、幅が(1/2、1]、(1 / 3,1 / 2]、(1 / 4,1 / 3 ]、(1 / 5、1 / 4]、(0、1 / 5]。ストリップも5つの領域R1、...、R5に分割されます。基本的に、(1 / i + 1、1 / i]、1 <= i <= 4の場合、BLによって領域Riにパックされます。BLはストリップの右側に上から下に向かって幅が広がるスペースを残すため、UDは最初にこの利点を利用します上から下へ、j = 1、…、4(順番)のRjにアイテムを梱包します。そのようなスペースがない場合、アイテムはBLによってRiに梱包されます。最後に、サイズが最大1/5のアイテム(一般化された)NFDHアルゴリズムによって、R1、...、R4のスペースにパックされます。
    概算比:UD(I)<=(5/4)・OPT(I)+(53/8)H(Hはアイテムの最大の高さ)。5/4の漸近境界はタイトです。

  6. リバースフィット(RF)アルゴリズム
    RFは、ストリップとアイテムの幅を正規化して、ストリップの幅をユニット幅にします。RFはまず、幅が1/2より大きいすべてのアイテムをスタックします。残りのアイテムは増加しない高さで並べ替えられ、1/2を超える高さH0より上にパックされます。次に、RFは次のプロセスを繰り返します。大まかに言えば、RFはアイテムが左から右に、余白がなくなるまで高さH0の線に沿って下からパックします。次に、全幅が少なくとも1/2になるまで、アイテムを右から左、上から下(逆レベルと呼ばれます)にパックします。次に、(少なくとも)そのうちの1つが下の項目に触れるまで、逆レベルがドロップダウンされます。ドロップダウンは何とか繰り返されます。
    近似比:RF(I)<= 2・OPT(I)。

  7. スタインバーグのアルゴリズム
    論文ではMと表記されているスタインバーグのアルゴリズムは、すべてのアイテムをパックするために必要な高さHの上限を推定し、入力アイテムを幅Wと高さHの長方形にパックできることが証明されるようにします。 7つの手順(7つの条件)を定義し、それぞれが問題を2つの小さな手順に分割し、それらを再帰的に解決します。扱いやすい問題は、7つの条件のいずれかを満たしていることが示されています。
    近似比:M(I)<= 2・OPT(I)。

  8. Split-Fitアルゴリズム(SF)SFは、アイテムを2つのグループに分割します。L1は幅が1/2より大きく、L2は最大で1/2です。L1のすべてのアイテムは、FFDHによって最初にパックされます。次に、幅が2/3を超えるすべてのアイテムが、幅が最大で2/3のアイテムの下になるように配置されます。これにより、幅1/3のスペースの長方形Rが作成されます。次に、L2の残りのアイテムはRにパックされ、その上のスペースはFFDHを使用してL1がパックされたアイテムの上に置かれます。Rで作成されたレベルは、L1のパッキングより上で作成されたレベルの下にあると見なされます。
    近似比:SF(I)<=(3/2)・OPT(I)+ 2; 3/2の漸近境界はタイトです。

  9. Sleatorのアルゴリズム
    Sleaterのアルゴリズムは4つのステップで構成されています。

    1. 幅が1/2を超えるすべてのアイテムは、ストリップの下部で互いの上にパックされます。h0が結果のパッキングの高さであると仮定します。その後のパッキングはすべてh0より上で行われます。

    2. 残りのアイテムは、増加しない高さで注文されます。アイテムのレベルは、高さh0の線に沿って左から右へ(高さの昇順ではない)パックされます。

    3. 次に、中央に垂直線を引き、ストリップを2つの等しい半分にカットします(この線は、右半分に部分的に詰め込まれたアイテムをカットする場合があることに注意してください)。2つの線がどのアイテムにも交差しないように、長さの半分、左半分(左ベースラインと呼ばれる)と右半分(右ベースラインと呼ばれる)の横にある2つの水平線セグメントをできるだけ低く描画します。

    4. より低い高さの左または右のベースラインを選択し、次のアイテムが広すぎるまで、アイテムのレベルをストリップの対応する半分にパックします。

    新しいベースラインが形成され、すべてのアイテムが梱包されるまで、下のベースラインでステップ(4)が繰り返されます。
    時間の複雑さ:O(n・log n)。
    Sleatorのアルゴリズムの近似比は2.5で、これはタイトです。


6
これらはすべて、スペースの幅を知っている必要があります。
Quantum7 2015年

1
OPは辺が2の累乗である必要があるため、@ Quantum7はあまり重要ではない可能性があります。したがって、十分な面積を持つ一連の次元を試すことができます。
Ciro Santilli郝海东冠状病六四事件法轮功

19

梱包の問題ご覧ください。あなたの物は「2Dビンパッキング」に該当すると思います。その解決策や他の梱包の問題から多くを学ぶことができるはずです。

長方形の画像データを正方形のテクスチャにパックする」も参照してください


:ここでは最適化の矩形パッキングアルゴリズムの別の良い例だcodeproject.com/Articles/210979/...
アンダーソングリーン

en.wikipedia.org/wiki/…でも言及されている問題特に、これにより、ビンのパッキングはサイズが不明な単一のビンに制限されます。
Ciro Santilli郝海东冠状病六四事件法轮功

17

この問題に関する広範な文献があります。良い貪欲な発見的方法は、最大領域から最小領域までの長方形を、コンテナーの左下に向かって最初の使用可能な位置に配置することです。すべてのアイテムを左下隅まで引き下げる重力を考えてください。このグーグルの説明については「シャゼルの左下のパッキング」。

最適なソリューションを実現するために、最先端の技術では20秒を超える長方形を数秒でパックできます。フアンはアルゴリズムを持っています最小の囲みバウンディングボックスを見つける問題と、長方形のセットが特定のサイズのバウンディングボックスに収まるかどうかを決定する問題を区別する。あなたは彼のプログラムに長方形のセットを与え、それはそれらをパックするのに必要な最小の囲み境界ボックスを教えてくれます。

あなたのケースでは、外側のループは可能な限り小さいバウンディングボックスから上方向に反復する必要があります(幅と高さは2の累乗で連続的に増加します)。これらの境界ボックスのそれぞれについて、長方形のパッキングが見つかるかどうかをテストして確認します。最適なソリューションであることが保証される最初の「はい」の回答まで、一連の「いいえ」の回答が得られます。

アルゴリズムの内部ループ-特定のサイズの境界ボックスに対して「はい」または「いいえ」と答えるループの場合、私はHuang参照を調べ、彼のアルゴリズムを実装するだけです。彼は基本的なアルゴリズムに加えて多くの最適化を含んでいますが、本当に必要なのは基本的な肉とジャガイモだけです。回転を処理したいので、検索中のすべての分岐点で、両方の回転が結果として解決しない場合は、両方の回転とバックトラックを試してください。


9

これはNP難しい問題であるとかなり確信していますでため、最適な解決策として、可能なすべての組み合わせを試すバックトラッキングアルゴリズムを実装する必要があります。

良いニュースは、限られた2Dスペースに2Dの長方形をパックする必要があるため、多くの可能性を早い段階で切り捨てることができるので、それほど悪くはないかもしれません。


3
あなたはおそらくNP完全を意味します。
starblue

7
まあ、それがNP完全であれば、簡単に解決できます。巡回セールスマンの同等のインスタンスを解くだけで、あとは問題ありません。しかし、NP完全な問題は決定問題(はい/いいえの答えを返す)であり、多項式時間検証アルゴリズムがあるため、提起されたとおりではないことを示すのは簡単です。質問は「256 * 128はNP完全可能性がより少ない面積を取る長方形、B、C ...の配置があります。
エクリプス

2
@Eclipseは正しいです。jair.org/media/3735/live-3735-6794-jair.pdfから「最適化の問題はNP困難ですが、長方形のセットを特定の境界ボックスにパックできるかどうかを決定する問題はNP完全です。ビンパッキングからの削減による(Korf、2003)。」ただし、OPは「かなり最適な方法」を要求し、Pには「フェアリー」の十分に広い定義のための解決策があることに注意してください。
ジムバルター2015年

私もNP困難を疑っていますが、参照/証明が必要です。
Ciro Santilli郝海东冠状病六四事件法轮功

2
聖なる糸のネクロ、バットマン。これは、パッキング問題であり、すでに最高の状態でNP困難であることが証明されています:en.wikipedia.org/wiki/Packing_problems
Blindy

2

必要なものは、 https://github.com/nothings/stb/blob/master/stb_rect_pack.hです。

サンプル:

stbrp_context context;

struct stbrp_rect rects[100];

for (int i=0; i< 100; i++)
{
    rects[i].id = i;
    rects[i].w = 100+i;
    rects[i].h = 100+i;
    rects[i].x = 0;
    rects[i].y = 0;
    rects[i].was_packed = 0;
}

int rectsLength = sizeof(rects)/sizeof(rects[0]);

int nodeCount = 4096*2;
struct stbrp_node nodes[nodeCount];


stbrp_init_target(&context, 4096, 4096, nodes, nodeCount);
stbrp_pack_rects(&context, rects, rectsLength);

for (int i=0; i< 100; i++)
{
    printf("rect %i (%hu,%hu) was_packed=%i\n", rects[i].id, rects[i].x, rects[i].y, rects[i].was_packed);
}

1

一般的な解決策は簡単ではありません(数学では完全に****不可能
と言われています)一般に人々は遺伝的アルゴリズムを使用して可能な組み合わせを試しますが、最大の形状を最初に配置してから別の場所を試すだけでかなりうまくいくことができます次に大きいなど。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.