Greedy heurisztikán alapuló közelítő algoritmusok
Greedy heurisztika Ha a greedy módszer, nem határozza meg egy feladat optimális eredményét, heurisztikus greedy módszernek nevezzük (a görög heuriskein = felfedezni). Ahhoz, hogy bebizonyítsuk, hogy a greedy módszer nem állapítja meg mindig az optimális eredményt elég, ha találunk egy olyan esetet, amire a módszer nem határozza meg az optimumot. A heurisztikus greedy algoritmusok lehetővé teszik néhány sajátos eset kizárása után a feladat gyors megoldását, olyankor, amikor a pontos megoldás exponenciális időt igényelne. Más esetben, megelégszünk egy „majdnem” optimummal, vagy egy közelítő eredménnyel, mivel a pontos eredményt meghatározó algoritmus költsége túlságosan nagy.
Az utazóügynök problémája Egy utazóügynök az áruját olyan körúton szeretné eladni, amely n városon halad át úgy, hogy a körút végén visszatér a városba ahol lakik. Adottak páronként a városok közötti közvetlen távolságok. Határozzuk meg az utazóügynök útvonalát úgy, hogy az a lehető legrövidebb legyen, és a kiindulópontot kivéve, minden városon csak egyszer haladjon át.
Megoldás Nem irányított gráf: G = (X, U), ahol X = a városok halmaza és U = a várospárok halmaza, amelyek között van közvetlen út, tehát a gráf teljes. a G teljes gráfban egy minimális hosszúságú hamilton-kört kell meghatároznunk (a hamilton-kör, olyan kör a gráfban, amely a gráf minden csomópontján pontosan egyszer halad át, és visszatér a kiindulópontba).
Elemzés Egy n csomóponttal rendelkező teljes gráf különböző hamilton-köreinek száma: n!/2n = (n – 1)!/2 Az {1, 2, …, n} halmaz valamennyi permutációja egy-egy körnek felel meg. Mindenik felírható 2n különböző módon, aszerint, hogy honnan indulunk, és milyen irányban járjuk be a kört). A halmaz, ahonnan a legrövidebb hamilton-kört ki kell választanunk, még n kicsi értékeire is nagy. Egyetlen hamilton-kör meghatározása is csak költséges algoritmusokkal lehetséges.
Elemzés Greedy stratégia: sorba vesszük a városokat, és minden lépésnél a legtöbbet „ígérőt” választjuk ki. A kiindulópont az 1-es város, ez lesz az első, amit kiválasztunk. A továbbiakban, ha a v1, v2, …, vi-1 városokat már kiválasztottuk, a legtöbbet ígérő következő város az lesz, amely a legkisebb távolságra van vi-1-től és még nem volt kiválasztva. Ez a válogatás nem mindig vezet optimális eredményhez, mivel miközben haladunk az útvonal meghatározásával, a halmaz számossága, ahonnan válogatjuk a városokat, egyre csökken és így előfordulhat, hogy az egy adott pillanatban még kiválasztható városok mind nagy távolságra esnek az utoljára kiválasztott várostól. A lokális minimum kiválasztása nem garantálja a globális minimumot.
Példa A legrövidebb hamilton-kör: Cmin = {1, 4, 2, 3, 5, 1} Hossza: 3 + 5 + 3 + 3 + 30 = 44 A greedy módszerrel generált kör: C1 = {1, 2, 3, 5, 4, 1} hossza: 111 Ha megcseréljük a kiindulópontot lehet, hogy találunk jobb megoldást. Például a C2 = {2, 1, 4, 3, 5, 2} körnek, amely felírható {1, 4, 3, 5, 2, 1} alakban, a hossza 78 < 111.
Algoritmus kör_hossza(n, t, k, kör): Minden i=1,n végezd el: még_nincsi igaz vége(minden) kör1 k { a kör a k csomópontból indul } még_nincsk hamis { k rajta van a körön } táv 0 { az aktuális kör hossza } Minden i=2,n végezd el: { a többi csomópont } előző köri-1 { megjegyezzük az „előző” csomópontot és } város Legközelebb(előző) { megkeressük legközelebbit } köri város { a legközelebbi „város” bekerül a körbe } még_nincsváros hamis{„város” a körön van: az „előző” és a } {„város” közti távolságot hozzáadjuk a kör hosszához } táv táv + telőző,város vége(minden) táv táv + tváros,k { zárul a kör k-ban } kör_hossza táv { térítjük a kör hosszát („táv”) } Vége(algoritmus)
Algoritmus Legközelebb(n, t, i, még_nincs): { egyszerű minimumkiválasztás, a függvény az } { i-hez legközelebbi csomópont indexét téríti } min végtelen Minden j=1,n végezd el: Ha még_nincsj és (tij < min ) akkor min tij jmin j vége(ha) vége(minden) Legközelebb jmin Vége(algoritmus)
Algoritmus Utazóügynök(n, t, mintáv, minkör): { egyszerű minimumkiválasztás, a legrövidebb kört } { határozzuk meg } mintáv végtelen Minden k=1,n végezd el: { minden pont lehet kiinduló } táv kör_hossza(k) Ha táv < mintáv akkor minkör kör mintáv táv { a legkisebb hosszúságú kör hossza } vége(ha) vége(minden) Vége(algoritmus)
Gráfszínezés Legyen egy n csomópontú nem irányított gráf, amelynek adottak az élei. Határozzuk meg a csomópontok legkevesebb színnel való befestését úgy, hogy bármely két szomszédos csomópont különböző színű legyen. Megjegyzések Ezt a feladatot általában a backtracking módszerrel oldjuk meg. Egy síkbeli gráf n csomópontja (k lehetséges színből) pontosan k = 4 legkevesebb színnel színezhető ki.
Elemzés A színezés optimális változatát egy kn elemű halmaz egy részhalmaza jelenti. Ha eltekintünk a követelménytől, hogy két szomszédos csomópont ne legyen azonos színű, minden csomópont befesthető k színnel, tehát kn különböző befestési mód létezik. Ha n értéke kicsi, a backtracking jól használható, de nagy értékekre elfogadhatatlan.
Elemzés Greedy módszer: a gráf csomópontjait egymás után úgy próbáljuk kiszínezni, hogy a szükséges színek száma minimális legyen: Befestjük az 1-es csomópontot az 1-es színnel, majd a többi i (i = 2, …, n) csomópont számára kiválasztjuk a legkisebb sorszámú színt, amely különbözik az illető csomóponttal illeszkedő csomópontok színétől. De: nem bízhatunk abban, hogy a greedy stratégia optimális megoldást talál.
Példa a) Optimális megoldás: 3 szín b) a greedy módszerrel talált megoldás: 4 szín
Algoritmus min_szín(i): min 1 Ismételd jó_szín igaz Minden j=1,i-1 végezd el: Ha szomszédij és (színj = min) akkor jó_szín hamis min min + 1 kilépünk a Minden-ből vége(ha) vége(minden) ameddig jó_szín min_szín min { a legkisebb használható szín } Vége(algoritmus)
Algoritmus Színezés(színek_száma, szín): színek_száma 1 szín1 1 Minden i=2,n végezd el: színi min_szín(i) { a legkisebb szín, amely különbözik a szomszédok színétől } Ha színi > színek_száma akkor színek_száma színi vége(ha) vége(minden) Vége(algoritmus)
Összegkifizetés minimumszámú bankjeggyel Határozzuk meg egy módját az S pénzösszeg minimumszámú bankjeggyel való kifizetésének. A b1, b2, …, bn címletű bankjegyek végtelen számban állnak rendelkezésünkre. Megoldás A pontos megoldást backtracking módszerrel adhatjuk meg. Próbáljuk megoldani a feladatot egy mohó algoritmussal! Ha minimumszámú bankjegyet szeretnénk felhasználni, előbb ki kellene fizessük azt az összeget amit még ki lehet fizetni a legnagyobb címletű bankjeggyel. Következésképpen, a bankjegyeket értékük szerint csökkenő sorrendbe rendezzük: b1 b2 … bn.
Megoldás Egymás után megállapítjuk azt a legnagyobb indexű bi bankjegyet, amivel ki lehet fizetni az S-ből még kifizetetlen összeget: szi = [S/bi] (S = az összeg, amit a bi, …, bn bankjegyekkel fogunk kifizetni). De így előfordulhat, hogy a fennmaradt összeget nem lehet kifizetni a még kiválasztatlan bankjegyekkel és így a greedy módszer nem találta meg az egyébként létező megoldást. Példa Ha S = 96 és b1 = 13, b2 = 12 és b3 = 3 Optimális megoldás 8 bankjegy (értékük 12) A greedy módszer: 7 bankjegy a 13 értékűből, marad S = 5 amit nem lehet kifizetni a megmaradt bankjegyekkel.
Példa Ha b1 = 13, b2 = 12 és b3 = 1, az S = 96 összeg 12 bankjeggyel fizethető ki: 7 darab 13 értékű és 5 darab 1 értékű. Ha túl sok nagy értékű bankjegyet használunk fel, előfordulhat, hogy a fennmaradt összeget túl sok kis értékű bankjeggyel kell kifizetnünk.
Algoritmus Összegkifizetés(n,b,S,nrb,sz): Minden i=1,n végezd el: { kifizetünk [S/bi] darab bi címletű bankjegyet } szi [S/bi] nrb nrb + szi S S - szi*bi Ha S = 0 akkor Kiir(i) Leálljuk az algoritmust vége(ha) vége(minden) Ki: 'A greedy módszer nem talált megoldást.' Vége(algoritmus)
Megjegyzés Előfordulhat, hogy a greedy nem talál egyáltalán megoldást, pedig létezik megoldás. A feladat megoldása a backtracking módszerrel használta a greedy stratégia ötletét, így viszonylag hamar megtaláltuk az optimális megoldást, és leállíthattuk a rekurzív hívásokat, amikor valamely részeredmény túllépte az eddig megtalált minimumot. A greedy és a backtracking módszerek kombinálása hozzásegített a pontos megoldás gyors megtalálásához.