24.03.2015 Views

2 dalis - techmat.vgtu.lt

2 dalis - techmat.vgtu.lt

2 dalis - techmat.vgtu.lt

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Algoritmų sudarymo principai ir metodai<br />

Algoritmų analizės specialieji skyriai<br />

doc. dr. Vadimas Starikovičius<br />

VGTU Matematinio modeliavimo katedra<br />

VGTU SC Lygiagrečiųjų skaičiavimų laboratorija<br />

Paskaitų kursas. 2-oji <strong>dalis</strong>.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Turinys<br />

1 Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Tai bendras daugelio uždavinių sprendimo algortimų sudarymo<br />

principas, kai sprendinį galima rasti patikrinus baigtinį<br />

variantų skaičių. Šis metodas ypač išpopuliarėjo, kai atsirado<br />

kompiuteriai. Sudarant konkretų algoritmą, iškyla 2 uždaviniai:<br />

1 Kaip gauti visus įmanomus variantus?<br />

2 Kaip sumažinti tikrinamų variantų skaičių, nes tiesioginis<br />

(pilnas) visų variantų patikrinimas gali būti praktiškai<br />

neįvykdomas net su greičiausiais superkompiuteriais?<br />

Šių uždavinių sprendimui naudojami įvairiausi metodai:<br />

1 specialūs kombinatorikos algoritmai, rekursija, ...<br />

2 šakų ir rėžių, dinaminio programavimo metodai, euristikos.<br />

Atvirkštinis pavyzdys: informacijos kodavimas ir jos dešifravimas.<br />

Informacija turi būti užkoduota taip, kad jos dešifravimui nebūtų<br />

galima sudaryti algoritmo su mažu variantų skaičiumi.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Rekursijos metodas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursija yra plačiai naudojama apibrėžiant matematinius<br />

objektus, sudarant bei realizuojant įvairiausius algoritmus.<br />

Rekursijos schema<br />

Objektas, priklausantis nuo parametro, yra apibrėžiamas<br />

naudojant tą patį objektą ar objektus, tik su kitomis<br />

parametro reikšmėmis.<br />

Nurodoma rekursijos pabaiga ir nustatomos pradinės<br />

sąlygos. Šių sąlygų skaičius sutampa su rekursijos gyliu.<br />

Pavyzdys. Fibonačio skaičiai (it. Leonardo Fibonaci).<br />

Aptinkami įvairiuose informatikos algoritmuose. Jie apibrėžiami<br />

tokiu būdu:<br />

{<br />

fn−1 + f n−2 , jei n > 1,<br />

f n =<br />

f 0 = 1, f 1 = 1 .<br />

doc. dr. Vadimas Starikovičius Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursinis Fibonačio skaičių radimo algoritmas<br />

Kai objektas (uždavinys) apibrėžiamas rekursijos pagalba, lengvai<br />

gaunamas objekto radimo (uždavinio sprendimo) rekursinis<br />

algortimas.<br />

int Fib (n)<br />

begin<br />

(1) if ( n < 2 ) return (1);<br />

else<br />

(2) return<br />

end if<br />

end Fib<br />

(<br />

Fib(n-1) + Fib(n-2)<br />

Rekursinio algoritmo vykdymo eiga, kai n = 4 ir n = 20:<br />

)<br />

;<br />

Daug kartų skaičiuojame tas pačias reikšmes!<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursinio Fibonačio skaičių algoritmo sudėtingumas<br />

Bazine algoritmo operacija laikykime sudėtį ir ignoruokime<br />

papildomas sąnaudas, atsirandančias realizuojant rekursijos<br />

kreipinius (praktijoje vis dė<strong>lt</strong>o šios sąnaudos pasirodo gana<br />

didelės). Gauname tokią rekurentinę lygtį ir pradines sąlygas:<br />

⎧<br />

⎨T(n) = T(n − 1) + T(n − 2) + 1,<br />

⎩T(0) = 1, T(1) = 1.<br />

Atlikę skaičiavimus, randame funkciją T(n):<br />

√<br />

( 1 + 5<br />

T(n) = c<br />

2<br />

) n<br />

+ (2 − c)<br />

( 1 −<br />

√<br />

5<br />

2<br />

√<br />

) n ( 1 + 5 ) n<br />

− 1 ≈ c .<br />

2<br />

Taigi rekursinis Fibonačio algoritmas yra eksponentinio<br />

sudėtingumo. Padidėjus vienetu duomenų skaičiui n,<br />

algoritmo vykdymo eiga pailgėja (1 + √ 5)/2 = 1, 618 kartų.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursinio Fibonačio skaičių radimo algoritmo<br />

skaičiavimo eksperimentas<br />

Šią teorinę išvadą patvirtina ir atlikto skaičiavimo<br />

eksperimento rezu<strong>lt</strong>atai:<br />

n skaičiavimo laikas T n ρ n = T n<br />

T n−1<br />

40 2,88 1,610<br />

41 4,68 1,625<br />

42 7,57 1,617<br />

43 12,25 1,618<br />

Atlikta analizė rodo, kad dideliems n, rekurisnis algoritmas<br />

praktiškai nenaudotinas (T(100) ≈ 317000 metų). Kaip dar<br />

galima rasti Fibonačio skaičius?<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Iteracinis Fibonačio skaičių radimo algoritmas<br />

Fibonačio skaičius galime rasti ir iteraciniu algoritmu:<br />

FibIter (n)<br />

begin<br />

(1) f2 = 1; f1 = 1; Fib = 1;<br />

(2) for ( i = 2; i


Algoritmų sudarymo principai ir metodai<br />

Kada reikalinga rekursija?<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Naudojant rekursiją, patogu kontroliuoti užduočių atlikimo eiliškumą,<br />

kai to reikalauja sprendžiamas uždavinys. Pavyzdžiui, dvejetainio<br />

medžio viršūnių aplankymo algoritmai: prefix, infix ir postfix.<br />

Prefix (node* tree)<br />

begin<br />

(1) if ( tree != NULL )<br />

(2) print(tree->data);<br />

(3) Prefix (tree->left);<br />

(4) Prefix (tree->right);<br />

end if<br />

end Prefix<br />

Infix (node* tree)<br />

begin<br />

(1) if ( tree != NULL )<br />

(2) Infix (tree->left);<br />

(3) print(tree->data);<br />

(4) Infix (tree->right);<br />

end if<br />

end Infix<br />

Postfix (node* tree)<br />

begin<br />

(1) if ( tree != NULL )<br />

(2) Postfix (tree->left);<br />

(3) Postfix (tree->right);<br />

(4) print(tree->data);<br />

end if<br />

end Postfix<br />

Pavyzdys. Tarkime, aritmetinė išraiška<br />

(a − b ∗ c)(d ∗ e + f ) saugoma dvejetainiame medyje.<br />

Tada, naudodami Prefix, Infix ir Postfix algoritmus,<br />

gauname tokias šios išraiškos formas:<br />

a) prefix: ∗ − a ∗ bc + ∗def , b) infix: a − b ∗ c ∗ d ∗ e + f ,<br />

c) postfix: abc ∗ −de ∗ f + ∗.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas grįžtant atgal<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursija yra labai naudinga sprendžiant uždavinius variantų<br />

perrinkimu su grįžimu atgal (angl. backtrack). Pavyzdžiui,<br />

1) Kaip pereiti per labirintą? 2) Žirgo maršrutas šachmatų lentoje?<br />

Sudarysime rekursinį algortimų šabloną (angl. template)<br />

tokių uždavinių sprendimui.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Variantų perrinkimo šablonas grįžtant atgal<br />

Sprendžiant konkretų uždavinį turime apibrėžti duomenų struktūrą pozicija,<br />

kurioje saugosime informaciją apie uždavinio sprendimo eigą (pvz., praeitą<br />

maršrutą labirinte arba šachmatų lentoje).<br />

Sprendinio paieška tęsiama iš P taško (pvz., P - lentos langelis).<br />

Turime apibrėžti funkciją S=BandymųAibė(P, pozicija), kuri generuoja<br />

visus naujus ėjimus, kuriuos galima atlikti iš taško P. Leistinų ėjimų aibę S<br />

apibrėžia uždavinio sąlygos ir duomenų struktūroje pozicija saugoma<br />

informacija apie jau aplankytas paieškos vietas.<br />

Cikle pasirenkame vieną po kito ėjimus iš S, kiekvienam gauname naują<br />

tašką U, kurį įtraukiame į pozicija, ir gautai naujai pozicijai rekursyviai<br />

kviečiame pagrindinę algoritmo funkciją (variantų perrinkimo šabloną).<br />

Jei padarę kažkurį ėjimą gauname, kad naujos pozicijos S yra tuščia arba<br />

netiko nei vienas iš naujos S ėjimų (pranešime apie tai grąžindami reikšmę<br />

0), tai turime grįžti atgal, atstatyti seną poziciją (SenaPozicija(U, pozicija))<br />

ir tikrinti kitą leistiną ėjimą.<br />

Kai surandame sprendinį RadomeSprendinį (pozicija) == taip, grąžiname<br />

reikšmę 1, taip panešdami šią funkciją iškvietusiai funkcijai, kad sprendinys<br />

rastas ir ji irgi gali nutraukti savo darbą grąžindama 1.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Rekursinis algortimų šablonas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

int Tikrink (int n, Point P, Inf pozicija)<br />

begin<br />

(1) if ( RadomeSprendinį (pozicija) == taip ) then<br />

(2) Spausdink (pozicija);<br />

(3) return(1);<br />

(4) else<br />

(5) S = BandymųAibė(P, pozicija)<br />

(6) while ( S ≠ ∅ ) do<br />

(7) U = NaujasBandymas(S);<br />

(8) NaujaPozicija(U, pozicija);<br />

(9) if ( Tikrink (n+1, U, pozicija) == 1 ) return (1);<br />

(10) else<br />

(11) SenaPozicija(U, pozicija);<br />

end if<br />

end do<br />

(12) return (0);<br />

end if<br />

end<br />

Tikrink<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Skaldyk ir valdyk metodas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Daugelio uždavinių efektyvius sprendimo algoritmus sudarome<br />

tokiu metodu:<br />

1 Uždavinį skaidome į kelis mažesnius uždavinius.<br />

2 Randame šių uždavinių sprendinius.<br />

3 Iš jų sudarome viso uždavinio sprendinį.<br />

Dalinius uždavinius vėl galime spręsti tokiu pačiu metodu. Taip<br />

skaidome tol, kol gautieji uždaviniai yra lengvai išsprendžiami.<br />

Taip gauname rekursinį skaldyk ir valdyk metodo (angl.<br />

divide and conquer) algoritmą.<br />

Sprendžiant konkretų uždavinį reikia apibrėžti, kaip<br />

realizuojami šie trys žingsniai. Tai galima daryti įvairiai, todėl<br />

dažnai tam pačiam uždaviniui skaldyk ir valdyk metodu galime<br />

sudaryti kelis skirtingus sprendimo algoritmus.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursinių skaldyk ir valdyk algortimų šablonas<br />

Sprendžiame uždavinį, kurį apibūdina duomenų struktūrą A.<br />

SprendTipas SkaldykIrValdyk (Inf A)<br />

begin<br />

(1) if ( |A| > ε ) then<br />

(2) (A 1 , A 2 , . . . , A M ) = Skaldyk (A);<br />

(3) for all ( A j , j=1, 2,…, M ) do<br />

(4) S j = SkaldykIrValdyk (A j );<br />

end do<br />

(5) S = Valdyk (S 1 , S 2 , . . . , S M );<br />

else<br />

(6) S = Sprendinys(A)<br />

end if<br />

(7) return (S);<br />

end SkaldykIrValdyk<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Rekursinių skaldyk ir valdyk algortimų sudėtingumas<br />

Tarkime, kad n dydžio uždavinį dalijame į a mažesnių<br />

uždavinių, kurių dydis yra n/b, o atskirų sprendinių sujungimo<br />

sąnaudos yra d(n).<br />

Kai uždavinys yra mažas, t. y. n = 1, jį išsprenžiame kokiu nors<br />

paprastu algoritmu, o veiksmų skaičių žymėsime c.<br />

Tokio algoritmo sudėtingumo funkcija tenkina uždavinį:<br />

⎧<br />

⎨c, jei n = 1 ,<br />

T(n) =<br />

⎩aT(n/b) + d(n), jei n > 1 .<br />

Kai n = b m , jo sprendinį jau apskaičiavome:<br />

T(n) = ca m + ∑ m−1<br />

j=0 aj d(b m−j ).<br />

Jei, a = 2, b = 2, d = gn, tai skaldyk ir valdyk algoritmo<br />

sudėtingumo funkcijaT(n) = O(n log n).<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Pavyzdys. Dvieju gretimų taškų radimas.<br />

Turime n = 2 m taškų aibę<br />

P(n) = {P j = (x j , y j ), j = 1, 2, . . . , n}.<br />

Atstumą tarp dviejų taškų P i ir P j apibrėžiame lygybe<br />

d(P i , P j ) = ( (x i − x j ) 2 + (y i − y j ) 2) 1/2 .<br />

Reikia rasti tokius du taškus P q ir P r , tarp kurių atstumas yra<br />

mažiausias<br />

d(P q , P r ) = min d(P i, P j ).<br />

1≤i,j≤n<br />

Koks yra pilno taškų porų perrinkimo algoritmo<br />

sudėtingumas? Iš viso galime sudaryti n(n−1)<br />

2<br />

skirtingas taškų<br />

poras, todėl tokio algoritmo sudėtingumas yra O(n 2 ).<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Skaldyk ir valdyk metodu sudarykime šio uždavinio sprendimo<br />

algortimą. Sunumeruokime taškus koordinatės x didėjimo<br />

tvarka: x 1 ≤ x 2 ≤ . . . ≤ x n .<br />

Padalinkime visus taškus į dvi vienodo dydžio aibes:<br />

(n ) {<br />

P L = Pj , j = 1, 2, . . . , n } ,<br />

2 2<br />

(n ) {<br />

P R = Pj , j = n 2<br />

2 + 1, 2, . . . , n} .<br />

Tada teisingas vienas iš šių teiginių:<br />

1 Abu taškai P q , P r priklauso aibei P L<br />

( n<br />

2<br />

) .<br />

2 Abu taškai P q , P r priklauso aibei P R<br />

( n<br />

2<br />

) .<br />

3 Taškas P q priklauso aibei P L<br />

( n<br />

2<br />

) , o taškas Pr priklauso<br />

aibei P R<br />

( n<br />

2<br />

) .<br />

Taigi, galime taikyti rekursinių skaldyk ir valdyk algortimų<br />

šabloną.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

float GretimiTaškai (Set P, int n)<br />

begin<br />

(1) if ( n > 2 )<br />

(2) p L = GretimiTaškai (P L , n 2 );<br />

(3) p R = GretimiTaškai (P R , n 2 );<br />

(4) p T = min(p L , p R );<br />

(5) p = Pasienis (P L , P R , p T );<br />

else<br />

(6) p = d (P 1 , P 2 );<br />

end if<br />

(7) return (p);<br />

end GretimiTaškai<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dabar pateiksime procedūros Pasienis realizaciją. Užtenka<br />

nagrinėti tik taškus, priklausančius pasienio juostai:<br />

P B (n) = {P j : x n/2+1 − p T < x j < x n/2 + p T , j = s, s + 1, . . . , f }.<br />

float Pasienis (Set P L , Set P R , float p T )<br />

begin<br />

(1) for (i=s; i


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Šakų ir rėžių metodas (angl. branch and bound method)<br />

Perrinkant variantus, skaidant ir sprendžiant mažesnius<br />

po-uždavinius, labai svarbu kuo anksčiau išskirti tuos<br />

variantus (po-uždavinius), kuriems uždavinio sprendinys<br />

tikrai nepriklauso, ir šių variantų (po-uždavinių) toliau<br />

nenagrinėti.<br />

Šakų ir rėžių metodas yra bendras metodas, nurodantis<br />

kaip konstruoti tokius sprendimo algoritmus globaliosios<br />

optimizacijos uždaviniams.<br />

Nagrinėsime funkcijos f (X) minimizavimo uždaroje ir<br />

baigtinėje srityje D uždavinį:<br />

f (X 0 ) = min<br />

X∈D f (X).<br />

Jį žymėsime P(f , D). D vadinama leistinųjų sprendinių<br />

aibe (paieškos aibe) ir gali būti įvairiausių prigimčių.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Šakų ir rėžių metodo pagrindiniai žingsniai<br />

Šakų ir rėžių metode yra 2 pagrindiniai žingsniai, kurie turi būti<br />

apibrėžti sudarant konkretų tam tikro uždavinio sprendimo<br />

algoritmą.<br />

1. Skaidymo (angl. branching) žingsnis. Leistinųjų<br />

sprendinių aibę skaidome į baigtinį skaičių mažesnių aibių:<br />

m⋃<br />

D = D i .<br />

i=1<br />

Tada funkcijos f (X) minimumo paieškos algoritmą patogu<br />

vaizduoti medžio duomenų struktūroje. Medžio šaknyje<br />

užrašome uždavinį P(f , D), šaknies m vaikai apibrėžia<br />

uždavinius P(f , D i ), t. y. funkciją f (X) minimizuojame srityse<br />

D i . Toks skaidymo procesas tęsiamas, kol nesunkiai<br />

apskaičiuojame gautojo uždavinio sprendinį.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

2. Rėžių apskaičiavimo (angl. bounding) žingsnis.<br />

Algoritme turime apibrėžti, kaip efektyviai apskaičiuoti<br />

funkcijos f (X) minimumo srityje D i apatinį LB(f , D i ) ir<br />

viršutinį UB(f , D i ) rėžius:<br />

LB(f , D i ) ≤ min<br />

X∈D i<br />

f (X) ≤ UB(f , D i ).<br />

Tada, žinodami UB(f , D i ), galime apskaičiuoti minimalios<br />

reikšmės f (X 0 ) viršutinį rėžį UB(f , D) visoje aibėje D:<br />

UB(f , D) = min<br />

1≤i≤m UB(f , D i).<br />

Žinodami šiuos rėžius, dažnai galime gerokai sumažinti<br />

nagrinėjamų sričių skaičių. Jeigu srityje D i apatinis f (X)<br />

reikšmių rėžis LB(f , D i ) yra didesnis už UB(f , D):<br />

LB(f , D i ) > UB(f , D), tai tokios srities toliau nebetiriame, nes<br />

joje tikrai nėra optimalaus sprendinio.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Šakų ir rėžių metodo algortimo šablonas<br />

Sudarykime šakų ir rėžių metodo algortimo šabloną.<br />

Tegu visos užduotys saugomos sąraše L.<br />

O geriausias šiuo metu žinomas sprendinys saugomas<br />

struktūroje S. S galėtų būti ir sąrašas, jei reikia išsaugoti<br />

visus gaunamus galimus sprendinius.<br />

Naują užduotį išimame iš sąrašo L, naudodami parinkimo<br />

taisyklę (angl. selection rule). Dažniausiai naudojamas<br />

taisykles aptarsime vėliau.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

begin BranchAndBound ⋃ ()<br />

m<br />

(1) Išskaidome D =<br />

i=1 D i, apskaičiuojame rėžius LB(D i ), UB(D i ),<br />

užduotis P(f , D i ) įtraukiame į sąrašą L = {P(f , D i ), 1 ≤ i ≤ m},<br />

S = ∅, apskaičiuojame UB(D) = min 1≤i≤m UB(D i ).<br />

(2) while (L ≠ ∅) do<br />

(3) Naudodami ( parinkimo ) taisyklę išimame užduotį P(f , D i ) ∈ L<br />

(4) if LB(Di ) < UB(D) then<br />

⋃ m<br />

(5) Išskaidome aibę D i =<br />

j=1 D ij<br />

(6) for all (D ij , j = 1, m) do<br />

(7) Apskaičiuojame ( rėžius UB(D ij ) ir ) LB(D ij )<br />

(8) UB(D) = min UB(D), UB(D ij ) //Galimai patiksliname rėžį<br />

(9) ( ) if LB(D ij ) < UB(D) then<br />

(10) if (P(f , D ij ) yra lapas ) then //Nebeskaidoma sritis<br />

(11) S = Sprendinys(D ij , S) //Ar D ij turi geresnį sprendinį<br />

(12) else // negu turimas S?<br />

(13) L := L ∪ P(f , D ij ) //Įtraukiame į sąrašą<br />

end if<br />

end if<br />

end do<br />

end if<br />

end do<br />

end BranchAndBound<br />

doc. dr. Vadimas Starikovičius Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dažniausiai naudojamos parinkimo taisyklės<br />

1. Naujausia užduotis. Tiriame užduotį, kurią vėliausiai<br />

sugeneravome. Naudodami tokią strategiją, greitai judame į<br />

variantų medžio gilumą ir minimizuojame saugomų užduočių<br />

skaičių (angl. depth-first search). Sąrašą L realizuojame<br />

naudodami dėklo (angl. stack) duomenų struktūrą.<br />

2. Perspektyviausia užduotis. Tiriame užduotį P(f , D i ),<br />

kurios sprendinių apatinis įvertis LB(f , D i ) yra mažiausias<br />

(angl. best-first search). Tikimės, kad, skaidydami šią užduotį,<br />

greičiau rasime gerus sprendinio artinius arba pavyks iš esmės<br />

sumažinti viršutinį sprendinio įvertį UB(f , D). Tada smarkiai<br />

sumažės ir nagrinėjamų variantų skaičius. Sąrašą L realizuojame<br />

naudodami piramidės (angl. heap) duomenų struktūrą.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dažniausiai naudojamos parinkimo taisyklės<br />

3. Mažiausio lygio užduotis. Tiriame užduotį P(f , D i ),<br />

kurios lygis medyje yra mažiausias (angl. breath-first search).<br />

Naudodami šią strategiją, tolygiai nagrinėjame visą leistinųjų<br />

sprendinių aibę, t. y. tikimės išvengti detalaus nereikalingų<br />

lokaliųjų minimumų nagrinėjimo. Sąrašą L realizuojame<br />

naudodami eilės (angl. queue) duomenų struktūrą.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Pavyzdys. Globalus Lipšico funkcijos minimumas.<br />

Rasime vienmatės funkcijos f (x) globalų minimumą uždarame<br />

intervale [a, b]:<br />

f (x 0 ) = min<br />

x∈[a,b] f (x).<br />

Tarsime, kad f yra Lipšico funkcija, t. y. egzistuoja konstanta<br />

L, leidžianti įvertinti funkcijos reikšmių skirtumus:<br />

|f (x) − f (y)| ≤ L|x − y|, x, y ∈ [a, b].<br />

Visos tolydžiai diferencijuojamos funkcijos yra ir Lipšico<br />

funkcijos, konstantą L randame imdami funkcijos išvestinės<br />

reikšmių modulio viršutinį rėžį:<br />

|f ′ (x)| ≤ L, x ∈ [a, b].<br />

Visai nebūtina rasti tikslųjį rėžį L, bet kuo mažesnė L reikšmė,<br />

tuo efektyvesnis šakų ir rėžių algoritmas. Pvz., y = sin x, L =?<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Funkcijos minimumo radimo šakų ir rėžių algoritmas<br />

Pagal šakų ir rėžių metodą turime apibrėžti skaidymo žingsnį ir<br />

rėžių apskaičiavimo taisykles.<br />

1. Skaidymo žingsnis. Uždavinio P(f , [a i , b i ]) intervalą<br />

skaidome į du naujus lygius intervalus:<br />

[a i , b i ] = [a i , c i ] ∪ [c i , b i ], c i = a i+b i<br />

2<br />

.<br />

Taip gauname du naujus mažesnius uždavinius P(f , [a i , c i ]) ir<br />

P(f , [c i , b i ]).<br />

Jei b i−a i<br />

2<br />

< ε, kur ε reikalaujamas tikslumas, tai intervalas<br />

toliau nebeskaidomas, o gaunamas uždavinio P(f , [a i , b i ])<br />

sprendinys s i tikslumu ε:<br />

f (s i ) = min(f (a i ), f (c i ), f (b i ))<br />

ir palyginamas su šiuo metu turimu sprendiniu s:<br />

doc. dr. Vadimas Starikovičius<br />

f (s) = min(f (s i ), f (s)).<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Funkcijos minimumo radimo šakų ir rėžių algoritmas<br />

2.1 Viršutinio įverčio skaičiavimo taisyklė. Uždavinio<br />

P(f , [a i , b i ]) sprendinio x 0i viršutinį rėžį UB(f , [a i , b i ]) galima<br />

gauti taip:<br />

f (x 0i ) =<br />

min f (x) ≤ min(f (a i), f (c i ), f (b i )) = UB(f , [a i , b i ]).<br />

x∈[a i ,b i ]<br />

Galima imti ir daugiau intervalo [a i , b i ] vidinių taškų.<br />

2.2 Apatinio įverčio skaičiavimo taisyklė. Uždavinio<br />

P(f , [a i , b i ]) sprendinio x 0i apatinį rėžį LB(f , [a i , b i ]) randame,<br />

taikydami Lipšico funkcijų apibrėžimą:<br />

|f (x 0i ) − f (c i )| ≤ L|x 0i − c i | ≤ L b i−a i<br />

2<br />

.<br />

f (x 0i ) ≥ f (c i ) − L b i−a i<br />

2<br />

= LB(f , [a i , b i ]).<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Lošimų teorijos algoritmai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Daugelį žaidimų galime aprašyti tokia bendra schema:<br />

1. Lošėjai paeiliui atlieka leistinus žaidimo ėjimus. Visą žaidimo<br />

eigą aprašome naudodami medžio duomenų struktūrą. Medžio<br />

viršūnėje saugome pradinę žaidimo poziciją. Viršūnės vaikai<br />

apibrėžia pozicijas, kurias gauname atlikę pirmąjį ėjimą ir t. t.<br />

Medžio lapuose saugome baigiamąsias žaidimo pozicijas.<br />

2. Remdamiesi žaidimo taisyklėmis, galime įvertinti visas<br />

pabaigos pozicijas tam tikru svoriu. Pavyzdžiui, šachmatuose<br />

visas pozicijas, kuriose laimi ba<strong>lt</strong>osios figūros, įvertiname 1,<br />

juodųjų figūrų laimėtas pozicijas vertiname (-1), o pozicijas, kai<br />

žaidimas baigėsi lygiosiomis, įvertiname 0.<br />

3. Lošėjai siekia priešingų tikslų: vienas nori, kad galutinės<br />

žaidimo pozicijos svoris būtų didžiausias, o antrasis stengiasi<br />

pasiekti mažiausio svorio baigiamąją poziciją.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Variantų perrinkimo algortimas su grįžimu atgal<br />

Apskaičiuojame optimalų rezu<strong>lt</strong>atą, kurį lošėjas gali pasiekti iš duotosios pozicijos<br />

A. Parametras tikslas (lygus MAX arba MIN) apibrėžia lošėjo strategiją.<br />

float Lošimas (pozicija A, int tikslas)<br />

begin<br />

(1) if ( A == pabaigosPozicija ) then<br />

(2) return Vertė(A);<br />

(3) else<br />

(4) if ( tikslas == MAX ) then<br />

(5) v = - ∞;<br />

(6) for all ( B ∈ Vaikai(A) ) do<br />

(7) v = max ( v, Lošimas (B, MIN) );<br />

end do<br />

(8) else<br />

(9) v = ∞;<br />

(10) for all ( B ∈ Vaikai(A) ) do<br />

(11) v = min ( v, Lošimas (B, MAX) );<br />

end do<br />

end if<br />

(12) return v;<br />

end if<br />

end Lošimas<br />

doc. dr. Vadimas Starikovičius Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Pavyzdys: lošimo uždavinio sprendimas su variantų<br />

perrinkimo algoritmu su grįžimu atgal<br />

Pradėkite nuo viršaus ir gaukite visų viršūnių svorius.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Šakų ir rėžių metodas taikymas lošimų uždaviniams<br />

Nagrinėjamų variantų skaičių galime sumažinti taikydami šakų<br />

ir rėžių metodą. Pritaikę jį lošimų algoritmams, gauname taip<br />

vadinama α–β metodą.<br />

Šio metodo idėja: vertindami viršūnės svorį, jį lyginame ir su<br />

viršūnės tėvo naujausiu įverčiu.<br />

Tarkime, kad viršūnės v tikslas yra MAX, o jos tėvo viršūnės w<br />

(jos strategija MIN) įvertis lygus α. Jeigu, tikrindami v vaikus,<br />

radome variantą, kurio svoris β ≥ α, tai nutraukiame tolesnę<br />

viršūnės v vaikų analizę, nes v pomedyje negali egzistuoti<br />

viršūnės w optimali žaidimo strategija. Taigi lošėjas, patekęs į<br />

w poziciją, niekada nesirinks ėjimo, vedančio į viršūnę v.<br />

Panašiai, jei viršūnės v tikslas yra MIN, tai jos vaikų analizę<br />

nutraukiame, jei radome variantą, kurio svoris β ≤ α.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

pav. : Lošimo uždavinio sprendimas α–β metodu. Pilka spalva<br />

pažymėtos tos medžio šakos ir viršūnės, kurių nereikia tikrinti<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

α–β algoritmas<br />

float αβ (pozicija A, int tikslas, double a)<br />

begin<br />

(1) if ( A == pabaigosPozicija ) then<br />

(2) return Vertė(A);<br />

else<br />

(3) B = KitasVaikas(A);<br />

(4) if ( tikslas == MAX ) then<br />

(5) v = - ∞; (6) while (v < a) && (B ≠ ∅) do<br />

(7) v = max (v, αβ (B, MIN, v) );<br />

(8) B = KitasVaikas(A);<br />

end do<br />

else<br />

(9) v = ∞; (10) while (v > a) && (B ≠ ∅) do<br />

(11) v = min (v, αβ (B, MAX, v) );<br />

(12) B = KitasVaikas(A);<br />

end do<br />

end if<br />

(13) return v;<br />

end if<br />

end<br />

αβ<br />

doc. dr. Vadimas Starikovičius<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Dinaminio programavimo metodas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Viso variantų perrinkimo algoritmai dažnai neefektyvūs dėl<br />

labai didelio nagrinėjamų variantų skaičiaus.<br />

Analizuodami daugelį tokių algoritmų matome, kad<br />

skaičiuojant daug kartų sprendžiame tas pačias užduotis.<br />

Šio trūkumo neturi dinaminio programavimo metodas, kurį<br />

pasiūlė Belmanas (R. Bellman).<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dinaminio programavimo metodo sąlygos<br />

Dinaminio programavimo metodas taikytinas tada, kai<br />

tenkinamos tokios sąlygos:<br />

1 Algoritmo vykdymo metu generuojamos užduočių aibės<br />

esmingai persidengia, todėl daug kartų sprendžiame tas<br />

pačias užduotis. Dinaminio programavimo metode<br />

įsimename jau spręstų užduočių sprendinius ir sprendžiame<br />

tik naujus uždavinius.<br />

2 Uždavinys tenkina Belmano sąlygą, kad optimalus<br />

sprendinys yra sudarytas iš atskirų mažesnių užduočių<br />

optimalių sprendinių. Šią sąlygą užrašome rekurentinės<br />

lygybės forma, ji smarkiai sumažina nagrinėjamų variantų<br />

skaičių.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Dinaminio programavimo metodo eiga<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Skaldyk ir valdyk algoritme užduotys generuojamos iš<br />

viršaus į apačią, t. y. pradinis uždavinys skaidomas į kelias<br />

mažesnes užduotis, kurios toliau dalijamos į mažesnes.<br />

Dinaminio programavimo metode uždavinį pradedame<br />

spręsti nuo mažiausių ir lengvai išsprendžiamų užduočių, jų<br />

rezu<strong>lt</strong>atus išsaugome (jei reikia) ir naudojame spręsdami<br />

didesnes užduotis. Taip surandame viso uždavinio<br />

sprendinį.<br />

Realizuodami dinaminio programavimo metodą<br />

nagrinėjame tik tuos variantus, kurių gali prireikti<br />

optimaliai strategijai sudaryti. Taip sataupome laiką, bet<br />

atsiranda papildomos atminties sąnaudos.<br />

Tokios strategijos pranašumus jau matėme nagrinėdami kai<br />

kuriuos rekursinius algoritmus, pvz., Fibonačio skaičius.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dinaminio programavimo metodo taikymo pavyzdys<br />

Pateiksime dar vieną panašų pavyzdį, kai ieškome, kiek yra<br />

skirtingų būdų išrinkti k daiktų iš n daiktų aibės.<br />

Atsakymą apibrėžia derinių kombinatorinė formulė<br />

C k n = n!<br />

k!(n−k)! ,<br />

tačiau ji netinka dideliems n, nes faktorialas - labai greitai<br />

didėjanti funkcija. Pvz., 13! = 6.227.020.800 > 2 32 =<br />

4.294.967.296, t.y. naudojant unsigned integer 32-bitų duomenų<br />

tipą negalime išreikšti n!, kai n ≥ 13.<br />

Tačiau šio duomenų tipo kintamajame galima išsaugoti C k n iki<br />

n = 34: C 17<br />

34 = 2.333.606.220.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Rekursyvus C k n skaičiavimo algoritmas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Cn k apskaičiavimui galime naudoti rekursinę lygybę:<br />

⎧<br />

1, k = 0,<br />

⎪⎨<br />

Cn k = Cn−1 k−1 + C n−1 k , 0 < k < n,<br />

⎪⎩<br />

1, k = n,<br />

kurios teisingumą patikriname atlikę elementarius veiksmus.<br />

int BinKoef (int n, int k)<br />

begin<br />

(1) if ( k == 0 || n == k ) then<br />

(2) return (1);<br />

(3) else<br />

(4) return ( BinKoef(n-1, k-1) + BinKoef(n-1, k) );<br />

end if<br />

end BinKoef<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Įvertinsime tokio algoritmo sudėtingumo funkciją T(n). Tegul,<br />

skaičiuodami binominį koeficientą Cn k , atliekame P(n, k)<br />

aritmetinių veiksmų. Tada T(n) = max 0≤k≤n P(n, k).<br />

Iš pateiktojo algoritmo gauname tokius sąryšius:<br />

⎧<br />

1, k = 0,<br />

⎪⎨<br />

P(n, k) = P(n − 1, k) + P(n − 1, k − 1), 0 < k < n,<br />

⎪⎩<br />

1, k = n,<br />

todėl P(n, k) = C k n . Jos reikšmė didžiausia, kai k = n/2. Taigi<br />

rekursinio algoritmo sudėtingumo funkcija<br />

T(n) = C n/2<br />

n =<br />

n!<br />

( (n/2)!<br />

) 2<br />

.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Pasinaudoję Stirlingo formule, gauname, kad<br />

n! = √ ( n ) n ( ) √ ( n ) n/2 ( )<br />

2πn 1+O(1/n) , (n/2)! = πn 1+O(1/n) ,<br />

e<br />

2e<br />

todėl teisingas asimptotinis įvertis T(n) = Θ(2 n / √ n).<br />

Matome, kad algoritmo veiksmų skaičius didėja eksponentiniu<br />

greičiu, taigi rekursyvus algoritmas yra paprastas, bet labai<br />

neefektyvus. Lentelėje pateikti skaičiavimo eksperimento<br />

rezu<strong>lt</strong>atai: T n yra binominio koeficiento Cn<br />

n/2 skaičiavimo<br />

laikas, ρ n =<br />

Tn<br />

T n−1<br />

.<br />

n T n ρ n<br />

32 18,5 2,015<br />

33 35,5 1,919<br />

34 71,3 2,008<br />

35 138 1,935<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dabar pateiksime algoritmą, kurį gauname dinaminio<br />

programavimo metodu. Ir šis algoritmas naudoja rekursinę<br />

formulę:<br />

C k n = C k−1<br />

n−1 + C k n−1,<br />

kuri ir yra binominio koeficiento Belmano sąlyga.<br />

Skaičiuoti pradedame nuo mažiausio koeficiento C0 0 ir didiname<br />

parametro n reikšmę. Pagalbinių koeficientų reikšmes saugome<br />

matricoje H , turinčioje (n + 1) eilutę ir (k + 1) stulpelį.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dinaminio programavimo binominių koeficientų<br />

algoritmas<br />

int BinKoef2 (int n, int k)<br />

begin<br />

(1) for ( i=0; i


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Dinaminio programavimo algoritmo sudėtingumas<br />

Naujuoju algoritmu binominį koeficientą apskaičiuojame, atlikę<br />

(n − k)(k + 1) + (k+2)(k+1)<br />

2<br />

veiksmų.<br />

Šis skaičius didžiausias, kai k = n 2<br />

(prisiminkite lygybę<br />

Cn k = Cn n−k ).<br />

Taigi dinaminio programavimo algoritmo sudėtingumo funkcija<br />

yra kvadratinė T(n) = 3n 2 /8 + O(n).<br />

Kokios yra dinaminio programavimo algoritmo atminties<br />

sąnaudos? Ar galima jas sumažinti?<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Euristiniai algoritmai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Daugeliui uždavinių variantų perrinkimo algoritmų<br />

sudėtingumas aprašomas nepolinomine (pvz., eksponentine)<br />

funkcija. Todėl dažnai visus variantus perrinkti neįmanoma net<br />

ir su šiuolaikiniais superkompiuteriais.<br />

Kai nėra žinomas pakankamai greitas algoritmas, randantis<br />

tikslųjį (optimalųjį) uždavinio sprendinį, naudojami algoritmai,<br />

gaunami atsisakius sprendinio tikslumo reikalavimo.<br />

Algoritmas vadinamas euristiniu arba tiesiog euristika (angl.<br />

heuristic), jei jis pakankamai greitai randa priimtiną, bet<br />

nebūtinai tikslųjį (optimalųjį) uždavinio sprendinį.<br />

Euristikos dažniausiai būna polinominio sudėtingumo. Tai<br />

pasiekiama patikrinant ne visus, o tik perspektyviuosius<br />

(euristikos apibrėžimo prasme) variantus.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Taip sudarytas algoritmas laikomas euristiniu, net jei jis<br />

praktiškai grąžina tiksliuosius sprendinius, bet nėra<br />

formalaus įrodymo, kad taip bus visada (t.y. bet kokiems<br />

uždavinio duomenims).<br />

Pavyzdžiui, sprendžiant paieškos ar optimizacijos<br />

uždavinius, populiarūs algoritmai gaunami naudojant<br />

godžiąją (angl. greedy) strategiją.<br />

Daugeliui uždavinių gaunami pagal šią strategiją taip<br />

vadinami godieji algoritmai yra tik euristikos, t.y.<br />

bendruoju atveju negarantuoja tikslaus (optimalaus)<br />

sprendinio radimo.<br />

Tačiau egzistuoja svarbus taikomieji uždaviniai, kurių<br />

sprendimui sukurti godieji algoritmai yra tikslieji<br />

algoritmai, t.y. jie randa tiksliuosius atitinkamų uždavinių<br />

sprendinius ir tai yra formaliai įrodyta.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Godžiųjų algoritmų sudarymo bendroji schema<br />

Uždavinio sprendinio paiešką išskaidome į n žingsnių.<br />

Kiekvienu žingsniu renkamės iš nedidelio baigtinio<br />

skaičiaus variantų m.<br />

Godieji algoritmai (angl. greedy) gaunami renkantis<br />

lokaliai geriausią variantą duotojo žingsnio metu (t.y.<br />

tą iš m, kuris šiuo žingsniu atneša didžiausią pelną).<br />

Aišku, kad tokia lokali pasirinkimo strategija nebūtinai<br />

yra optimali viso uždavinio sprendimo atžvilgiu. Bet jos<br />

realizavimo sąnaudos yra labai mažos: lokalaus pasirinkimo<br />

sudėtingumas – O(m), o viso godžiojo algoritmo<br />

sudėtingumas – tik O(nm) veiksmų.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Diskretusis kuprinės užpildymo uždavinys<br />

(angl. 0 − 1 knapsack problem)<br />

Tarkime, kad turime n daiktų, kurių tūriai yra v 1 , v 2 , . . . , v n , o<br />

kaina p 1 , p 2 , . . . , p n . Reikia rasti tokį daiktų rinkinį, kuris tilptų<br />

į V tūrio kuprinę, o daiktų vertė būtų didžiausia.<br />

Sprendžiame optimizavimo uždavinį:<br />

max (x 1p 1 + x 2 p 2 + . . . + x n p n ),<br />

(x 1 ,...,x n)∈D<br />

D = {x 1 v 1 + x 2 v 2 + . . . + x n v n ≤ V , x j ∈ {0, 1}}.<br />

Tiesioginio pilno perrinkimo algoritmo (angl. brute-force<br />

search) sudėtingumas - O(2 n ).<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Diskretusis kuprinės uždavinys. Godieji algoritmai.<br />

Pirmiausia pagal bendrąją godžiųjų algoritmų sudarymo<br />

schemą išskaidome sprendinio paiešką į n žingsnių:<br />

kiekviename žingsnyje dedame į kuprinę po vieną daiktą<br />

(jis ten ir lieka iki algoritmo pabaigos).<br />

Tada i-ame žingsnyje turime rinktis iš tų likusių n − i<br />

daiktų, kurie telpa į dar neužpildytą kuprinės tūrį.<br />

Lokaliai geriausio varianto (t.y. daikto) pasirinkimą galima<br />

apibrėžti 3 būdais:<br />

1 pagal mažiausią tūrį - v j ,<br />

2 pagal didžiausią kainą - p j ,<br />

3 pagal didžiausią santykinę vertę - p j<br />

v j<br />

.<br />

Visi 3 būdai duoda leistinus sprendinius, tačiau nei vienas<br />

negarantuoja tikslaus (optimalaus) sprendinio. Kuris būdas<br />

duos geresnį sprendinį priklauso nuo uždavinio duomenų.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Panagrinėkime pavyzdį (kuprinės tūris V = 100):<br />

Godieji sprendiniai pagal Optimalus<br />

p i<br />

i v i p i kainą tūrį s. vertę sprendinys<br />

v i<br />

1 100 40 0.4 1 0 0 0<br />

2 50 35 0.7 0 0 1 1<br />

3 45 18 0.4 0 1 0 1<br />

4 20 4 0.2 0 1 1 0<br />

5 10 10 1.0 0 1 1 0<br />

6 5 2 0.4 0 1 1 1<br />

sprendinio tūris 100 80 85 100<br />

sprendinio vertė 40 34 51 55<br />

Taigi diskrečiajam kuprinės užpildymo uždaviniui sudaryti<br />

godieji algoritmai yra tik euristikos.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Sudarykite godaus algoritmo pseudo-kodą ir raskite jo<br />

sudėtingumą.<br />

Kaip kitaip galima rasti optimalų uždavinio sprendinį?<br />

Tegu A(n, V ) yra maksimali vertė daiktų, išrinktų iš n, tokių,<br />

kad jų bendras tūris neviršija V . Tada A(n, V ) gali būti rastas<br />

pagal rekursinį sąryšį:<br />

⎧<br />

0, jei n = 0,<br />

⎪⎨ 0, jei V = 0,<br />

A(n, V ) =<br />

A(n − 1, V ), jei v n > V ,<br />

⎪⎩<br />

max {A(n − 1, V ), p n + A(n − 1, V − v n )} , jei v n ≤ V .<br />

Sudarykite dinaminio programavimo metodo algoritmą ir<br />

įvertinkite jo sudėtingumą.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Tolydusis (angl. fractional) kuprinės uždavinys<br />

Užduoties sąlyga tokia pati, kaip diskrečiajame uždavinyje,<br />

tik dabar daiktai yra dalūs ir galime imti jų dalį, t.y.<br />

0 ≤ x i ≤ 1, i = 1, 2, ..., n.<br />

Pavyzdžiui, tai gali būti aukso plytelės (diskretusis užd.) ir<br />

aukso smėlis (tolydusis), supakuotas ir birusis cukrus.<br />

Tada naudojame tokį godųjį algoritmą: surūšiuojame<br />

daiktus pagal jų santykines vertes ir kiekviename žingsnyje<br />

imame į kuprinę patį vertingiausią likusį daiktą (visą arba<br />

dalį, kiek telpa).<br />

Nagrinėkime daiktų rinkinį, pateiktą ankstesniame pavyzdyje.<br />

Tada į kuprinę nuosekliai įdedame visą 5-ą daiktą (jo tūris – 10,<br />

o vertė – 10), visą 2-ą daiktą (jo tūris – 50, vertė – 35) ir 40<br />

tūrio vienetų 1-ojo daikto (tūris – 40, vertė – 40 ∗ 0.4). Taigi<br />

toks krovinys užpildo visą kuprinę, o jo vertė – 61.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Godžiųjų algoritmų optimalumas<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Kada godžiuoju algoritmu visada randame optimalųjį (tikslųjį)<br />

uždavinio sprendinį? Turi būti patenkintos dvi sąlygos:<br />

1. (angl. optimal substructure property). Optimalų sprendinį<br />

galime apskaičiuoti išskaidę uždavinį į mažesnių (tokių pačių)<br />

užduočių seką ir suradę optimalius jų sprendinius.<br />

Tai yra dinaminio programavimo metodo Belmano sąlyga. Ji yra<br />

būtina, bet jos nepakanka, kaip matėme diskrečiojo kuprinės<br />

uždavinio atveju, kai ši sąlyga patenkinta, bet godieji algoritmai yra<br />

tik euristikos.<br />

Godžiajame algoritme visada renkamės tik lokaliai vertingiausią<br />

sprendinį, o dinaminio programavimo metode įvertiname tokio<br />

pasirinkimo pasekmes visiems tolesniems variantams.<br />

2. (angl. greedy-choice property). Atliekant lokaliai geriausią<br />

(godųjį) pasirinkimą kiekviename žingsnyje išlieka galimybė<br />

gauti viso uždavinio optimalųjį sprendinį.<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

Teorema. Godžiuoju algoritmu randame optimalųjį tolydaus<br />

kuprinės užpildymo uždavinio sprendinį.<br />

Įrodymas. Jei į kuprinę telpa tik vertingiausias daiktas ar jo<br />

<strong>dalis</strong>, tai godžiojo algoritmo optimalumas yra akivaizdus.<br />

Nagrinėkime atvejį, kai v 1 < V . Tada godžiuoju algoritmu<br />

pirmajame žingsnyje pasirinkome visą kiekį santykinai<br />

vertingiausio daikto - v 1 .<br />

Tarkime, kad egzistuoja optimalus rinkinys, kuriame šio<br />

produkto yra mažiau: w 1 < v 1 . Pažymėkime optimalaus<br />

rinkinio vertę P O .<br />

Tada, išėmę iš optimaliai užpildytos kuprinės (v 1 − w 1 )<br />

mažiausiai vertingo k-ojo produkto (k ≠ 1) ir įdėję tokį patį<br />

kiekį pirmojo produkto, gausime naują rinkinį, kurio vertė lygi<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai


Algoritmų sudarymo principai ir metodai<br />

Variantų perrinkimas ir rekursijos metodas<br />

Skaldyk ir valdyk metodas<br />

Šakų ir rėžių metodas<br />

Dinaminio programavimo metodas<br />

Euristikos ir godieji algorimai<br />

a) P O + (v 1 − w 1 )(s 1 − s k ) > P O , jei s 1 > s k (s i = p i<br />

v i<br />

), t.y.<br />

didesnė negu optimalaus rinkinio! Gavome prieštaravimą!<br />

b) P O , jei s 1 = s k , t.y. gavome kitą optimalų rinkinį (jų gali<br />

būti ne vienas, kai dalies produktų santykinės vertės sutampa),<br />

kuriame yra w 1 + (v 1 − w 1 ) = v 1 pirmojo produkto.<br />

Taigi godžiosios strategijos taikymas pirmajame žingsnyje (v 1<br />

įdėjimas) leidžia rasti optimalų rinkinį.<br />

Po pirmojo žingsnio vėl gavome kuprinės užpildymo<br />

vertingiausiais produktais uždavinį, tik sumažėjo kuprinės tūris<br />

(V − v 1 ) ir liko trumpesnis daiktų sąrašas. Remdamiesi<br />

matematinės indukcijos metodu, tvirtiname, kad godžiuoju<br />

algoritmu randame optimalų sprendinį. ✷<br />

doc. dr. Vadimas Starikovičius<br />

Algoritmų analizės specialieji skyriai

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!