Fractional Knapsack Problem: girig algoritm med exempel
โก Smart sammanfattning
Fraktionellt ryggsรคcksproblem anvรคnder en girig algoritm som sorterar paket efter vรคrde-till-vikt-fรถrhรฅllande och tar artiklar i den ordningen, vilket gรถr att brรฅkdelar av artiklarna kan fylla รฅterstรฅende kapacitet fรถr en garanterat optimal lรถsning.

Vad รคr Greedy Strategy?
Giriga algoritmer Vรคlj det bรคsta lokala valet i varje steg i hopp om att en kedja av lokala optima producerar en globalt optimal lรถsning. Liksom dynamisk programmering riktar de in sig pรฅ optimeringsproblem, men de ser aldrig tillbaka fรถr att omprรถva tidigare beslut.
Giriga algoritmer รคr vanligtvis enkla att skriva, snabba (ofta linjรคr eller kvadratisk tid), lรคtta att felsรถka och krรคver lite minne. Nackdelen รคr att resultatet inte alltid รคr optimalt, sรฅ strategin fungerar bara fรถr problem som har en bevisad girig-sรคker struktur.
Giriga strategier lรถser kombinatorisk optimering genom att bygga en lรถsning A, en komponent av AI i taget. Vid varje steg vรคljer du AI optimalt under de rรฅdande begrรคnsningarna och krymper problemet till ett mindre delproblem.
Tvรฅ egenskaper mรฅste gรคlla fรถr att en girig metod ska vara korrekt:
- Girigt val egendom: Ett lokalt optimum i varje steg leder till ett globalt optimum. Valet beror pรฅ tidigare beslut men inte pรฅ framtida.
- Optimal underkonstruktion: Den optimala lรถsningen av hela problemet innehรฅller optimala lรถsningar av dess delproblem.
En girig algoritm har fem komponenter:
- En kandidatuppsรคttning frรฅn vilken lรถsningar byggs.
- En urvalsfunktion som vรคljer den bรคsta nรคsta kandidaten.
- En genomfรถrbarhetsfunktion som kontrollerar om en kandidat kan utรถka den aktuella partiella lรถsningen.
- En objektivfunktion som vรคrderar en fullstรคndig eller partiell lรถsning.
- En utvรคrderingsfunktion som signalerar nรคr lรถsningen รคr klar.
Idรฉn om girig
Greedy One sorterar paket enbart efter vรคrde:
- Sortera paket i icke-stigande vรคrdeordning.
- Gรฅ igenom den sorterade listan och lรคgg varje paket i ryggsรคcken om den รฅterstรฅende kapaciteten rymmer det.
Denna regel ger inte alltid det optimala svaret. Motexempel:
- Parametrar: n = 3, M = 19.
- Paket: {i = 1; W = 14; V = 20}, {i = 2; W = 6; V = 16}, {i = 3; W = 10; V = 8} โ hรถgt vรคrde men ocksรฅ hรถg vikt.
- Den girige vรคljer paket 1 med ett totalt vรคrde pรฅ 20, medan det optimala valet (paket 2, paket 3) nรฅr 24.
Idรฉn om giriga tvรฅ
Greedy Two sorterar paket enbart efter vikt:
- Sortera paketen i icke-fallande viktordning.
- Gรฅ igenom den sorterade listan och lรคgg varje paket i ryggsรคcken om den รฅterstรฅende kapaciteten rymmer det.
Denna regel misslyckas ocksรฅ med att vara optimal. Motexempel:
- Parametrar: n = 3, M = 11.
- Paket: {i = 1; W = 5; V = 10}, {i = 2; W = 6; V = 16}, {i = 3; W = 10; V = 28} โ lรฅg vikt men lรฅgt vรคrde.
- Giriga Tvรฅ val (paket 1, paket 2) med totalt vรคrde 26, medan det optimala valet (paket 3) nรฅr 28.
Idรฉn om giriga tre
Greedy Three รฅtgรคrdar bรฅda felen genom att kombinera vรคrde och vikt i en enda rangordningsnyckel. Det รคr standardmetoden fรถr det brรฅkdelsbaserade ryggsรคcksproblemet.
- Berรคkna enhetskostnaden V[i] / W[i] fรถr varje paket.
- Sortera paket i icke-stigande ordning efter enhetskostnad.
- Gรฅ igenom den sorterade listan och lรคgg till varje paket om den รฅterstรฅende kapaciteten rymmer det.
Giriga Tre sorteringar efter enhetskostnad V[i] / W[i]
Idรฉ: Berรคkna vikt-vรคrde-fรถrhรฅllandet V[i] / W[i] fรถr varje paket, sortera i fallande ordning och ta det stรถrsta tillgรคngliga fรถrhรฅllandet fรถrst tills ryggsรคcken รคr full.
Fรถr det sanna Fraktionerad variant, nรคr nรคsta paket inte fรฅr plats helt, ta en brรฅkdel som exakt fyller den รฅterstรฅende kapaciteten. Den extra regeln รคr det som gรถr Greedy Three bevisligen optimal pรฅ Fractional Knapsack.
Steg i algoritmen
Fรถr 0/1-varianten med gren och bundna punkter driver den sorterade enhetskostnadslistan ett sรถktrรคd:
- Steg 1: Rotnoden representerar en tom ryggsรคck. TotalValue = 0. UpperBound = M ร maximal enhetskostnad.
- Steg 2: Fรถrgrena roten efter hur mรฅnga kopior av paketet med stรถrsta fรถrhรฅllandet som fรฅr plats. Fรถr varje barn, berรคkna om TotalValue, รฅterstรฅende kapacitet M och UpperBound.
- Steg 3: Utรถka barnet med den stรถrsta รถvre grรคnsen fรถrst, i hopp om att snabbt hitta en stark lรถsning.
- Steg 4: Beskรคr alla noder vars UpperBound inte รคr bรคttre รคn den nuvarande bรคsta kompletta lรถsningen.
- Steg 5: Nรคr varje nod antingen utรถkas eller beskรคrs รคr den nuvarande bรคsta kompletta lรถsningen optimal.
Pseudokod fรถr den rena fraktionella ryggsรคcksgiriga algoritmen:
Fractional Knapsack (Array W, Array V, int M) 1. for i <- 1 to size(V) 2. cost[i] <- V[i] / W[i] 3. Sort-Descending(cost) 4. total <- 0 5. i <- 1 6. while (i <= size(V) and M > 0) 7. if W[i] <= M 8. M <- M - W[i] 9. total <- total + V[i] 10. i <- i + 1 11. else 12. total <- total + V[i] * (M / W[i]) 13. M <- 0
Algoritmens komplexitet:
- Med en enkel sortering (urval eller bubbla): O(n2).
- Anvรคndning av snabb sortering eller sammanslagningssortering: O(n log n), dominerad av sorteringssteget.
Java Code fรถr giriga tre
Definiera KnapsackPackage klass med vikt, vรคrde och hรคrledd kostnad (V/W-fรถrhรฅllandet som anvรคnds fรถr sortering):
public class KnapsackPackage { private double weight; private double value; private Double cost; public KnapsackPackage(double weight, double value) { super(); this.weight = weight; this.value = value; this.cost = Double.valueOf(value / weight); } public double getWeight() { return weight; } public double getValue() { return value; } public Double getCost() { return cost; } }
Skapa sedan funktionen som implementerar Greedy Three:
public void knapsackGreProc(int W[], int V[], int M, int n) { KnapsackPackage[] packs = new KnapsackPackage[n]; for (int i = 0; i < n; i++) { packs[i] = new KnapsackPackage(W[i], V[i]); } Arrays.sort(packs, new Comparator<KnapsackPackage>() { @Override public int compare(KnapsackPackage a, KnapsackPackage b) { return b.getCost().compareTo(a.getCost()); } }); double remain = M; double result = 0d; for (int i = 0; i < n && remain > 0; i++) { if (packs[i].getWeight() <= remain) { remain -= packs[i].getWeight(); result += packs[i].getValue(); System.out.println("Pack " + i + " - Weight " + packs[i].getWeight() + " - Value " + packs[i].getValue()); } else { double fraction = remain / packs[i].getWeight(); result += packs[i].getValue() * fraction; System.out.println("Pack " + i + " - Fraction " + fraction + " - Value " + packs[i].getValue() * fraction); remain = 0; } } System.out.println("Max Value:\t" + result); }
Funktion knapsackGreProc() in Java
Fรถrklaring av kod:
- Slรฅ in varje inmatning i en
KnapsackPackagesรฅ sorteringsnyckeln (V/W-fรถrhรฅllandet) รคr fรถrberรคknad. - Sortera i fallande kostnadsordning.
- Ta varje paket hel om det fรฅr plats.
- Ta en brรฅkdel av nรคsta paket fรถr att fylla den รถverblivna kapaciteten.
- Stoppa sรฅ snart den รฅterstรฅende kapaciteten nรฅr noll.
ร
tgรคrdsanmรคrkning: ursprungliga Java loop avancerad i endast nรคr ett paket inte fick plats, vilket orsakade att samma paket togs upprepade gรฅnger. Versionen ovan flyttar fram ett paket per iteration och lรคgger till ett steg fรถr fraktionerad fyllning, vilket matchar den sanna regeln fรถr fraktionerad ryggsรคck.
Java drivrutin som kรถr algoritmen pรฅ ett fungerande exempel:
public void run() { int W[] = new int[]{15, 10, 2, 4}; int V[] = new int[]{30, 25, 2, 6}; int M = 37; int n = V.length; knapsackGreProc(W, V, M, n); }
Python3 Code fรถr giriga tre
Definiera fรถrst KnapsackPackage klass. De __lt__ Metoden gรถr det direkt sorterbart efter kostnad:
class KnapsackPackage(object): """Knapsack Package Data Class""" def __init__(self, weight, value): self.weight = weight self.value = value self.cost = value / weight def __lt__(self, other): return self.cost < other.cost
Implementera sedan Fractional Knapsack-rutinen:
class FractionalKnapsack(object): def knapsackGreProc(self, W, V, M, n): packs = [KnapsackPackage(W[i], V[i]) for i in range(n)] packs.sort(reverse=True) remain = M result = 0 for i in range(n): if remain == 0: break if packs[i].weight <= remain: remain -= packs[i].weight result += packs[i].value print("Pack", i, "- Weight", packs[i].weight, "- Value", packs[i].value) else: fraction = remain / packs[i].weight result += packs[i].value * fraction print("Pack", i, "- Fraction", fraction, "- Value", packs[i].value * fraction) remain = 0 print("Max Value:", result)
Funktion knapsackGreProc() in Python
ร
tgรคrdsanmรคrkning: ursprungliga Python klassen definierade en tom __init__ utan kropp, som hรถjer IndentationErrorVersionen ovan tar bort den tomma konstruktorn eftersom ingen behรถvs.
Drivrutin som kรถr algoritmen i det fรถrsta exemplet:
if __name__ == "__main__": W = [15, 10, 2, 4] V = [30, 25, 2, 6] M = 37 n = 4 proc = FractionalKnapsack() proc.knapsackGreProc(W, V, M, n)
C# Code fรถr giriga tre
Definiera KnapsackPackage klass:
using System; namespace KnapsackProblem { public class KnapsackPackage { private double weight; private double value; private double cost; public KnapsackPackage(double weight, double value) { this.weight = weight; this.value = value; this.cost = value / weight; } public double Weight { get { return weight; } } public double Value { get { return value; } } public double Cost { get { return cost; } } } }
Implementera Greedy Three med ett steg med fraktionerad fyllning:
public void KnapsackGreProc(int[] W, int[] V, int M, int n) { KnapsackPackage[] packs = new KnapsackPackage[n]; for (int k = 0; k < n; k++) packs[k] = new KnapsackPackage(W[k], V[k]); Array.Sort<KnapsackPackage>(packs, (a, b) => b.Cost.CompareTo(a.Cost)); double remain = M; double result = 0d; for (int i = 0; i < n && remain > 0; i++) { if (packs[i].Weight <= remain) { remain -= packs[i].Weight; result += packs[i].Value; Console.WriteLine("Pack " + i + " - Weight " + packs[i].Weight + " - Value " + packs[i].Value); } else { double fraction = remain / packs[i].Weight; result += packs[i].Value * fraction; Console.WriteLine("Pack " + i + " - Fraction " + fraction + " - Value " + packs[i].Value * fraction); remain = 0; } } Console.WriteLine("Max Value:\t" + result); }
Funktion KnapsackGreProc() i C#
Motexempel: Giriga tre pรฅ 0/1 ryggsรคck
Giriga Tre รคr optimal fรถr Brรฅkvarianten, men pรฅ 0/1 Ryggsรคcken (dรคr fรถremรฅl inte kan delas) kan den besegras. Motexempel:
- Parametrar: n = 3, M = 10.
- Paket: {i = 1; W = 7; V = 9; kostnad = 9/7}, {i = 2; W = 6; V = 6; kostnad = 1}, {i = 3; W = 4; V = 4; kostnad = 1}.
- Greedy Three vรคljer paket 1 fรถr totalt vรคrde 9, medan det optimala 0/1-valet (paket 2, paket 3) nรฅr 10.
Lรคrdomen: anvรคnd Greedy Three endast nรคr brรฅk รคr tillรฅtna. Fรถr 0/1-varianten, anvรคnd Dynamisk programmering istรคllet.
Tillรคmpningar av fraktionerad ryggsรคck
- Lastning dรคr flytande, pulveriserade eller bulkgods kan delas upp efter vikt.
- Portfรถljallokering รถver investeringsalternativ som accepterar delfinansiering.
- Molnbandbreddsdelning dรคr flรถden kan fรถrbruka en brรฅkdel av en lรคnk.
- CPU-schemalรคggning under en delad tidssegmentmodell med delbara arbetsbelastningar.
- AI-resursallokering dรคr ett utbildningsjobb kan anvรคnda en brรฅkdel av en GPU.





