What is the difference between 0/1 knapsack and fractional knapsack?

Diferența dintre Rucsac 0/1 și Rucsac Fracționar

08/07/2023

Rating: 4.47 (6936 votes)

În lumea complexă a algoritmilor de optimizare, problemele rucsacului (Knapsack Problem) reprezintă o categorie fundamentală, adesea întâlnită în scenarii de alocare a resurselor, planificare logistică și decizii economice. Deși conceptul de bază – maximizarea valorii totale a obiectelor încărcate într-un rucsac cu o capacitate limitată – rămâne același, există variații semnificative care dictează abordările de rezolvare și complexitatea acestora. Două dintre cele mai studiate și aplicate forme sunt Problema Rucsacului 0/1 și Problema Rucsacului Fracționar. În acest articol, vom explora în detaliu aceste două variante, evidențiind diferențele lor cruciale, metodele de rezolvare specifice și scenariile în care fiecare se aplică cel mai eficient, oferind o perspectivă clară asupra modului de a alege abordarea corectă pentru provocarea ta de optimizare.

What are the three types of knapsack problems?
There are three types of knapsack problems i. e. 0-1 Knapsack, Fractional Knapsack, and Unbounded Knapsack. In this article, we will be seeing the fractional knapsack Problem in detail. This article defines the fractional knapsack problem in detail with the help of examples.
Cuprins

Ce este Problema Rucsacului?

Problema Rucsacului este o problemă de optimizare combinatorială care se prezintă sub diverse forme, dar esența sa rămâne constantă: având o colecție de obiecte, fiecare cu o anumită greutate și o anumită valoare, și un rucsac cu o capacitate maximă de greutate, scopul este de a selecta un subset de obiecte care să încapă în rucsac și să maximizeze valoarea totală. Imaginați-vă că sunteți un explorator care trebuie să împacheteze provizii valoroase pentru o expediție, dar rucsacul dumneavoastră are o limită de greutate. Cum alegeți ce să luați pentru a obține cel mai mare "profit" din călătoria dumneavoastră?

Problema Rucsacului 0/1

Problema Rucsacului 0/1 (Zero-One Knapsack Problem) este numită astfel deoarece fiecare obiect poate fi fie inclus în întregime în rucsac (reprezentat de "1"), fie exclus în totalitate ("0"). Nu există posibilitatea de a lua o fracțiune dintr-un obiect. Această caracteristică de indivizibilitate a obiectelor este definitorie și impune constrângeri semnificative asupra abordării de rezolvare. Este o problemă clasică de optimizare discretă.

Abordarea Naivă și Programarea Dinamică

O abordare naivă ar implica examinarea tuturor subseturilor posibile de obiecte, calcularea greutății și valorii fiecărui subset, și apoi selectarea celui care respectă capacitatea rucsacului și maximizează valoarea. Cu toate acestea, numărul de subseturi crește exponențial cu numărul de obiecte (2^n), făcând această abordare impracticabilă pentru seturi mari de date.

Din cauza naturii sale discrete și a proprietății de substructură optimă (soluția optimă a unei probleme mai mari poate fi construită din soluțiile optime ale subproblemelor), Problema Rucsacului 0/1 este, în general, rezolvată eficient folosind programare dinamică. Această metodă implică construirea unei tabele (sau a unei matrici) care stochează soluțiile optime pentru subprobleme mai mici. De exemplu, dp[i][w] ar putea reprezenta valoarea maximă care poate fi obținută folosind primele i obiecte și o capacitate de rucsac de w. Alegerea pentru fiecare obiect i este fie să-l includem (dacă încape), fie să nu-l includem. Formula de recurență ar arăta, de obicei, astfel:

dp[i][w] = max(dp[i-1][w], dp[i-1][w - greutate[i]] + valoare[i])

Cazul de bază este atunci când nu există obiecte sau capacitatea este zero, caz în care valoarea este zero.

Exemplu 0/1 Knapsack

Să considerăm un rucsac cu o capacitate c = 20 și următoarele obiecte:

  • Obiect 1: greutate = 18, valoare = 25
  • Obiect 2: greutate = 15, valoare = 24
  • Obiect 3: greutate = 10, valoare = 15

Dacă aplicăm logica 0/1:

  • Doar Obiectul 1: Greutate = 18, Valoare = 25.
  • Doar Obiectul 2: Greutate = 15, Valoare = 24.
  • Doar Obiectul 3: Greutate = 10, Valoare = 15.
  • Obiectul 2 + Obiectul 3: Greutate = 15 + 10 = 25 (depășește capacitatea de 20).
  • Obiectul 1 + Obiectul 3: Greutate = 18 + 10 = 28 (depășește capacitatea de 20).
  • Obiectul 1 + Obiectul 2: Greutate = 18 + 15 = 33 (depășește capacitatea de 20).

Valoarea maximă care poate fi obținută este 25, luând doar Obiectul 1. Vectorul soluției ar fi [1, 0, 0], indicând că primul obiect este luat în întregime, iar celelalte nu.

Complexitatea Temporală

Complexitatea temporală a abordării de programare dinamică pentru Problema Rucsacului 0/1 este O(nW), unde n este numărul de obiecte și W este capacitatea maximă a rucsacului. Aceasta este o complexitate pseudo-polinomială, deoarece depinde de valoarea numerică a lui W, nu doar de numărul de biți necesari pentru a-l reprezenta. Dacă W este foarte mare, algoritmul devine lent.

Problema Rucsacului Fracționar

Spre deosebire de varianta 0/1, în Problema Rucsacului Fracționar, obiectele pot fi împărțite sau luate în fracțiuni. Această proprietate de divizibilitate simplifică semnificativ problema, permițând o abordare mult mai directă și eficientă. Imaginați-vă că obiectele sunt substanțe precum aurul, nisipul sau lichidele, care pot fi măsurate și luate parțial.

Abordarea Greedy

Datorită naturii fracționabile a obiectelor, Problema Rucsacului Fracționar poate fi rezolvată folosind un algoritm greedy. Aceasta înseamnă că facem cea mai bună alegere locală la fiecare pas, cu încrederea că aceasta va duce la o soluție globală optimă. Strategia este următoarea:

  1. Calculați raportul valoare-greutate (v/w) pentru fiecare obiect. Acesta reprezintă cât de multă valoare obțineți pentru fiecare unitate de greutate a obiectului.
  2. Sortați obiectele în ordine descrescătoare a acestui raport valoare/greutate. Obiectele cu cel mai mare raport sunt cele mai "dense" în valoare și, prin urmare, cele mai dorite.
  3. Parcurgeți lista de obiecte sortate și adăugați-le în rucsac. Dacă un obiect încape în întregime, adăugați-l. Dacă nu încape în întregime, luați o fracțiune din el, exact cât este necesar pentru a umple rucsacul. Odată ce rucsacul este plin, opriți-vă.

Această abordare funcționează deoarece, luând întotdeauna obiectul care oferă cea mai mare valoare pe unitate de greutate, garantăm că umplem rucsacul cu cea mai mare valoare posibilă.

What is value-to-weight ratio in fractional knapsack problem?
A: The value-to-weight ratio helps prioritize items that provide the most value for the least weight, leading to an optimal solution in the Fractional Knapsack Problem. The Fractional Knapsack Problem is a fundamental optimization problem that highlights the efficiency of the greedy algorithm.

Exemplu Fractional Knapsack

Folosind aceleași date ca mai sus:

  • Capacitate rucsac c = 20
  • Obiect 1: greutate = 18, valoare = 25 (raport v/w = 25/18 ≈ 1.388)
  • Obiect 2: greutate = 15, valoare = 24 (raport v/w = 24/15 = 1.6)
  • Obiect 3: greutate = 10, valoare = 15 (raport v/w = 15/10 = 1.5)

Sortăm obiectele după raportul v/w în ordine descrescătoare:

  1. Obiect 2 (1.6)
  2. Obiect 3 (1.5)
  3. Obiect 1 (1.388)

Acum aplicăm algoritmul greedy:

  • Pasul 1: Luăm Obiectul 2 (cel mai mare raport v/w). Greutate = 15, Valoare = 24.
    Greutate rucsac curent = 15. Profit total = 24. Capacitate rămasă = 20 - 15 = 5.
  • Pasul 2: Luăm Obiectul 3. Greutatea sa este 10, dar avem nevoie doar de 5 (capacitatea rămasă). Luăm o fracțiune de 5/10 = 0.5 din Obiectul 3.
    Greutate adăugată = 0.5 * 10 = 5. Valoare adăugată = 0.5 * 15 = 7.5.
    Greutate rucsac curent = 15 + 5 = 20. Profit total = 24 + 7.5 = 31.5. Capacitate rămasă = 0.

Rucsacul este plin. Valoarea maximă obținută este 31.5. Vectorul soluției ar fi [0, 1, 0.5], indicând că Obiectul 2 este luat în întregime, iar Obiectul 3 este luat pe jumătate.

Complexitatea Temporală

Complexitatea temporală pentru Problema Rucsacului Fracționar este dominată de pasul de sortare a obiectelor, care durează O(n log n), unde n este numărul de obiecte. Odată sortate, parcurgerea listei pentru a umple rucsacul durează O(n). Prin urmare, complexitatea totală este O(n log n), ceea ce este mult mai eficient decât abordarea 0/1 pentru seturi mari de date.

Diferențe Cheie: 0/1 Knapsack vs. Fractional Knapsack

Pentru a sublinia distincțiile, iată o tabelă comparativă:

CriteriuProblema Rucsacului 0/1Problema Rucsacului Fracționar
Natura ObiectelorIndivizibile (totul sau nimic)Divizibile (pot fi luate parțial)
Abordare OptimăProgramare Dinamică (sau Backtracking/Branch and Bound pentru probleme NP-hard)Algoritm Greedy
Complexitate TemporalăO(nW) - pseudo-polinomialăO(n log n) - polinomială
Tip de ProblemăProblemă de optimizare discretă, NP-hardProblemă de optimizare continuă, rezolvabilă în timp polinomial
Exemplu ScenariuÎncărcarea unui camion cu mobilă, selecția proiectelor software.Transportul de cereale, alocarea de resurse financiare, tăierea unei bucăți de material.
Garanția SoluțieiSoluție optimă globalăSoluție optimă globală

Când să Folosim Fiecare Abordare?

Alegerea între Problema Rucsacului 0/1 și cea Fracționară depinde în totalitate de natura obiectelor și de contextul problemei pe care încercați să o rezolvați:

  • Problema Rucsacului 0/1 este adecvată atunci când obiectele sunt unități discrete și nu pot fi împărțite. Gândiți-vă la obiecte fizice precum echipamente electronice, cărți, sau chiar decizii binare (da/nu). De exemplu, dacă ești un hoț de bijuterii și nu poți tăia un diamant în două, ai de-a face cu o problemă de tip 0/1. De asemenea, în managementul de proiect, selectarea unui set de proiecte care să maximizeze beneficiile într-un buget fix, unde fiecare proiect este fie finanțat, fie nu, este o aplicație a rucsacului 0/1.
  • Problema Rucsacului Fracționar este ideală pentru situațiile în care obiectele sunt omogene și pot fi împărțite în orice cantitate. Exemple tipice includ resursele vrac, cum ar fi lichidele, minereurile, produsele chimice sau chiar alocarea de timp pentru sarcini, unde o parte dintr-o sarcină poate fi finalizată. Dacă ești un cumpărător de aur și poți cumpăra orice cantitate dintr-un lingou, ai de-a face cu o problemă fracționară. Aceasta este adesea utilizată în scenarii de producție, unde materiile prime pot fi utilizate parțial pentru a maximiza profitul.

Întrebări Frecvente (FAQ)

Poate Problema Rucsacului 0/1 să fie rezolvată cu un algoritm Greedy?

Nu, în general, Problema Rucsacului 0/1 nu poate fi rezolvată cu un algoritm greedy. Motivul este că o alegere locală optimă (adică luarea obiectului cu cel mai mare raport valoare/greutate) nu garantează o soluție globală optimă. De exemplu, luarea unui obiect mare, cu un raport valoare/greutate mare, ar putea ocupa prea multă capacitate, împiedicându-vă să luați mai multe obiecte mai mici, care, cumulate, ar putea oferi o valoare totală mai mare. Exemplul nostru de mai sus a demonstrat acest lucru: obiectul 2 avea cel mai bun raport v/w (1.6), dar luându-l pe el și o fracțiune din obiectul 3, am obținut 31.5 în cazul fracționar. În timp ce pentru 0/1, dacă am fi aplicat o logică greedy naivă (luând Obiectul 2 primul), am fi rămas cu 24, deoarece nu am mai fi putut adăuga Obiectul 3 fără a depăși capacitatea. Comparativ, luând Obiectul 1 (care avea un raport v/w mai mic, 1.388), am obținut 25, o valoare mai bună în contextul 0/1. Prin urmare, programarea dinamică este necesară pentru a explora toate combinațiile relevante și a asigura optimalitatea.

Este Problema Rucsacului Fracționar întotdeauna "mai bună" sau mai profitabilă decât 0/1?

Nu neapărat "mai bună" în sens absolut, ci mai flexibilă și, prin urmare, capabilă să atingă o valoare totală egală sau mai mare decât varianta 0/1 pentru același set de obiecte și aceeași capacitate. Flexibilitatea de a lua fracțiuni permite rucsacului să fie umplut la capacitate maximă, valorificând fiecare unitate de greutate disponibilă. În contrast, 0/1 poate lăsa spațiu nefolosit dacă obiectele rămase nu se potrivesc perfect sau dacă includerea lor ar depăși capacitatea. Astfel, soluția fracționară va fi întotdeauna cel puțin la fel de bună, iar de cele mai multe ori, strict mai bună decât soluția 0/1 pentru aceleași date de intrare, deoarece are un grad mai mare de libertate în selecție.

Care este cea mai mare provocare în rezolvarea Problemei Rucsacului 0/1?

Cea mai mare provocare în rezolvarea Problemei Rucsacului 0/1 constă în natura sa combinatorială și în clasificarea sa ca problemă NP-hard. Aceasta înseamnă că, pentru instanțe mari, timpul necesar pentru a găsi o soluție optimă crește exponențial (sau pseudo-polinomial, în cazul programării dinamice, care depinde de capacitate). Acest lucru o face dificil de rezolvat în timp rezonabil pe măsură ce numărul de obiecte sau capacitatea rucsacului devin foarte mari. Deși programarea dinamică oferă o soluție exactă, ea devine ineficientă pentru capacități extrem de mari. Pentru astfel de cazuri, se apelează adesea la algoritmi de aproximare sau euristici, care găsesc soluții "suficient de bune", dar nu neapărat optime, într-un interval de timp practic. Această complexitate inerentă o distinge fundamental de problema rucsacului fracționar, care poate fi rezolvată eficient cu un algoritm greedy.

Concluzie

Înțelegerea diferențelor dintre Problema Rucsacului 0/1 și Problema Rucsacului Fracționar este fundamentală pentru oricine lucrează cu algoritmi de optimizare. În timp ce varianta 0/1 impune constrângeri stricte de indivizibilitate, necesitând adesea abordări mai complexe precum programarea dinamică, varianta fracționară beneficiază de simplitatea și eficiența unui algoritm greedy, datorită posibilității de a împărți obiectele. Alegerea corectă a tipului de problemă și a algoritmului aferent este esențială pentru a obține soluții optime și eficiente în diverse aplicații din lumea reală, de la logistică și planificare la gestionarea resurselor. Prin stăpânirea acestor concepte, programatorii și analiștii pot aborda cu încredere o gamă largă de provocări de optimizare, transformând constrângerile în oportunități de eficiență maximă.

Dacă vrei să descoperi și alte articole similare cu Diferența dintre Rucsac 0/1 și Rucsac Fracționar, poți vizita categoria Fitness.

Go up