Який алгоритм можна використовувати для упаковки прямокутників різних розмірів у найменший можливий прямокутник досить оптимальним способом?


273

У мене з'явилася купа прямокутних предметів, які мені потрібно упакувати в найменший можливий простір (розміри цього простору повинні бути двома потужностями).

Мені відомо про різні алгоритми упаковки, які найкраще запакуватимуть елементи у певний простір, однак у цьому випадку мені потрібен алгоритм, щоб розробити, наскільки має бути цей простір.

Скажімо, я отримав такі прямокутники

  • 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
Хіба друге рішення не є оптимальним? Чи не повинно бути 128 на 224?
Mantas Vidutis

"розміри цього простору повинні бути потужностями двох". Отже, це не має ніякої різниці, для чого це було / є для того, що я не можу припустити, що нежиття двох підтримується безумовно обладнанням.
Пожежний улан

2
У будь-якому випадку це спростило алгоритм у кінцевому підсумку (спробуйте помістити все це в 32x32, якщо nto, то спробуйте 64x32, потім 64x64, 128x64 тощо) :)
Fire Lancer


Я розміщую тут один тип грубої сили. Stackoverflow.com/a/47698424/1641247
Шон

Відповіді:


67

Швидке і брудне рішення першого проходу завжди чудове для початку, як порівняння, якщо нічого іншого.

Жадібне розміщення від великого до малого.

Покладіть найбільший прямокутник, що залишився в упакованій зоні. Якщо він не може поміститися ніде, помістіть його в місце, яке якнайменше розширює область упаковки. Повторіть, поки не закінчите з найменшим прямокутником.

Це зовсім не ідеально, але це легко і приємно. Він все-таки ідеально упакує ваш оригінальний приклад і дасть вам рівнозначну відповідь і на другий.


1
Я просто грав з чимось подібним на трохи паперу, зараз він виглядає досить оптимальним у більшості випадків, навіть не обертаючи прямокутники чи що-небудь інше
Fire Lancer

1
Я реалізував це і запустив через нього купу тестових даних, схоже, зробив досить непогану роботу, залишивши лише трохи витрачених даних. Тепер мені просто потрібно переписати мою реалізацію, щоб бути ефективнішою, ніж лінійний пошук для кожної прямої лінії через доступний простір, перевіряючи кожен піксель, ця точка заблокована (проти всіх існуючих ректів) ...
Fire Lancer

4
Оптимальне рішення дано в jair.org/media/3735/live-3735-6794-jair.pdf
Джим Балтер

2
Мені важко було намагатися уявити, наскільки оптимально це може працювати. Тому я зашифрував це (з квадратною формою), і результати чудові. Ось демо-анімація: imgur.com/ISjxuOR
Аттіла Таній

@ JimBalter квадратний простір мудрий ... напевно ... з точки зору швидкості та масштабованості? Не зовсім?
Арек Бал

86

Дивіться цю сторінку проекту ARC, щоб ознайомитись з рішеннями, існує компроміс між складністю / часом та оптимальністю впровадження, але існує широкий спектр алгоритмів на вибір.

Ось витяг із алгоритмів:

  1. Алгоритм зменшення висоти першого розміру (FFDH)
    FFDH пакує наступний елемент R (у зростаючу висоту) на перший рівень, де R підходить. Якщо жоден рівень не може вмістити R, створюється новий рівень.
    Часова складність FFDH: O (n · log n).
    Коефіцієнт наближення: FFDH (I) <= (17/10) · OPT (I) +1; асимптотична межа 17/10 є тісною.

  2. Алгоритм зменшення висоти "Next-Fit" (NFDH) "
    NFDH" пакує наступний елемент R (у зростаючу висоту) на поточний рівень, якщо R підходить. В іншому випадку поточний рівень "закритий" і створюється новий рівень.
    Часова складність: O (n · log n).
    Коефіцієнт наближення: NFDH (I) <= 2 · OPT (I) +1; асимптотична межа 2 щільна.

  3. Алгоритм зменшення висоти найкращого пристосування (BFDH)
    BFDH запаковує наступний елемент R (у зростаючу висоту) на рівні, серед тих, що можуть вмістити R, для якого залишковий горизонтальний простір є мінімальним. Якщо жоден рівень не може вмістити R, створюється новий рівень.

  4. Алгоритм знизу вліво (BL)
    BL позицій першого порядку за шириною, що не збільшується. BL упаковує наступний предмет так само ближче до нижнього, як він буде вміщуватися, а потім як можна ближче ліворуч, наскільки він може пройти, не перекриваючи жоден упакований предмет. Зауважте, що BL не є алгоритмом упаковки, орієнтованого на рівень.
    Часова складність: O (n ^ 2).
    Коефіцієнт наближення: BL (I) <= 3 · OPT (I).

  5. Алгоритм "Угору вниз" Бейкера
    UD використовує комбінацію BL та узагальнення NFDH. Ширина смуги та елементів нормалізується так, щоб смуга була одиничною шириною. UD упорядковує елементи з не збільшується шириною, а потім ділить їх на п'ять груп, кожна з шириною в діапазоні (1/2, 1], (1 / 3,1 / 2], (1 / 4,1 / 3 ], (1 / 5,1 / 4], (0,1 / 5]. Смуга також розділена на п’ять областей R1, ···, R5. В основному деякі елементи ширини в діапазоні (1 / i + 1, 1 / i], для 1 <= i <= 4, упаковуються в область Ri по BL. Оскільки BL залишає простір збільшення ширини зверху вниз в правій частині смуги, UD використовує цю перевагу спочатку упаковка предмета в Rj для j = 1, ···, 4 (для порядку) зверху вниз. Якщо немає такого місця, предмет упаковується в Ri по BL. Нарешті, розмір елементів не більше 1/5 упаковані в пробіли в R1, ···, R4 за алгоритмом (узагальненим) NFDH.
    Коефіцієнт наближення: UD (I) <= (5/4) · OPT (I) + (53/8) H, де H - максимальна висота елементів; асимптотична межа 5/4 є тісною.

  6. Алгоритм
    RF із зворотним приляганням (RF) також нормалізує ширину смуги та елементів так, щоб смуга була одиничною шириною. РФ спочатку укладає всі предмети шириною більше 1/2. Залишки відсортовані по висоті, що не збільшується, і будуть упаковані вище висоти H0, досягнутої на ті, що перевищують 1/2. Потім РФ повторює наступний процес. Грубо кажучи, РФ упаковує предмети зліва направо дном по лінії висоти H0, поки не залишиться місця. Потім упакуйте елементи праворуч ліворуч і зверху вниз (називаються зворотним рівнем), поки загальна ширина не буде не менше 1/2. Потім зворотний рівень опускається вниз, поки (принаймні) один з них не торкнеться якогось елемента нижче. Падіння вниз якось повторюється.
    Коефіцієнт наближення: RF (I) <= 2 · OPT (I).

  7. Алгоритм
    Штейнберга Алгоритм Штейнберга, позначений як M у статті, оцінює верхню межу висоти H, необхідної для упаковки всіх елементів, щоб було доведено, що елементи введення можуть бути упаковані у прямокутник шириною W і висотою H. Вони потім визначте сім процедур (із семи умовами), кожна з яких розділить проблему на дві менші та вирішить їх рекурсивно. Було показано, що будь-яка простежена проблема задовольняє одній із семи умов.
    Коефіцієнт наближення: M (I) <= 2 · OPT (I).

  8. Алгоритм Split-Fit (SF) SF розділяє елементи на дві групи, L1 шириною більше 1/2, а L2 максимум 1/2. Усі позиції L1 спочатку запаковуються FFDH. Потім вони розташовуються так, що всі предмети шириною більше 2/3 виявляються нижче розмірів шириною не більше 2/3. Це створює прямокутник R простору шириною 1/3. Залишилися елементи в L2 потім упаковуються в R, а простір вище тих, які упаковані L1, використовуючи FFDH. Рівні, створені в R, вважаються нижчими за рівні, створені над упаковкою L1.
    Коефіцієнт наближення: SF (I) <= (3/2) · OPT (I) + 2; асимптотична межа 3/2 є тісною.

  9. Алгоритм Sleator Алгоритм Sleater
    складається з чотирьох кроків:

    1. Усі предмети шириною більше 1/2 упаковуються один на одного в нижній частині смужки. Припустимо, h0 - висота отриманої упаковки. Усі наступні упаковки відбудуться вище h0.

    2. Залишилися елементи впорядковуються по зростаючій висоті. Рівень елементів упакований (у порядку, що не збільшується) зліва направо по лінії висоти h0.

    3. Потім посередині прорисовується вертикальна лінія, щоб розрізати смужку на дві рівні половини (зверніть увагу, що ця лінія може вирізати предмет, який частково упакований у правій половині). Накресліть два відрізки горизонтальної лінії довжиною одна половина, один через ліву половину (називається лівою базовою лінією) та один поперек правої половини (називається правою базовою лінією) якомога нижче, щоб дві лінії не перетинали жоден предмет.

    4. Виберіть ліву або праву базову лінію, яка має меншу висоту, і запакуйте рівень елементів у відповідну половину смужки, поки наступний елемент не стане занадто широким.

    Формується нова базова лінія, і крок (4) повторюється на нижній базовій лінії, поки всі елементи не будуть упаковані.
    Часова складність: O (n · log n).
    Коефіцієнт наближення алгоритму Слятора становить 2,5, що є щільним.


6
Все це вимагає знати ширину простору.
Quantum7

1
@ Quantum7, можливо, не надто важливий, оскільки ОП вимагає, щоб сторони були двома силами, тому ми могли просто спробувати купу розмірів з достатньою площею.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

19

Погляньте на проблеми з упаковкою . Я думаю, що ваша підпадає під "2D упаковку у смітник". Ви повинні мати можливість багато чого навчитися вирішувати проблеми та інші проблеми з упаковкою.

Також дивіться: Укладання даних прямокутного зображення в квадратну текстуру.


Ось ще один приємний приклад оптимізуючого алгоритму пакування прямокутника: codeproject.com/Articles/210979/…
Андерсон Грін

Проблема також згадується у: en.wikipedia.org/wiki/… Помітно, це обмежує упаковку контейнера до одного бака невідомого розміру, мені цікаво, чи він досі не заповнений NP.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

17

Про цю проблему існує велика література. Хорошим жадібним евристикою є розміщення прямокутників від найбільшої площі до найменшої у першому доступному положенні у напрямку до дна та зліва від контейнера. Подумайте про тяжкість, тягнучи всі предмети до лівого нижнього кута. Для опису цього google "Шампунь з нижньої лівою упаковкою".

Для оптимальних рішень найсучасніші методики можуть спакувати понад 20 прямокутників за кілька секунд. У Хуанга є алгоритм, який відокремлює проблему пошуку найменшого огороджувального обмежувального поля від проблеми вирішення питання про те, чи може набір прямокутника вміщуватися у обмежувальний ящик певного розміру. Ви даєте його програмі набір прямокутників, і він повідомляє вам найменший огороджувальний обмежувальний ящик, необхідний для їх упаковки.

У вашому випадку зовнішня петля повинна переходити від найменшої обмежувальної коробки вгору (при цьому ширина і висота послідовно збільшуються потужністю двох). Для кожного з цих обмежувальних коробок перевіряйте, чи зможете ви знайти упаковку для ваших прямокутників. Ви отримаєте купу відповідей "ні", до першої відповіді "так", яка буде гарантовано оптимальним рішенням.

Що стосується внутрішньої петлі вашого алгоритму - тієї, яка відповідає "так" чи "ні" на обмежувальне поле конкретного розміру, я би шукав посилання Хуана і просто реалізував його алгоритм. Він включає в себе безліч оптимізацій поверх основного алгоритму, але вам потрібні лише основні м'ясо та картопля. Оскільки ви хочете обробляти обертання, у будь-якій точці гілки під час пошуку просто спробуйте як обертання, так і зворотний трек, коли обидва обертання не дають рішення.


9

Я досить впевнений, що це складна проблема NP , тому для оптимального рішення вам доведеться реалізувати алгоритм зворотного відстеження, який намагається використовувати всі можливі комбінації.

Хороша новина полягає в тому, що через необхідність упакувати 2D прямокутники в обмеженому 2D просторі, ви можете скоротити багато можливостей на початку, так що це може бути не БЕЗПЕЧНО.


3
Ви, мабуть, маєте на увазі NP-повне.
starblue

7
Ну, якщо це NP повний, то це легко вирішити, просто вирішити еквівалентний екземпляр мандрівного продавця, і там ви йдете. Але суттєво показати, що, як це поставлено, це не так, оскільки проблеми, повні з NP, - це проблеми з рішенням (ви отримуєте відповіді "так" / "відповіді") та маєте алгоритм багаточленної версії часу. Питання "чи є розташування прямокутників a, b, c ..., які займають менше площі, ніж 256 * 128, може бути NP-завершеним.
Eclipse

2
@Eclipse правильний. From jair.org/media/3735/live-3735-6794-jair.pdf "Проблема оптимізації є важкою для NP, тоді як проблема вирішення того, чи можна упакувати набір прямокутників у заданому обмежувальному полі, не відповідає NP, через скорочення від упаковки для сміття (Korf, 2003). " Однак зауважте, що ОП запропонувала "досить оптимальний шлях", і для P в цьому є рішення для досить широких визначень "справедливо".
Джим Балтер

Я також підозрюю твердість NP, але нам потрібна довідка / доказ.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
Свята нитка некро, Бетмен. Це проблема з упаковкою, і вона вже в кращому випадку виявилася важкою для NP: en.wikipedia.org/wiki/Packing_problems
Сліпий

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

Загальне рішення є нетривіальним (математика говорити абсолютно не можна).
Як правило, люди використовують генетичний алгоритм, щоб спробувати можливі комбінації, але ви можете зробити досить добре, просто поклавши спочатку найбільшу форму, а потім приміряючи різні місця для наступний за величиною тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.