Задача пакування рюкзака
Задача пакування рюкзака (англ. Knapsack problem) — задача комбінаторної оптимізації: для заданої множини предметів, кожен з яких має вагу і цінність, визначити яку кількість кожного з предметів слід взяти, так, щоб сумарна вага не перевищувала задану, а сумарна цінність була максимальною. Задача бере свою назву від доволі відомої ситуації, коли потрібно наповнити рюкзак, що здатен витримати деяку максимальну масу, предметами, кожен з яких має вартість (або корисність) та масу. Необхідно обрати об'єкти в такий спосіб, аби максимізувати сумарну вартість (або користь), але не перевищити максимально припустиму масу.
Задача часто виникає при розподілі ресурсів, коли наявні фінансові обмеження, і вивчається в таких областях, як комбінаторика, інформатика, теорія складності, криптографія, прикладна математика.
Описання задачі досить просте, але розв'язання — складне. Відомі алгоритми, на практиці, здатні розв'язати задачі досить великих розмірів. Однак, унікальне формулювання задачі, а також той факт, що вона присутня як підзадача у більших, загальніших проблемах, робить її важливою для наукових досліджень.
Задача про пакування рюкзаку досліджується вже понад століття. Відома згадка ще 1897 року в статті Джорджа Метьюза Балларда[en][1]. Сама назва «задача про пакування рюкзаку» відсилає до ранніх робіт математика Тобіаса Данцига[en] (1884—1956)[2], і стосується звичайної проблеми пакування найбільш цінних або корисних речей без перевантаження.
Інтенсивне дослідження проблеми почалось з середини ХХ століття і в 1972 році була включена Річардом Карпом (англ. Richard Karp) до списку 21 NP-повної задачі[3].
Дослідження 1998 року проведене репозитарієм алгоритмів [Архівовано 28 листопада 2009 у Wayback Machine.] університету Стоні Брук показало, що з 75 алгоритмічних задач, задача пакування рюкзака була 19-ю за по популярністю і 3-ю з найбільш необхідних після таких задач, як суфіксне дерево та задача про пакування в ємності[4].
Задачу пакування рюкзака використовують для моделювання різних проблем, зокрема:
- У системах підтримки управління портфелем для балансування та диверсифікації вибраних капіталовкладень із метою пошуку найкращого балансу між ризиками та ефективністю вкладів у різні фінансові активи[5] та для сек'юритизації активів[6];
- Генерування ключів для криптосистем Меркле — Геллмана[7] та інших криптосистем[en].
Також задача пакування рюкзака виникає у великій кількості промислових задач[8][9]:
- У кроєнні різних матеріалів[en] (тканини, сталеві листи тощо): вибір оптимальної схеми розкрою матеріалів з метою зменшення кількості відходів[10];
- При завантаженні човна або літака: вибір багажів для оптимального завантаження транспортного засобу;
- При розміщенні вантажів на складі мінімальної площі.
Одним із перших застосувань алгоритмів пакування рюкзака була створення та оцінка тестів, в яких тестовані особи мали вибір, на які питання вони будуть відповідати. При невеликій кількості прикладів це доволі прозорий процес. Наприклад, якщо іспит містить 12 запитань кожен з яких на 10 балів, тестованій особі потрібно відповісти лише на 10 запитань для досягнення максимально можливої оцінки — 100 балів. Проте, якщо тестові завдання дають різну кількість балів, зробити вибір вже важче. Фюерман і Вайс запропонували систему, в якій студентам дають гетерогенний тест із загальною кількістю 125 можливих балів. Студентів просять відповісти на всі питання, наскільки це можливо. З усіх можливих підмножин завдань, загальні значення яких дорівнюють або не перевищують 100, алгоритм визначає, який піднабір дасть кожному студенту найвищий можливий бал[11].
Задачу пакування рюкзака можна визначити засобами математичного апарату. Нехай кожному об'єктові для пакування зіставлено індекс i, який приймає значення від 1 до n. Числа та відповідають вазі та вартості об'єкта i. Максимальна припустима маса, яку здатен витримати рюкзак, дорівнює W.
- 0-1 задача пакування рюкзака
Існує багато варіантів заповнення рюкзака. Для описання окремого варіанту пакування необхідно вказати для кожного об'єкта, чи його обрано (запаковано). Для цього можна використати двійковий вектор , компонента якого дорівнюватиме 1, якщо i-тий об'єкт запаковано, та 0 якщо ні. Цей вектор називається вектором заповнення. Вагу та вартість запакованих предметів, можна обчислити як функцію від вектора заповнення.
Для заданого вектора заповнення X вартість предметів запакованих у рюкзак дорівнює:
Аналогічно, загальна маса предметів дорівнює:
Таким чином, задача пакування рюкзака полягає у відшуканні такого вектора заповнення , що максимізує функцію за умови:
- (1)
Тобто, загальна маса обраних предметів не перевищує можливості рюкзака .
Взагалі, діють такі додаткові умови:
- : всі доступні об'єкти не можливо покласти до рюкзака разом;
- : будь-який додатковий об'єкт надає перевагу;
- : будь-який об'єкт використовує ресурси.
Термінологія:
- Функція — називається цільовою;
- Будь-який вектор , що відповідає умові (1), називається припустимим;
- Якщо вартість максимальна, то вектор називається оптимальним.
Припустімо, окрім вартості предмети мають ще одну характеристику (наприклад, щільність). Задача пошуку вектора заповнення , що максимізує обидві функції (сумарна вартість та сумарна щільність) є багатокритеріальним варіантом 0-1 задачі пакування рюкзака.[12]
Обмежена задача пакування рюкзака обмежує кількість копій кожного виду предмета максимальним цілим значенням . Математично цю задачу можна сформулювати так:
- максимізувати
- за умови
Необмежена задача пакування рюкзака (НЗПР) не накладає верхньої межі для кількості копій кожного виду предмета. Тобто потрібно
- максимізувати
- за умови
Приклад такої задачі наведена на малюнку у вступній частині (див. текст «Якщо доступна достатня кількість екземплярів кожної коробки…»)
Особливий інтерес представляє окремий випадок задачі пакування рюкзака з такими властивостями:
- вона є проблемою вибору,
- вона є 0-1 задачею,
- для кожного виду предмета вага дорівнює вартості: .
У цьому разі задача еквівалентна такій задачі: задано множину невід'ємних цілих чисел, чи існує будь-яка її підмножина, сума елементів якої складає точно W? Або, якщо допускається від'ємна вага і W дорівнює нулю, то задачею є: задано множину цілих чисел, чи існує непорожня підмножина, сума елементів якої точно дорівнює 0? Цей окремий випадок називається задачею суми підмножини. У галузі криптографії термін задача пакування рюкзака часто використовується для позначення конкретно задачі суми підмножини.
Якщо допускається декілька рюкзаків, то задачу краще розглядати як задачу пакування в ємності.
Задачу пакування рюкзака можна описати термінами теорії множин.[13]
Нехай задано множину об'єктів , вагу , та вартість для кожного об'єкта та максимальну припустиму вагу . Необхідно знайти підмножину , таку, щоб:
- та .
Для оцінки алгоритмічної складності задачі, її оптимізаційне формулювання змінюють на задачу розпізнавання, яка є більш простою і тому може слугувати нижньою оцінкою складності.
Представлення у вигляді задачі розпізнавання запроваджує додатковий параметр P — бажана вартість предметів у рюкзаку та ставить запитання чи існує ще один варіант пакування, з сумарною вартістю запакованих предметів більшою за P.[13] Мета запровадження задачі розпізнавання полягає в тому, що з точки зору теорії обчислювальної складності та NP-повноти для неї легше визначати складність. Якщо цільову функцію не складно обчислювати, то задача розпізнавання не складніша за відповідну задачу оптимізації. Таким чином, із NP-повноти задачі розпізнавання випливає NP-повнота задачі оптимізації.[14][13]
Задача розпізнавання для оптимізаційної задачі 0-1 пакування рюкзака формулюється так: Задано скінченну множину U об'єктів, вагу , вартість для кожного об'єкта та цілі числа W (ємність рюкзака) та P (бажана вартість). Чи існує така підмножина , що:
- , та ?
Задача пакування рюкзака цікава з точки зору інформатики з багатьох причин:
- Задача пакування рюкзака у формі проблеми вибору (чи може бути досягнуто значення, щонайменше V, без перевищення ваги W?) є NP-повною, тому в загальному випадку не існує алгоритму як правильного, так і швидкого (який виконується за поліноміальний час).
- Хоча проблема вибору є NP-повною, проблема оптимізації є NP-складною, то вона, щонайменше, таке ж складна, як і проблема вибору, і тому не існує поліноміального алгоритму, який може визначити, чи є рішення оптимальним (це б означало, що не існує рішення, яке дає значення більше V, таким чином розв'язуючи NP-повну проблему вибору).
- Існує псевдополіноміальний алгоритм, який використовує динамічне програмування.
- Існує схема наближення до поліноміального часу, яка використовує наведений вище псевдополіноміальний алгоритм як підпрограму.
- У більшості випадків, що виникають на практиці, і для «випадкових екземплярів» з деяких ймовірнісних розподілів, все ж таки можуть бути розв'язані точно.
Як і для інших NP-повних задач, в деяких випадках достатньо знайти рішення, наближене до оптимального, але не обов'язково оптимальне. Бажано, також, щоб різниця між оптимальним розв'язком та знайденим була гарантованих розмірів.
Далі під ефективністю предмета розуміється відношення його вартості до ваги. Чим вище ефективність предмета, тим кориснішим він є для пакування.
Одним з найпростіших алгоритмів пошуку приблизного розв'язку є жадібний алгоритм. Ідея алгоритму полягає в тому, щоб класти до рюкзака в першу чергу найефективніші предмети, аж до його заповнення:
впорядкувати предмети у порядку зменшення ефективності w_пак: = 0
для i від 1 до n якщо w[i] + w_пак <= W тоді x[i] := 1 w_пак := w_пак + w[i] інакше x[i] := 0 кінець якщо кінець для
Класична задача пакування рюкзака була вивчена досить глибоко. Існує багато методів пошуку точних розв'язків задачі. Більшість з них є покращеними варіантами одного з наведених нижче методів пошуку точного розв'язку задачі. А саме використовується підхід динамічне програмування[15], метод гілок і меж[16] або гібридне поєднання[en] обох підходів.[17][18][19][20]
Задача пакування рюкзака має властивість суб-оптимальної структури, тобто, можна знайти оптимальний розв'язок задачі з змінними на основі розв'язку задачі з змінною. Ця властивість дозволяє застосувати засоби динамічного програмування для розв'язання задачі пакування рюкзака.
Нехай потрібно розв'язати 0-1 задачу пакування рюкзака. Позначимо через KP(i, c) максимальну вартість, яку можна отримати для перших предметів із загальною вагою меншою або рівною c. Задача пакування рюкзака зводиться до знаходження KP(n, W).
Ідея полягає в тому, що оптимальний розв'язок задачі KP(i, c) можна отримати, використовуючи розв'язки двох простіших задач:
- задачі з змінними для рюкзака з такою ж ємністю c (KP(i−1, c)), та ;
- задачі з змінними для рюкзака з ємністю (), та .
Розв'язок задачі пакування рюкзака з 0 змінними (KP (0 ,*)) дорівнює нулю. Розв'язок задачі пакування рюкзака при c=0 (KP (* ,0)) також дорівнює нулю.
Тепер можна записати рекурсивно:
- , якщо (новий предмет важчий, ніж поточний резерв ваги)
- , якщо .
Потім будується таблиця T[i, c], елементи якої містять значення розв'язків задач KP(i, c) в наступний спосіб:
для c від 0 до W робити T[0,c] := 0 кінець для
для i від 1 до n робити для c від 0 до W робити якщо c>=w[i] то T[i,c] := max( T[i-1,c], T[i-1, c-w[i]] + p[i] ) інакше T[i,c] := T[i-1,c] кінець якщо кінець для кінець для вивести T[n,W]
Коли таблиця побудована, випадок задачі T[n, W] слід звести до випадку T[0, *].
Часова складність алгоритму дорівнює . Алгоритм має дві переваги:
- Швидкість;
- Не потрібне сортування змінних.
та недолік:
- вимагає порівняно багато пам'яті (що робить його не прийнятним для розв'язання великих задач).
Цей метод було розроблено Робертом Ґарфінкелем та Джорджем Немгаузером[en] в 1972 році.[21]
Подібно до інших задач комбінаторної оптимізації, задача пакування рюкзака може бути розв'язана методом гілок і меж (англ. Branch-and-bound algorithm). Застосування методу гілок і меж до розв'язання задачі пакування рюкзака вперше запропонував Колесар в 1967 році. Варіант алгоритму розроблений Грінбергом та Хегерічем в 1970 році мав істотно нижчі вимоги до пам'яті та часу. Горовіц та Сані в 1974 році запропонували свій алгоритм побудований на основі попередніх варіантів. Цей алгоритм найефективніший та найпростіший для реалізації у порівнянні з попередніми алгоритмами. Запропонований Мартело та Тозом алгоритм[22] набув значного поширення. Перевагою цього методу є низькі вимоги до обсягів необхідної пам'яті.
- ↑ Mathews, G. B. (25 June 1897). On the partition of numbers (PDF). Proceedings of the London Mathematical Society. 28: 486—490. doi:10.1112/plms/s1-28.1.486. Архів оригіналу (PDF) за 26 травня 2012. Процитовано 26 липня 2019.
- ↑ Dantzig, Tobias. Numbers: The Language of Science, 1930.
- ↑ Richard M. Karp (1972). Reducibility Among Combinatorial Problems (PDF). У R. E. Miller; J. W. Thatcher; J.D. Bohlinger (ред.). Complexity of Computer Computations. New York: Plenum. с. 85—103. doi:10.1007/978-1-4684-2001-2_9. Архів оригіналу (PDF) за 10 лютого 2021. Процитовано 26 липня 2019.
- ↑ Skiena, S. S. (September 1999). Who is Interested in Algorithms and Why? Lessons from the Stony Brook Algorithm Repository. ACM SIGACT News. 30 (3): 65—74. CiteSeerX 10.1.1.41.8357. doi:10.1145/333623.333627. ISSN 0163-5700.
- ↑ Kellerer, Pferschy, and Pisinger, 2004, с. 461.
- ↑ Kellerer, Pferschy, and Pisinger, 2004, с. 465.
- ↑ Kellerer, Pferschy, and Pisinger, 2004, с. 472.
- ↑ Silvano, 1990, с. 2.
- ↑ Бурков, Горгидзе, Ловецкий, 1974, с. 217.
- ↑ Kellerer, Pferschy, and Pisinger, 2004, с. 449.
- ↑ Feuerman, Martin; Weiss, Harvey (April 1973). A Mathematical Programming Model for Test Construction and Scoring. Management Science. 19 (8): 961—966. doi:10.1287/mnsc.19.8.961. JSTOR 2629127.
- ↑ Matthias Ehrgott (2005). Multicriteria Optimization. Springer. ISBN 3-540-21398-8.
- ↑ а б в (англ.) Michail G. Lagoudakis, The 0-1 Knapsack Problem — An Introductory Survey [Архівовано 2008-12-03 у Wayback Machine.], 1996.
- ↑ Garey M. R., Johnson D. S., Computers and Intractability: A Guide to the Theory of NP-completeness, W. H. Freeman and Comp., San Francisco, 1979.
- ↑ Andonov, Rumen; Poirriez, Vincent; Rajopadhye, Sanjay (2000). Unbounded Knapsack Problem : dynamic programming revisited. European Journal of Operational Research. 123 (2): 168—181. CiteSeerX 10.1.1.41.2135. doi:10.1016/S0377-2217(99)00265-9. Архів оригіналу за 29 січня 2020. Процитовано 28 липня 2019.
- ↑ S. Martello, P. Toth, Knapsack Problems: Algorithms and Computer Implementations, John Wiley and Sons, 1990
- ↑ Poirriez, Vincent; Yanev, Nicola; Andonov, Rumen (2009). A hybrid algorithm for the unbounded knapsack problem. Discrete Optimization. 6 (1): 110—124. doi:10.1016/j.disopt.2008.09.004. ISSN 1572-5286.
- ↑ S. Martello, D. Pisinger, P. Toth, Dynamic programming and strong bounds for the 0-1 knapsack problem, Manag. Sci., 45:414–424, 1999.
- ↑ Plateau, G.; Elkihel, M. (1985). A hybrid algorithm for the 0-1 knapsack problem. Methods of Oper. Res. 49: 277—293.
- ↑ Martello, S.; Toth, P. (1984). A mixture of dynamic programming and branch-and-bound for the subset-sum problem. Manag. Sci. 30 (6): 765—771. doi:10.1287/mnsc.30.6.765.
- ↑ (англ.) R. S. Garfinkel et G. L. Nemhauser. Integer Pogramming. John Wiley & Sons, New York, 1972. ISBN 0-471-29195-1.
- ↑ (англ.) Silvano Martello et Paolo Toth, Knapsack Problems: Algorithms and Computer Implementations, John Wiley & Sons, 1990 ISBN 0-471-92420-2.
- Hans Kellerer, Ulright Pferschy and David Pisinger, Knapsack Problems, Springer, 2004 ISBN 3-540-40286-1. (англ.)
- Honsberger, R. Mathematical Gems III. Washington, DC: Math. Assoc. Amer., pp. 163—166, 1985. (англ.)
- Список задач про наповнення рюкзака
- 21 NP-повна задача Карпа
- Комбінаторна оптимізація
- Задача про пакування в ємності
- Задача комівояжера
- Динамічне програмування. 0-1 задача пакування рюкзака [Архівовано 16 лютого 2012 у Wayback Machine.] (слайди лекції) (англ.)
- Слайди лекції з динамічного програмування [Архівовано 19 квітня 2009 у Wayback Machine.] (п.4. Задача пакування рюкзака). (рос.)