Sunteți pe pagina 1din 32

Optim.

intro
Rezolvarea problemelor de optimizare prin metode numerice

Pe scurt: vi se oferă o singură funcție f care depinde de una sau mai multe variabile independente.
Doriți să găsiți valoarea acelor variabile in care f are o valoare maximă sau minimă.
Puteți apoi să calculați care este valoarea lui f realizat la maxim sau minim.
Operatiile de maximizare și minimizare sunt în mod trivial legate între ele, deoarece valoarea
minima a funcției f poate la fel de bine sa fie maximul functiei -f.
Astfel metodele de calcul sunt aceleasi, indiferent daca se cauta valoarea maxima sau minima. Ceea
ce intereseaza in primul rand este viteza cu care se obtine solutia (numarul de calcule), cat de ieftin
este programul, și nu în ultimul rand, cata memorie foloseste.
Deseori efortul de calcul este dominat de costul evaluării functiei f (și, de asemenea, probabil,
derivatele sale parțiale cu privire la toate variabilele, dacă algoritmul ales le solicită). În astfel de
cazuri dezideratele decizia folosirii unei metode sau a alteia consta intr-o decizie simpla: evaluează
f de cât mai puține ori.
Un extrem (punct maxim sau minim) poate fi fie global (cu adevărat cea mai mare sau cea mai mică
valoare a funcției) sau locală (cea mai mare sau cea mai mică într-un interval finit al domeniului de
definitie a functiei). (Vezi Figura Optim.0.1.)

Găsirea unui extrem global este, în general, o problemă foarte dificilă. Două standard
euristicile sunt utilizate pe scară largă:
(i) găsesc extrema locală începând de la diferite variații ale valorilor de pornire ale variabilelor
independente (probabil alese aproape aleatoriu, ca în §7.7), apoi alegeți dintre acestea pe cele mai
extreme (dacă nu sunt toate la fel); sau
(ii) perturba un extrem local, făcând un pas de amplitudine fină de la acesta și apoi verificand dacă
rutina ta te întoarce într-un punct mai bun sau „mereu” la același punct.

Relativ recent, așa-numitele „metode de recoacere simulate” (§Optim.9) au


a demonstrat succese importante in cazul unei mari varietati de probleme de cautare a extremului
global.Titlul subcapitolului nostru, ar putea fi la fel de bine tot unul de optimizare, numele obișnuit
pentru acest domeniu foarte mare de cercetare numerică.

Importanța atribuită, diverse sarcini în acest domeniu depind puternic de interesele speciale ale
acestora. Economiștii, și unii ingineri, sunt deosebit de preocupați de optimizarea in cazul in care
apar si conditii de constrângere. In aceste cazuri există limitări a priori asupra valorilor permise ale
variabilelor independente. De exemplu, pretul unui m3 de pamant excavat, al unei lucrari de
constructie, etc. Trebuie fi un număr non-negativ. O zonă restrânsă deosebit de bine dezvoltată in
optimizare, este programare liniară, unde funcția trebuie optimizată și constrângerile se întâmplă să
fie funcții liniare ale variabilelor independente.
Secțiunea Optim.8, care este altfel oarecum deconectat de restul materialului se poate numi
„algoritm simplex” pentru probleme de programare liniară.

O altă secțiune, §Optim.9, se află, de asemenea, în afara domeniului obisnuit al optimizarii, dar
pentru un alt motiv: așa-numitele „metode de imbatranire, sau recoacere” sunt relativ noi, deci nu
știm încă unde se vor încadra în cele din urmă în randul algoritmilor de optimizare. Totuși, aceste
metode au rezolvat unele probleme considerate anterior insolubile; ele abordează direct problema
găsirii extremului global în prezența unui număr mare de extrema locale nedorite.

Celelalte secțiuni din acest capitol constituie o selecție dintre cei mai bine cotati
algoritmi în minimizarea fara restricții. (Pentru definire, vom descoperi acum problema de
optimizare ca fiind cea de minimizare.) Aceste secțiuni sunt conectate, cu cele ulterioare dar preiau
functii si din cele anterioare. Dacă sunteți doar în căutarea algoritmul „perfect” pentru a rezolva
problema dvs. particulară, puteți simți asta se prezinta mai multe decât doriți să știți. Din păcate, nu
există niciun algoritm perfect de optimizare. Acesta este un caz în care capitolul prezent va
recomanda să încercați mai mult decât o metodă comparativă. Alegerea dvs. inițială de metodă se
poate baza din următoarele considerente:

-Trebuie să alegeți între metodele care au nevoie doar de evaluări pentru funcția de minimizat și
metodele care necesită, de asemenea, evaluări ale derivatelor acestei funcții. În cazul
multidimensional, aceste derivate sunt gradientul, o cantitate vectorială.
Algoritmii care folosesc derivatele sunt ceva mai eficiente decât cei care folosesc doar funcția, dar
nu întotdeauna suficient de eficiente pentru a compensa calculele suplimentare ale
derivatelor. Putem construi cu ușurință exemple care favorizează o abordare sau alta. Cu toate
acestea, dacă puteți calcula derivatele, încercati să le folositi.
- Pentru minimizarea unidimensională (minimizați o funcție a unei variabile) fără
calculul derivatei, încearca metoda de minim descrisa în §Optim.1, apoi foloseste
metoda lui Brent așa cum este descris în §Optim.2. Dacă funcția ta are derivata de
ordinul doi (sau cea de ordinul unu) discontinua, atunci functia de aproximare
parabolica folosita la interpolarea cu metoda Brent nu aduce nici un avantaj si utilizarea
formei mai simplă de căutare a minimului, cu secțiunia de aur, asa cum este descrisa în
§Optim.1 devine cea mai avantajoasa metoda.
- Pentru minimizarea unidimensională cu folosirea derivatei, metoda din §Optim.3
furnizează o variantă a metodei Brent care utilizează în mod limitat datele primei derivate. Se evita
alternativa de utilizare a polinoamelor de ordin mare, deoarece, de regulă, îmbunătățirea
convergenței spre solutie se produce foarte lent. De asemenea, minimul gasit nu compenseaza
tendinta polinoamelor de ordin inalt de a conduce la erori de interpolare în stadii incipiente, în
special pentru funcțiile care pot avea caracteristici clare, „exponențiale”.

Revenim acum la cazul multidimensional, atât cu, cât și fără calculul de primele derivate.
• Trebuie să alegeți între metodele care necesită N2 operatii și cele care necesită numai ordinul N,
unde N este numărul de dimensiuni.
Pentru valori moderate de operatii N și dimensiuni rezonabile ale memoriei, aceasta nu este o
constrângere serioasă. Va exista, totuși, aplicația ocazională unde stocarea poate fi critică.
• Redăm în §Optim.4 o metodă simplă de coborâre, uneori neglijată apartinand lui Nelder și Mead.
(Această utilizare a cuvântului „simplex” nu trebuie să fie confundat cu metoda simplex de
programare liniară.) Această metodă consta in deplasarea într-o manieră simplă, spre minimul
functiei. Minim care se gaseste intr-un domeniu definit. Aceasta metoda de cautare a minimului
poate fi extrem de lenta, dar de cele mai multe ori se dovedeste si extrem de robusta. Nu trebuie
trecut cu vederea faptul ca implementarea ei se bazeaza pe un cod foarte concis si complet
autonom, fiind un program de optimizare ce nu depaseste in general 100 de linii de program!
Aceasta metoda este cea mai utilă atunci când calculul de minimizare este doar o prima etapa a unei
probleme de optimizare generala.Cerința de stocare este de
ordinea N2 și calculele derivatelor nu sunt necesare.
• Secțiunea Optim.5 tratează metode bazate pe direcțiule posibile de cautare a optimului, dintre care
metoda Powell este cea mai abordata. Acestea sunt metodele de alegere atunci când nu se pot
determina cu ușurinta derivatele, metoda nu necesita calculul lor. Dar deși derivatele nu sunt
necesare, metoda necesită apelarea unei functii de minimizare unidimensională, care de regula este
metoda Brent (vezi mai sus). Numarul de operatii necesare este de ordinul N2.

Există două familii majore de algoritmi destinati minimizarii multidimensionale care impun
calculul primelor derivate. Ambele familii necesită o abordare separata pe fiecare dimensiune a
domeniului bazanduse pe diverse tipuri de sub-algoritmi de minimizare, care pot sa se bazeze sau
nu pe derivatele functiei de optimizat. In functie de problema abordata se pot gasi mai multe
alternative disponibile:
• Prima familie intră sub denumirea de metode de tip gradient conjugat, după cum este denumit in
algoritmul Fletcher-Reeves și strâns legat in algoritmul superior Polak-Ribiere. Metodele de tip
gradient conjugate necesită un numar de operatii aritmetice de cateva ori mai mare ca N, necesită
calculul derivatelor și sub-minimizare unidimensională. Apelați la §Optim.6 pentru discuții
detaliate și implementare.
• A doua familie intră sub denumirile cvasi-Newton sau metode cu metrică variabilă, așa cum este
tipizat de algoritmul Davidon-Fletcher-Powell (DFP) (uneori denumit doar Fletcher-Powell) sau
strâns legate Algoritmul Broyden-Fletcher-Goldfarb-Shanno (BFGS). Aceste metode necesită spatii
de stocare mai mari si un numar de operatii aritmetice de ordinul N2, necesită calculele derivatelor.
Detaliile sunt prezentate în §Optim.7.

Bibliografie:

Dennis, J.E., and Schnabel, R.B. 1983, Numerical Methods for Unconstrained Optimization and
Nonlinear Equations (Englewood Cliffs, NJ: Prentice-Hall).
Polak, E. 1971, Computational Methods in Optimization (New York: Academic Press).
Gill, P.E., Murray, W., and Wright, M.H. 1981, Practical Optimization (New York: Academic Press).
Acton, F.S. 1970, Numerical Methods That Work; 1990, corrected edition (Washington: Mathematical
Association of America), Chapter 17.
Jacobs, D.A.H. (ed.) 1977, The State of the Art in Numerical Analysis (London: Academic
Press), Chapter III.1.
Brent, R.P. 1973, Algorithms for Minimization without Derivatives (Englewood Cliffs, NJ: Prentice-
Hall).
Dahlquist, G., and Bjorck, A. 1974, Numerical Methods (Englewood Cliffs, NJ: Prentice-Hall),Chapter Optim.
Optim.1 Metoda sectiunii de aur pentru o singura directie

Amintiți-vă cum determinam rădăcinile funcțiilor folosind metoda de injumatatire a intervalului,


(bisectiei) in cazul functiei de o singura variabila,(§9.1):
-Se presupune că rădăcina se gaseste într-un interval (a, b). Se verifica daca capetele intervalului
sunt radacini, daca nu, se evaluează funcția într-un punct intermediar x și obține o nouă valoare a
functiei. Se verifica daca radacina se gaseste in subintervalul (a,x) sau in (x,b) si se inlatura
subintervalul care nu contine radacina. Procesul continuă până la obtinerea unui interval mai mic
decat eroarea cu care se doreste determinarea radacinii. Este optim să alegeți x care să fie mijlocul
intervalului (a, b) astfel încât sa fim siguri ca vom determina radacina cautata dintr-un numar
suficient de pasi. Daca folosim metoda coardei, atunci scăderea lungimii intervalului este
maximizată astfel incit in multe cazuri sa se reduca numarul de iteratii pana la determinarea
solutiei.
In cazul cautarii unui minim, acesta exista in intervalul cautat doar daca pentru trei puncte, a, b, c
cu (a<b<c), f(a)>f(b)<f(c), deci f(b) trebuie sa fie mai mica decat valoarea functiei la capetele
intervalului. Astfel, daca functia este continua, atunci va avea un minim (sau cel putin un minim) in
intervalul (a,c).
Analog metodei bisectiei, se alege un nou punct x, fie între a și b fie între b și c. Să presupunem,
pentru a fi specific, că facem alegerea intre b si c, b<x<c. Atunci calculand valoarea f (x).
Dacă f (b) <f (x), atunci noua tripletă de punctaj este (a, b, x);
Dacă f (b)> f (x), atunci noul triplet de bracketing este (b, x, c).
În toate cazurile punctul de mijloc al noii triplete este abscisa a cărei ordine este cel mai bun minim
realizat până acum. Vezi Figura Optim.1.1.
Continuăm procesul de micsorare a intervalului până ce distanța dintre cele două puncte exterioare
ale tripletei devine mai mica decat toleranta de calcul a minimului.

Figura Optim.1.1. Intervalele succesive de cautare a minimului. Minimul este cautat inițial între punctele (1,3,2). Apoi, funcția este
evaluată in 4, si se constata ca trebuie înlocuit 2, noul domeniu de cautare devine (1,3,4); apoi se genereaza punctul 5 in interiorul
intervalului (1,3,4), cum valoarea functiei in 5, f(5) < f(1), f(5) > f(3) si f(5) < f(4) iar f(1)>f(4) rezulta ca se înlocuiește punctul 1 si noul
interval de cautare devine (5,3,4); In noul interval se genereaza punctul 6, pentru care, f(6)>f(3), f(5)>f(3) si f(6) < f(4) rezulta ca se va
elimina punctul 4 si noul interval va fi (5,3,6). Deci minimul se gaseste in intervalul (5,3,6). Se genereaza un nou punct, 7 etc. Pana in
momentul in care intervalul devine mai mic decit abaterea cu care se doreste solutia.
Cât de mica poate fi abaterea „eps” ? Pentru un minim situat la o abscisa b, dumneavoastră s-ar
putea să cred că un naiv va fi capabil să-l încadrați într-un interval cât mai mic
(1 - eps) b <b <(1 + eps) b, unde eps este precizia de exprimare a unui numar zecimal pe
calculatorul cu care lucrati, poate fi 3×10−8 (pentru cazul variabilelor declarate float) sau 10-15
(pentru cele declarate double).
Atentie insa, in general,forma funcției dvs. f (x) lângă b va fi dată de teorema lui Taylor

In ecuatie, al doilea termen va fi neglijabil în comparație cu primul (adică va fi un factor


mai mic și va acționa la fel ca zero atunci când se adaugă) oricând

Partea dreapta se scrie in acest mod deoarece pentru majoritatea funcțiilor, rădăcina pătrată finală
este un număr de ordinul unitatii. Prin urmare, de regulă, aceasta nu poate influenta un interval cu o
lățime mai mică de √ε ori din valoarea medie a intervalului, deci o latime de numai aproximativ
10−4 (in precizie float) sau 3 × 10−8 (in double). Cunoașterea acestui fapt va salva o mulțime de
bisecții inutile!
Rutinele dezvoltate pentru găsirea minimă in acest capitol vor solicita deseori un utilizator furnizat
argumentul tol și întoarceți-vă cu o abscisă a cărei precizie fracțională este de aproximativ ± tol
(intervalul de oprire va avea dimensiunea fracțională aproximativ 2 × tol). Doar dacă ai un mai bun
de estimare pentru pentru partea dreaptă a ecuației (Optim.1.2), ar trebui să setați tol egal cu nu cu
mult mai puțin decât rădăcina pătrată a preciziei punctului flotant al calculatorului pe care il
folositi, valori mai mici nu vă vor aduce nici un avantaj. Rămâne să decidem asupra unei strategii
pentru alegerea noului punct x, din intervalul dat (a, b, c).
Să presupunem că b este o fracție w dintre a și c, deci,

De asemenea, să presupunem că următorul nostru punct de încercare x este o fracție suplimentară z


dincolo de b,

Apoi, următorul segment de interval va fi fie de lungime w + z în raport cu intervalul curent sau
altul cu lungimea 1 - w. Dacă vrem să minimalizăm cea mai proastă posibilitate, atunci
vom alege z astfel incat să le facem egale cele doua conditii și anume

Se presupune că noul punct este punctul simetric la b în intervalul inițial, deci cum | b - a | este egal
cu | x - c |. Aceasta implică faptul că punctul x se gaseste în segmentul mai mare
din cele două segmente (z este pozitivă numai dacă w <1/2).
Dar unde în segmentul mai mare? Sa vedem din care segment provine w ?
Probabil ca va trebui sa stim ce s-a intamplat in etapa anterioara, in care s-a stabilit w ca fiind
alegerea optima. Prin urmare, dacă z este ales a fi optim, atunci a fost w înaintea lui intr-o etapa
anterioara. Această asemănare la scară presupune că x ar trebui să fie aceeași fracție a drumului de
la b la c (dacă acesta este segmentul mai mare) exact cum a fost fost b de la a la c, cu alte cuvinte,
Ecuațiile (Optim.1.5) și (Optim.1.6) dau ecuația patratică


Cu alte cuvinte, intervalul optim de cautare (a, b, c) are pentru punctul său intermediar b o
distanță fracțională 0,38197 de la un capăt (să spunem, a) și 0,61803 de celălalt capăt (să zicem, b).
Aceste fracții sunt cele ale așa-numitei medii de aur sau a secțiunii de aur, ale căror proprietăți
presupuse estetice se întorc din vechii pitagorei. Aceasta metoda optimă de minimizare a funcțiilor,
analogul metodei de bisecare pentru găsirea radacinilor, se numește astfel căutarea secțiunii de aur,
rezumată după cum urmează:
Pentru fiecare etapăde calcul, pentru fiecare triplă de puncte, următorul punct care va fi generat se
gaseste la valoarea fracționala de 0,38197 în cel mai mare subinterval, măsurarea distantei se face
din punctul central al tripletei.
Pentru (a,b,c) atunci cand (a,b) > (b,c), noul punct generat va fi in intervalul (a,b) la distanta (a + (1-
w)LAB) sau b-wLAB.
Dacă începeți cu un triplet de cautare ale cărui segmentele nu se află în raporturile de aur, procedura
de alegere a punctelor succesive fata de punctul mediu,alegerea noului punct dupa legea sectiunii de
aur in segmentul mai mare va conduce la rapoarte proprii, autoreplicante.
Căutarea secțiunii de aur garantează că fiecare nouă funcție de evaluare va genera (după ce au fost
obținute raporturi de auto-replicare), intervale minimul la un interval de doar 0,61803 ori mai mare
decât dimensiunea intervalului precedent. Acest lucru este comparabil cu alegerea mijlocului
intervalului din metoda injumatatirii intervalului.
In acest caz, convergența este liniară, ceea ce înseamnă că succesiv cifre semnificative sunt
câștigate liniar cu evaluări suplimentare ale funcțiilor.
Metoda următoare va oferi o dezvoltare mai rapida a cautarii minimului.

Functia de determinare a minimului utilizand sectiunea de aur.

//#define _NR_UTILS_H_
#define GOLD 1.618034
#define GLIMIT 100.0 // nr. iteratii in golden - mnbreak(...)
#define TINY 1.0e-25 // cel mai mic numar
#define ITMAX 200 // nr max iteratii in Powell
#define TOL 2.0e-4
#define SHFT3(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
#define SHFT2(a,b,c) (a)=(b);(b)=(c);
#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); // pentru mn_brak(..)
#define R 0.61803399 // rata golden
#define C (1.0-R)

void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb, double
*fc,double (*func)(double))
{

double TINYY= 1.0e-20;


double ulim,u,r,q,fu,dum;

*fa=(*func)(*ax);
*fb=(*func)(*bx);
if (*fb > *fa) {// schimba pozitiile lui a si b pentru a inainta de la a la b
SHFT(dum,*ax,*bx,dum)
SHFT(dum,*fb,*fa,dum)
}
*cx=(*bx)+GOLD*(*bx-*ax); // prima pozitie a lui c
*fc=(*func)(*cx);
while (*fb > *fc) { // ruleaza pina cand se ajunge la minimizare
r=(*bx-*ax)*(*fb-*fc);
q=(*bx-*cx)*(*fb-*fa);
// calculeaza u prin aproximare parabolica intre a,b,c TINY previne impartirea la
zero
u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/(2.0*SIGN(FMAX(fabs(q-r),TINY),q-
r));
ulim=(*bx)+GLIMIT*(*cx-*bx);
// Testeaza diversele cazuri
if ((*bx-u)*(u-*cx) > 0.0) { // u determinat prin aprox. parabolica
este intre b si c se incearca
fu=(*func)(u);
if (fu < *fc) { // s-a obtinut minimul intre b si c
*ax=(*bx);
*bx=u;
*fa=(*fb);
*fb=fu;
return;
} else if (fu > *fb) { // s-a obtinut minimul intre ab si u
*cx=u;
*fc=fu;
return;
}
u=(*cx)+GOLD*(*cx-*bx); // nu se utiliz. aprox. parab. se
determina u cu regula de aur
fu=(*func)(u);
} else if ((*cx-u)*(u-ulim) > 0.0) { // pasul parabolic intre
c si limita mai apropiata
fu=(*func)(u);
if (fu < *fc) {
SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
SHFT(*fb,*fc,fu,(*func)(u))
}
} else if ((u-ulim)*(ulim-*cx) >= 0.0) {
u=ulim;// valoarea maxima posibila pentru pasul parabolic.
fu=(*func)(u);
} else {
u=(*cx)+GOLD*(*cx-*bx);
fu=(*func)(u);
}
SHFT(*ax,*bx,*cx,u) //Elimina punctul vechi si continua.
SHFT(*fa,*fb,*fc,fu)
}
} // end funcie mnbrak

(Din cauza schimbarilor implicate în mutarea a trei sau patru puncte și a valorilor funcției in aceste
puncte, programul de mai sus ajunge să pară foarte ciudat si înșelător. Acest lucru este valabil și
pentru alte câteva programe din acest capitol. Ideile de bază, cu toate acestea, sunt destul de
simple.)
/*--------------------------------------------------------------------------------*/
/*Fiind data o funcție f, și trei puncte de cautare AX, BX, CX (cu BX > AX si BX < CX) */
/* si (f(BX) < A(X) si f(BX) < f(CX)) această functie efectueaza o cautare dupa */
/* sectiunea de aur pentru determinarea minimului f(X), izolarea minimului se face cu */
/* precizia TOL iar abscisa va fi valoarea intoarsa xmin, valoarea minima este returnata */
/*--------------------------------------------------------------------------------*/
double golden(double ax, double bx, double cx, double (*f)(double), double tol,
double *xmin)
{
double f1,f2,x0,x1,x2,x3;
x0=ax; // pentru orice apelare se folosesc punctele
x3=cx; // puncte, x0,x1,x2,x3
if (fabs(cx-bx) > fabs(bx-ax)) { // segmentul minim x0,x1
x1=bx;
x2=bx+C*(cx-bx); // determina noul punct ca fiind al treilea, x2
} else {
x2=bx;
x1=bx-C*(bx-ax);
}
f1=(*f)(x1); // evaluarea functiei initiale in capetele originale x0,x3
f2=(*f)(x2);
while (fabs(x3-x0) > tol*(fabs(x1)+fabs(x2))) {
if (f2 < f1) { // o singura valoare posibila
SHFT3(x0,x1,x2,R*x1+C*x3) // limitarea domeniului pentru ea
SHFT2(f1,f2,(*f)(x2)) // primul rezultat
} else { // cel de-al doile rezultat
SHFT3(x3,x2,x1,R*x2+C*x0)
SHFT2(f2,f1,(*f)(x1)) // noua evaluare a functiei
} // end if
}// end while -> s-au terminat verificarile
if (f1 < f2) { // Am terminat, intoarce cele mai bune rezultate
*xmin=x1; // valoarea abscisei pentru minim
return f1; // valoarea minima a functiei
} else {
*xmin=x2;
return f2;
}
}

Optim.2 Interpolarea parabolică și metoda lui Brent într-o singură dimensiune

Am constatat deja ca putem folosi metoda interpolării parabolice din secțiunea anterioară a rutinei
mnbrak, dar acum este timpul ca algoritmul să fie dezvoltat. Căutarea secțiunii de aur este
proiectată pentru a gestiona, de fapt, cel mai rău caz posibil, minimizarea funcției, cu minimul
necooperant ( preluat și încolțit ca un iepure speriat). Dar de ce să-ți asumi cel mai rău? Dacă
funcția este considerata parabolică in apropierea minimului - cu siguranță cazul generic pentru
funcții suficient de netede - atunci parabola care trece prin orice trei puncte ar trebui să ne ducă într-
un singur salt la minim, sau cel puțin foarte aproape de acesta (a se vedea figura Optim.2.1). Astfel
vom găsi mai degrabă o abscisă decât o ordonată, procedura se numește tehnic interpolare
parabolică inversa.
Formula pentru abscisa x care este minimul unei parabole prin trei puncte f(a), f(b) si f(c) este:
după cum puteți deriva cu ușurință.
Această formulă nu reușește dacă cele trei puncte sunt colineare, caz în care numitorul este zero
(minimul parabolei este infinit de departe

Figura Optim.2.1. Convergența spre minimum prin interpolare parabolică inversă. O parabolă (linie punctată) este
trasata prin cele trei puncte originale 1,2,3 de pe funcția dată (linie solidă). Funcția este evaluată
la minimul parabolei, punctul 4, care înlocuiește punctul 3. O nouă parabolă (linie punctată) este desenată prin
puncte 1,4,2. Minima acestei parabole este in punctul 5, ceea ce este aproape de minimul funcției

Rețineți, totuși, că (Optim.2.1) este la fel de fericit sărind la un maxim parabolic la minimum. Nu
este posibilă nicio schemă de minimizare de care depinde exclusiv (Optim.2.1) a reuși în practică.
Sarcina exactă este de a inventa o schemă care se bazează pe o tehnică sigură, dar lentă, ca și
căutarea secțiunii de aur, când funcția nu este cooperantă, dar aceasta comută over to (Optim.2.1)
când funcția permite. Sarcina este inutilă pentru câțiva motive, inclusiv următoarele:
(i) menajele necesare pentru a evita funcțiile inutile evaluările în comutarea între cele două
metode pot fi complicate.
(ii) Atent trebuie acordată atenție „jocului final”, unde funcția este evaluată foarte aproape de
limita de ecuație (Optim.1.2).
(iii) Schema de detectare a funcția de cooperare versus non-cooperativă trebuie să fie foarte
robustă.

Metoda Brent [1] depinde de sarcină în toate particularitățile. În orice etapă particulară, urmează
șase puncte funcționale (nu neapărat toate distincte), a, b, u, v,w și x, definite după cum urmează:
minimul este între paranteză între a și b; x este punct cu cea mai mică valoare a funcției găsite până
acum (sau cea mai recentă în caz de egalitate); w este punctul cu a doua valoare a funcției; v este
precedentul valoarea lui w; u este punctul în care funcția a fost evaluată cel mai recent. De
asemenea apariția în algoritm este punctul xm, punctul mediu dintre a și b; in orice caz, funcția nu
este evaluată acolo.
Puteți citi codul de mai jos pentru a înțelege organizarea logică a metodei.
Menționarea câtorva principii generale aici poate fi de folos: Parabolic se încearcă interpolarea,
încadrându-se prin punctele x, v și w. Pentru a fi acceptabil, etapa parabolică trebuie
(i) să se încadreze în intervalul de delimitare (a, b) și
(ii) să implice o modificare catre cea mai bună valoare curentă x care este mai mică de
jumătate din modificarea facuta cu un pas înaintea celei curente. Acest al doilea criteriu
asigură că etapele parabolice sunt de fapt convergând la ceva, mai degrabă decât să
zicem, sărind în jurul unor neconvergente din ciclul limită.
În cel mai rău caz posibil, unde etapele parabolice sunt acceptabile, dar inutil, metoda va alterna
aproximativ între trepte parabolice și ale sectiunii de aur secțiuni, convergând la timp în virtutea
acestora din urmă. Motivul de comparare a valorilor curente cu cele din pasul anterior este esential:
Experiența arată că este mai bine să nu „pedepsească” algoritmul pentru o singură etapă proastă
dacă îl poate compensa pe următorul.
Un alt principiu exemplificat în cod este să nu evaluezi funcția mai puțin decât o distanță tol dintr-
un punct deja evaluat (sau dintr-o paranteză cunoscută punct). Motivul este că, așa cum am văzut în
ecuația (Optim.1.2), nu există pur și simplu nu conținut de informații în acest sens: funcția va diferi
de valoarea deja existentă evaluata insuficient. Prin urmare, în codul de mai jos veți găsi mai multe
teste și modificări ale unui potențial nou punct, impunând acest lucru printr-o restricţie. Această
restricție interacționează de asemenea subtil cu testul „doneness”, care decide asupra metodei ce va
fi utilizata.

//---------------------------------------------------------------------------------
// Brent -
//---------------------------------------------------------------------------------
// SCOP: fiind data functia f, si trei limite ale absciselor ax, bx,cx
// (ax<bx<cx) si f(bx) < f(ax) si f(bx) < f(cx) aceasta functie izoleaza
minimul
// functiei f(x) cu o precizie impusa folosind metoda Brent.
// Valoarea lui x pentru care s-a obtinut minimul este notata cu xmin si
intoarsa
// in programul principal.
//----------------------------------------------------------------------------------
double brent(double ax, double bx, double cx, double (*f)(double), double tol,double
*xmin)
{
int iter;
double a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
double e=0.0;

/* Marimea pasului curent*/


a=(ax < cx ? ax : cx); //a si b trebuie sa fie in ordine crescatoare
b=(ax > cx ? ax : cx); //dar punctul de pornire de pe ox trebuie
initializat
x=w=v=bx;
fw=fv=fx=(*f)(x);
for (iter=1;iter<=ITMAX;iter++) { // ciclul de baza
xm=0.5*(a+b);
tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
if (fabs(x-xm) <= (tol2-0.5*(b-a))) { // realizarea testului
*xmin=x;
return fx;
}
if (fabs(e) > tol1) { // aproximarea
parabolica
r=(x-w)*(fx-fv);
q=(x-v)*(fx-fw);
p=(x-v)*q-(x-w)*r;
q=2.0*(q-r);
if (q > 0.0) p = -p;
q=fabs(q);
etemp=e;
e=d;
if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-
x))
d=CGOLD*(e=(x >= xm ? a-x : b-x));
// Conditiile determina acceptabilitatea pasului parabolic.
// Se se face pasul bazat pe sectiunea de aur in interiorul domeniului
else {
d=p/q; // se face pasul parabolic
u=x+d;
if (u-a < tol2 || b-u < tol2)
d=SIGN(tol1,xm-x);
}
} else {
d=CGOLD*(e=(x >= xm ? a-x : b-x));
}
u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
fu=(*f)(u);
// evaluarea functiei curente
// Se decide asupra evaluarii
if (fu <= fx) {
if(u >= x) a=x; else b=x;
SHFT(v,w,x,u);
SHFT(fv,fw,fx,fu);
} else {
if (u < x) a=u; else b=u;
if (fu <= fw || w == x) {
v=w;
w=u;
fv=fw;
fw=fu;
} else if (fu <= fv || v == x || v == w) {
v=u;
fv=fu;
}
}
}
nrerror("Nr. de iteratii depasit in brent");
*xmin=x; // atribuirea valorii minime gasite
return fx;

} // end brent

Optim.3 Interpolarea cu funcţii parabolice şi utilizarea acesteia la metoda Brent


pentru funcţii de o singură variabilă.
În cazul utilizării metodei secţiunii de aur a fost utilizată interpolarea parabolică pentru
a se putea analiza cât mai elegant ansamblul de posibilităţi destinate determinării
segmentului în care se găseşte minimul căutat. Dacă se ţine cont că în apropierea
minimului funcţia poate fi interpolată printr-un polinom de ordinul doi, polinom care în
acest caz este o parabolă. Descrierea acestei parabole se face utilizând trei puncte de
pe curbă. Alegerea acestor puncte nu este însă întâmplătoare, acestea trebuie
obligatoriu să îcadreze minimul căutat. Deoarece în acest caz se pune problema
determinării abscisei mai curând decât a ordonatei, problema de interpolare este
atipicabila. Din această cauză se numeşte interpolare parabolică inversă.
Abscisa x care corespunde valorii minime a unei parabole ce trece prin trei punce (a,b,c) şi
care are valoarea în aceste puncte f(a), f(b) şi respectiv f(c) este:

(Optim.3.1)
Această relaţie nu are sens doar în cazul în care punctele sunt coliniare, caz în care
numitorul se anulează şi punctul în care “parabola” are valoare minimă devine infinit.
Din păcate doar utilizarea acestei relaţii la determinarea minimului şi a poziţiei
acestuia nu conduce la rezultatele aşteptate.
Din această cauză se caută o combinare între metoda secţiunii de aur, în care se
analizează poziţia absciselor punctelor care încadrează minimul, pentru a se micşora
domeniul de încadrare şi atunci când s-a atins un domeniu suficient de mic se
utilizează interpolarea pătratică inversă (relaţia 5.8) pentru a se deremina valoarea
abscisei minimului (x).
Din păcate acest mod de abordare nu s-a dovedit eficient deoarece este necesară
calcularea şi menţinerea în memorie a valorilor funcţiei de interpolare pătratice pentru
mai mulţi paşi de aproximare succesivi.
De asemenea este dificilă determinarea momentului în care s-a atins optimul şi se
poate ajunge la influenţa unor erori de rotunjire foarte apropiate de valoarea reală a
minimului căutat. Un alt inconvenient major constă în stabilirea momentului de trecere
de la metoda secţiunii de aur la metoda interpolării parabolice.
Evitarea acestor neajunsuri a fost făcută de Brent [1] prin memorarea pentru fiecare
pas al procesului iterativ a 6 valori ale punctelor funcţiei, a,b,u,v,w şi x.
În această metodă, a şi b sunt limitele domeniului în care se determină minimul,
x este abscisa celei mai mici valori determinate pentru funcţia f în intervalul
(a,b)
w este abscisa următoarei valori minime, mai mare decât valoarea funcţiei în x
v este valoarea anterioară a lui w,
u este abscisa curentă a funcţiei f.
Mai este utilizat şi mijlocul segmentului ab notat cu xm cu toate că funcţia nu este
evaluată în acest punct. Interpolarea parabolică se face pentru punctele, x,v şi w şi
pentru ca pasul să fie acceptat trebuie ca:
a) punctele să fie în intervalul (a,b)
b) să existe o deplasare de la cea mai mică valoare găsită până în acest
moment (la abscisa x) şi această deplasare să fie mai mică decât jumătatea
pasului precedent.
Condiţia b) asigură convergenţa algoritmului şi evită intrarea într-un ciclu infinit.
În cel mai nefavorabil caz, atunci când pasul de interpolare parabolică este acceptabil
dar nu satisface cerinţa b) se utilizează pentru pasul curent metoda secţiunii de aur
urmând ca la următorul pas să se încerce utilizarea interpolării parabolice din nou.
Se asigură astfel o bună convergenţă şi se evită ieşirea forţată din algoritm dacă un
pas al acestuia nu satisface condiţia b)
Se impune o distanţă minimă, tol, astfel încât să nu se facă calculul funcţiei pentru
două puncte care sunt mai apropiate decât această distanţă, deoarece aşa cum se
vede din ecuaţie, valorile funcţiei în cele două puncte vor diferi foarte puţin şi eroarea
de calcul poate influenţa rezultatul semnificativ.

Implementarea metodei, funcţia Brent.


Cu aceste observaţii, funcţia brent, are forma:
// Declaraţii în antet
# include <math.h>
# include “util.h”
# define ITMAX 100
# define CGOLD 0.38109660
#define EPS 1.0e-10
// ITMAX nr.-ul maxim de iteraţii admis pentru determinarea optimului.
#define SHFT(a,b,c,d) (a)=(b); (b)=(c); (c) =(d)

float f_brent(float ax, float bx, float cx, float functieMin(float, float
tol,
float *xmin)
{
int iter;
float a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
float e=0.0;
// noile distanţe de mutare a absciselor. Se impune ca a < b.
a=(ax < cx ? ax : cx);
b=(ax > cx ? ax : cx);
x=w=v=bx;
fw=fv=fx=functieMin(x);
// Ciclul principal
for (iter=1;iter<=ITMAX;iter++) {
xm=0.5*(a+b);
tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
// Testarea terminării
if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
*xmin=x;
return fx;
}
// Construirea interpolării prin trei puncte
if (fabs(e) > tol1) {
r=(x-w)*(fx-fv);
q=(x-v)*(fx-fw);
p=(x-v)*q-(x-w)*r;
q=2.0*(q-r);
if (q > 0.0) p = -p;
q=fabs(q);
etemp=e;
e=d;
if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-
x))
d=CGOLD*(e=(x >= xm ? a-x : b-x));
// Condiţiile de mai sus determină acceptarea pasului patratic.
// Se va utiliza sectiunea de aur (SA) pentru un domeniu mai mare
// decît două segmente.
else {
// Pasul parabolic
d=p/q;
u=x+d;
if (u-a < tol2 || b-u < tol2)
d=SIGN(tol1,xm-x);
}
} else {
d=CGOLD*(e=(x >= xm ? a-x : b-x));
}
u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
// Se evaluează câte o funcţie pe iteraţie
fu=functieMin(u);
// Se analizează funcţiile din iteraţie
if (fu <= fx) {
if (u >= x) a=x;
else b=x;
SHFT(v,w,x,u)
SHFT(fv,fw,fx,fu)
} else {
if (u < x) a=u; else b=u;
// Se formează variabilele noi
if (fu <= fw || w == x) {
v=w;
w=u;
fv=fw;
fw=fu;
} else if (fu <= fv || v == x || v == w) {
v=u;
fv=fu;
}
}
}
nrerror("S-a depasit numarul de iteratii <ITER> in brent");
*xmin=x; // Nu se ajunge aici se iese din nrerror.
return fx;
}

O alternativa este „să folosești tot ceea ce ai”: Calculează un polinom de ordin relativ ridicat (cubic
sau superior) care este de acord cu un număr de funcții precedente și evaluări ale derivatelor. De
exemplu, există un polinom de gradul 3, unic care aproximeaza funcția prin cele 3 puncte iar
derivata lui este un polinom de gradul 2, care poate fi utilizat la determinarea subintervalului in care
se gaseste minimul, (a,c) sau (c,b). Algoritmul dezvoltat de Davidon și alții, este descris în [1].
In practica problemelor pe care le-am întâlnit, semnul derivatei în punctul central al tripletei de
puncte (a, b, c) indică dacă următorul punct de testare trebuie luat în intervalul (a, b) sau în interval
(b, c). La determinarea noului punct din intervalul astfel ales se impun aceleasi conditii ca in
metoda Brent.

Optim 3.1. Determinarea minimului pentru funcţii de o singură variabilă


utilizând prima derivată.

Se caută dezvoltarea algoritmilor deja prezentaţi şi care se bazează pe utilizarea a trei


valori ale variabilei independente pentru a mărgini zona în care se găseşte minimul
prin determinarea primei derivate a funcţiei.
Se poate utiliza o metodă de determinare a rădăcinilor primei derivate, cum ar fi
metoda secantei sau Newton-Rapshon. Deşi din punct de vedere clasic aceste
metode pot fi folosite cu succes, nu se vor dezvolta programe numerice pentru
această metodă din cauza dificultăţilor pe care le implică analiza derivatei de ordinul
doi pentru a vedea dacă avem un maxim sau un minim sau a necesităţii analizei
detaliate a domeniului în care se caută extremul.
Deoarece metodele care se bazează pe utilizarea a trei abscise pentru a delimita zona
extremului sunt precise şi uşor de implementat în programarea numerică ne vom axa
pe dezvoltarea acestora. Din această cauză informaţiile legate de valoarea derivatei
funcţiei vor fi utilizate doar pentru a mări viteza de determinare a noilor triplete de
abscise ce delimitează optimul căutat. În acest mod se asigură utilizarea şi
dezvoltarea metodelor de calcul deja verificate. S-au dezvoltat astfel metode de calcul
bazate pe determinarea unui polinom de ordinul doi care să îndeplinească şi condiţiile
impuse asupra derivatelor de ordinul întîi în punctele de capăt ale intervalului de
mărginire. Analizând minimul acestui poligon se determină următorul punct candidat în
calculul valorii minime căutate şi se reduce intervalul de calcul. Se repetă procedura
până când diferenţa dintre minimul funcţiei şi al poligonului de interpolare devine
neglijabilă. Metoda a fost dezvoltată de Davidon ş.a [3.1]. Dacă analizăm cu atenţie
această metodă se poate observa că nu îtotdeauna aproximaţia polinomială este cea
mai indicată. De multe ori polinomul de interpolare trece prin punctele impuse, dar în
afara acestor puncte se distanţează mult de funcţia pe care dorim să o aproximăm. O
soluţie ar fi utilizarea polinoamelor cu grad mai mic, care în acest caz ar putea deveni
drepte şi nu s-ar ajunge la nici o îmbunătăţire a metodelor deja prezentate.
Din aceste cauze se vor utiliza derivatele de ordinul întâi doar pentru a determina cu
ajutorul semnului acesteia în ce segment se găseşte minimul (a,b) sau (b,c). Pentru
acest lucru este importantă determinarea semnului derivatei funcţiei în punctul b.
Valoarea derivatei în punctul b ca şi în celălalt capăt al segmentului pot fi utilizate
pentru a se determina poziţia în care derivata se anulează. Această abscisă se
determină prin interpolare liniară şi se ajunge la “1.618..” deci exact ca în metoda
secţiunii de aur. Mai departe se impun aceleaşi condiţii ca şi în metoda Brent.
În continuare se introduce funcţia dbrent în limbajul C.
Informaţii privind declaraţiile librăriilor şi a definiţiilor funcţiilor.
#include <math.h>
#define ITMAX 100
#define ZEPS 1.0e-10
#define MOV3(a,b,c, d,e,f) (a)=(d);(b)=(e);(c)=(f);
/*
Fiind dată o funcție f, și dată cu o triplă de bracketing axcissas, bx, cx (astfel
încât bx este între ax și cx, și f (bx) este mai mic decât ambele f (ax) și f (cx)),
această rutină izolează precizia minimă până la o fracțiune de aproximativ tol
folosind metoda Brent. Abscisa din minimul este returnat ca xmin, iar valoarea
minimă a funcției este returnată ca brent,valoarea funcției returnate
INTRĂRI:
functieMin(float) -Funcţia al cărui minim este căutat derivFunc(float) -
Derivata I-a a funcţiei functieMin ax,bx,cx -Abscisele domeniului în care se
caută minimul (ax<bx<cx)
tol -Abaterea admisă
DATE CALCULATE:
fx -Valoarea minimă
*xmin -Abscisa la care se găseşte valoarea minimă
*/
// Date de calcul:
// Indicatoare privind stadiul de calcul şi calea prin algoritm
*/
double dbrent(double ax, float bx, double cx, double (*f)(double),
double (*df)(double), double tol, double *xmin)
{

int iter,ok1,ok2;
double a,b,d,d1,d2,du,dv,dw,dx,e=0.0;
double fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm;

a=(ax < cx ? ax : cx);


b=(ax > cx ? ax : cx);
x=w=v=bx;
fw=fv=fx=(*f)(x);
dw=dv=dx=(*df)(x);
for (iter=1;iter<=ITMAX;iter++) {
xm=0.5*(a+b);
tol1=tol*fabs(x)+ZEPS;
tol2=2.0*tol1;
if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
*xmin=x;
return fx;
}
if (fabs(e) > tol1) {
d1=2.0*(b-a);
d2=d1;
if (dw != dx) d1=(w-x)*dx/(dx-dw);
if (dv != dx) d2=(v-x)*dx/(dx-dv);
u1=x+d1;
u2=x+d2;
ok1 = (a-u1)*(u1-b) > 0.0 && dx*d1 <= 0.0;
ok2 = (a-u2)*(u2-b) > 0.0 && dx*d2 <= 0.0;
olde=e;
e=d;
if (ok1 || ok2) {
if (ok1 && ok2)
d=(fabs(d1) < fabs(d2) ? d1 : d2);
else if (ok1)
d=d1;
else
d=d2;
if (fabs(d) <= fabs(0.5*olde)) {
u=x+d;
if (u-a < tol2 || b-u < tol2)
d=SIGN(tol1,xm-x);
} else {
d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
}
} else {
d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
}
} else {
d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
}
if (fabs(d) >= tol1) {
u=x+d;
fu=(*f)(u);
} else {
u=x+SIGN(tol1,d);
fu=(*f)(u);
if (fu > fx) {
*xmin=x;
return fx;
}
}
du=(*df)(u);
if (fu <= fx) {
if (u >= x) a=x; else b=x;
MOV3(v,fv,dv, w,fw,dw)
MOV3(w,fw,dw, x,fx,dx)
MOV3(x,fx,dx, u,fu,du)
} else {
if (u < x) a=u; else b=u;
if (fu <= fw || w == x) {
MOV3(v,fv,dv, w,fw,dw)
MOV3(w,fw,dw, u,fu,du)
} else if (fu < fv || v == x || v == w) {
MOV3(v,fv,dv, u,fu,du)
}
}
}
nrerror("Too many iterations in routine dbrent");
return 0.0;
}
Acton, F.S. 1970, Numerical Methods That Work; 1990, corrected edition (Washington: Mathematical
Association of America), pp. 55; 454–458. [1]
Brent, R.P. 1973, Algorithms for Minimization without Derivatives (Englewood Cliffs, NJ: Prentice-
Hall), p. 78.

Optim.4. Metoda simplexurilor pentru cazul funcţiilor de


mai multe variabile.

Metoda a fost publicată de Nelder şi Mead [4.1] şi nu necesită decât evaluarea funcţiei
ce va fi optimizate fără să fie necesare şi determinările derivatelor acesteia. Metoda se
foloseşte doar pentru optimizarea funcţiilor care depind de mai mulţi parametri şi nu
este foarte eficientă prin prisma valorii optime determinate ca şi a poziţiei acesteia.
Marele avantaj al acestei metode constă însă în simplitatea sa şi în faptul că poate fi
utilizată împreună cu metode mult mai precise pentru a determina valoarea şi poziţia
optimului căutat. Se asigură astfel delimitarea zonei sau zonelor în care se găsesc
extremele funcţiei ca şi a mărimilor necesare pentru ca în aceste zone să se poată
aplica metode de tip gradient pentru stabilrea soluţiilor dorite ca şi valorile parametrilor
independenţi dacă este nevoie.
De asemenea metoda permite o vizualizare geometrică fără mari probleme ceea ce
face o face uşor de înţeles şi mai ales uşor de aplicat la probleme de complexitate
mare.
Un simplex este o figură geometrică care într-un spaţiu cu N dimensiuni constă într-un
număr de N+1 puncte unite prin segmente de dreaptă în aşa manieră încât să se
genereze feţe poligonale. Astfel în 2D simplexul este un triunghi, în 3D un tetraedru,
etc., nu este necesar ca aceste figuri să fie şi regulate. În cazurile cele mai simple de
implementare aceste simplexuri sunt regulate, deci triunghi echilateral, tetraedru
regulat, etc. Singura restricţie care se pune acestor simplexuri este aceea de a nu fi
degenerate, deci de a nu avea puncte suprapuse. În plan triunghiul să nu degenereze
în dreaptă, etc. Algoritmul va porni dintr-o soluţie iniţială introdusă de programator,
ceea ce d.p.d.v. geometric reprezintă un vector N-dimensional care constă din valorile
de pornire pentru variabilele independente. Caz întâlnit frecvent la majoritatea
metodelor de optimizare.
Având cunoscut acest prim punct algoritmul va căuta singur minimul indiferent de
complexitatea pe care o poate avea o funcţie în spaţiul cu N dimensiuni. Atunci când a
fost întâlnit un punct de minim (chiar şi local) acesta se opreşte şi soluţia este salvată.
Metoda poate fi iniţiată şi prin utilizarea mai multor puncte, N+1 puncte, deci primul
simplex. Dacă se porneşte de la un singur punct, P0, atunci celelalte puncte ale
simplexului se pot determina utilizând relaţia:

(Optim 4.1)
unde λi este o constantă ce înmulţeşte versorul direcţiei ei. Astfel λi reprezintă scările
pentru fiecare direcţie care sunt utilizate la realizarea simplexului. Există programe care
utilizează de regulă o singură scară.
În urma definirii simplexului algoritmul constă într-o serie de paşi, majoritatea dintre
aceştia constau în mutarea punctelor simplexului din zonele în care valoarile funcţiei
sunt mari către zonele în care valorile funcţiei sunt mai mici. Aceşti paşi sunt paşi de
“reflecţie” sau simplu “reflecţii” şi au caracteristica de a respecta condiţia ca noul
simplex să-şi păstreze volumul constant în zonele în care nu sunt extreme. Mai mult,
unii algoritmi permit chiar o mărire a volumului simplexului, (λi + δλi) ceea ce conduce
la reducerea numărului total de simplexuri şi parcurgerea mai rapidă a zonelor lipsite
de interes.
La întâlnirea zonelor în care suprafaţa definită de funcăia ce se optimizează suferă o
modificare a pantei, atunci şi coeficienţii de scară se modifică, (λi – δλi) generând
simplexuri din ce în ce mai mici, deci o reţea din ce în ce mai fină. Se asigură astfel
apropierea de minim. În aceste zone simplexurile se “contractă”, în scopul de a
asigura mărirea preciziei. În figura 5.4 se prezintă posibilităţile pe care funcţia special
proiectată le îndeplineşte.
Criteriile care conduc la decizia de terminare a procesului de optimizare trebuie să fie
introduse cu mare atenţie. Acest lucru este specific majorităţii metodelor destinate
optimizării funcţiilor de mai multe variabile sau a rezolvării sistemelor de ecuaţii
neliniare. Dificultăţile sunt generate de lipsa unui domeniu bine stabilit în care putem
căuta minimul ca şi de faptul că avem mai multe variabile independente ceea ce face
greoaie procedura utilizată în cazul unei singure variabile. Având în vedere aceste
observaţii se poate adopta opţiunea de terminare a procesului de optimizare prin
analizarea vectorului deplasării pe care o are simplexul nou creat faţă de cel
precedent. În cazul în care această deplasare este mai mică decît o mărime aleasă,
notată în program cu tol. De asemenea se poate impune ca diferenţa dintre valoarea
minimă a funcţiei din simplexul nou şi cea din simplexul anterior să fie mai mică decât
o valoare impusă, notată în program cu tol_1. Deşi ambele criterii au fost introduse în
program, acestea pot fi depăşite la generarea unui simplex atipic. În acest caz, se
restartează procesul de minimizare din punctul în care aceasta a selectat un minim
prim reiniţializarea tuturor variabilelor, astfel se reiniţiază N din cele N+1 versori şi se
impune P0 în punctul pe care rularea anterioară l-a găsit ca fiind minim.
În continuare se prezintă funcţia simplexuri destinată detrminării minimului utilizând
această metodă.
Implementarea funcţiei Simplexuri.
Simplexuri.h

#include <math.h>
// Cel mai mic număr pentru estimarea poziţiei simplexului.
#define TINY 1.0e-10
//Numărul maxim de evaluări ale funcţiei.

#define NMAX 5000


#define GET_PSUM \
for (j=1;j<=ndim;j++) {\
for (sum=0.0,i=1;i<=mpts;i++) sum += p[i][j];\
psum[j]=sum;}
#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}

void simplexuri(double **p, float y[], int ndim, double ftol,double


functieMin(double []), int *nfunk);

double amotry(double **p, double y[], double psum[], int ndim, double
functieMin(double []), int ihi, double fac)

// Codul funcţiilor

void simplexuri(double **p, double y[], int ndim, double ftol,double


functieMin(double []), int *nfunk)
{
// Variabile intregi
int ndim, i,ihi,ilo,inhi,j,mpts=ndim+1;
// Variabile float
double amotry(double **p, double y[], double psum[]);
double functieMin(double []), int ihi, double fac);
double rtol,sum,swap,ysave,ytry,*psum;

psum=m1ddouble(1,ndim);
*nfunk=0;
GET_PSUM
for (;;) {
ilo=1;
// Se determină valoarea funcţiei în vîrfurile simplexului şi se
// ordonează crescător
ihi = y[1]>y[2] ? (inhi=2,1) : (inhi=1,2);
for (i=1;i<=mpts;i++) {
if (y[i] <= y[ilo]) ilo=i;
if (y[i] > y[ihi]) {
inhi=ihi;
ihi=i;
} else if (y[i] > y[inhi] && i != ihi) inhi=i;
} // end if
rtol=2.0*fabs(y[ihi]-y[ilo])/(fabs(y[ihi])+fabs(y[ilo])+TINY);

// Calculează raportul dintre valorile maxime şi minime ale funcţiei în


// vîrfurile simplexului şi revino în program dacă simplexul nu este
// degenerat.
if (rtol < ftol) { // Dacă da pune pe poziţia 1 virful.
SWAP(y[1],y[ilo])
for (i=1;i<=ndim;i++) SWAP(p[1][i],p[ilo][i])
break;
} // end if
if (*nfunk >= NMAX) nrerror("NMAX exceeded");
*nfunk += 2;
// Incepe o noua iteratie. Inmulţeşte cu -1 faţa opusă vârfului pentru
// care y[] este maximă pentru a face reflexia faţă de acest punct.
ytry=amotry(p,y,psum,ndim,funk,ihi,-1.0);
if (ytry <= y[ilo])
// Se obţine un rezultat mai mic decât minimul din simplexul anterior
// şi se încearcă extinderea simplexului cu scara 2.
ytry=amotry(p,y,psum,ndim,funk,ihi,2.0);
else if (ytry >= y[inhi]) {
// Punctul obţinut prin reflexie nu este aşa de bun ca ca cel cu
// valoarea imediat inferioară celui de-al doilea maxim.
// Se ncearcă o contracţie după direcţia acestei variabile.
ysave=y[ihi];
ytry=amotry(p,y,psum,ndim,funk,ihi,0.5);
if (ytry >= ysave) {
// Nu poate fi eliminat punctul cu valoare maximă.
// Se încearcă contracţia pentru cel cu valoarea minimă.
for (i=1;i<=mpts;i++) {
if (i != ilo) {
for (j=1;j<=ndim;j++)

p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]);
y[i]=(*funk)(psum);
} // end if
}// end for i
// Păstrează rezultatele evaluării funcţiei.
*nfunk += ndim;
// Recalculează psum.
GET_PSUM
}
} else --(*nfunk);//Corecţie a nr. De iteraţii.
} // Inapoi la testarea unei noi iteraţii.
free_m1ddouble(psum,1,ndim);
} // end functie.

/*
Inmulţeşte cu factorul de scară <fac> faţa simplexului opusă valorii maxime.
Incearcă noul rezultat şi înlocuieşte punctul cu valoarea maximă dacă noul
punct este mai bun.
*/
double amotry(double **p, double y[], double psum[], int ndim, double
functieMin(double []), int ihi, double fac)
{
int j;
double fac1,fac2,ytry,*ptry;
ptry=m1ddouble(1,ndim);
fac1=(1.0-fac)/ndim;
fac2=fac1-fac;
for (j=1;j<=ndim;j++) ptry[j]=psum[j]*fac1-p[ihi][j]*fac2;
// Evaluează funcţia în cel de-al treilea punct.
ytry=functieMin(ptry);
// Dacă soluţia este mai bună înlocuieşte vârful cu valoare maximă.
if (ytry < y[ihi]) {
y[ihi]=ytry;
for (j=1;j<=ndim;j++) {
psum[j] += ptry[j]-p[ihi][j];
p[ihi][j]=ptry[j];
} // end for
}// end if
free_m1ddouble(ptry,1,ndim);
return ytry;
}

Optim 5. Minimizarea utilizând metode bazate pe direcţii de căutare


În cubcapitolele 5.1, 5.2 şi 5.3 s-a dezvoltat proceduri de optimizare pentru funcţii de o
singură variabilă. În cazul funcţiilor de mai multe variabile problema apare mult mai
complicată, dar dacă se consideră că se porneşte procesul de căutare a minimului
pornind de la un punct iniţial, P0, şi se continuă căutarea minimului pe direcţia unei
axe, (caz în care doar o singură variabilă poate lua valori), atunci, problema poate fi
redusă la optimizarea unei funcţii de o singură variabilă. Acesta este considerentul pe
care se bazează toate metodele de optimizare de tipul direcţiilor conjugate, Powell,
etc. Toate aceste metode de optimizare au în comun o procedură de tipul:

Fiind dat un punct P, o direcţie n şi o funcţie f, să se determine o nărime scalară, λ, care


să minimizeze funcţia f(P + λ n). Se înlocuieşte P cu P + λ n şi n cu λ n. Sfârşit.

Această procedură este implementată în funcţia C, linMin şi este comună metodelor


de acest tip. Tot o procedură comună acestor algoritmi este şi cea de determinare a
direcţiei care conduce cel mai rapid la determinarea minimului. Aceasta este
implementată pentru cazul de faţă în funcţia C denumită linFind şi deoarece este
utilizată şi de programe care folosesc gradienţii funcţiei de optimizat conţine şi
utilizarea mărimilor acestora. Prin neapelarea funcţiilor care calculează gradienţii se
poate adapta cu uşurinţă metodelor mai generale care nu necesită calculul
gradienţilor. Acelaşi lucru este valabil şi pentru linMin.
Modul de lucru al algoritmilor bazaţi pe eceste metode constă în principiu în:
Fiind considerat un set de direcţii e1,e2, …,eN corespunzând fiecărei variabile
independente. Utilizând linMin se face o deplasare spre minim după prima
direcţie şi determină punctul P1, din P1 se face o deplasare spre minimul de pe
direcăia P2 şi se continuă procesul de căutare pentru următoarele direcţiii şi aşa
mai departe.
Procesul continuă iterativ din punct în punc. Oprirea procesului de căutare a
minimului are loc atunci când valoarea funcţiei în punctul curent nu mai scade.

Observaţii.
Deoarece nu are loc o evaluare în prealabil a direcţiei după care scăderea funcţiei
este maximă procesul poate în unele cazuri să dureze mult mai mult decât ar fi
necesar.
Obţinerea unei soluţii cât mai precisă se face prin micşorarea pasului discretizării. De
asemenea este necesară evitarea unui număr mare de iteraţii prin introducerea unor
direcţii de căutare alese cât mai judicios ca şi prin testarea direcţiei pe care valoarea
funcţie scade cît mai rapid.
S-au introdus astfel mai multe variante ale algoritmului.
Acestea se bazează pe alegerea unor direcţii care să evite zonele cu scăderi sau
creşteri bruşte ale funcţiei sau pe căutarea unor direcţii cu proprietatea că minimizarea
funcţiei pe o direcţie să nu fie afectată de celelalte direcţii, astfel încât deolasarea spre
minimul funcţiei să se facă din cât mai puţini paşi.

Optim. 5.1. Metoda Powell pentru funcţii de mai multe variabile

Direcţiile onjugate.

Dacă se dezvoltă în serie Taylor funcţia f(x1,..,xN) în jurul unui punct P şi se grupează
termenii care conţin prima şi a doua derivată se pot determina direcţiile căutate.

(Optim. 5.1)
Termenii ecuaţiei pot fi scrişi su forma:

(Optim 5.2)
Să considerăm că s-a căutat minimul pe un set de direcţii U şi se urmăreşte acum
deplasarea la alt set de direcţii V astfel încât să nu se influenţeze pe cât posibil
valoarea obţinută la căutarea anterioară. Această condiţie este îndeplinită dacă
gradientul tinde spre zero, deci direcţiile sunt perpendiculare.

(Optim 5.3)
Atunci când [U][A][V] 0 direcţiile [U] şi [V] se numesc conjugate.
Succesul metodelor de optimizare bazate pe metoda căutării optimului pe un set de
direcţii independente este asigurat dacă aceste direcţii sunt conjugate. Din această
cauză primul pas în algoritmul de optimizare constă în determinarea acestor direcţii şi
apoi se realizează dezvoltarea în serii Taylor în jurul punctului curent şi fie se caută
cea mai mică valoare a funcţiei pe direcţiile conjugate sau se rezolvă sistemul:

(Optim 5.4)
Obţinerea setului de direcţii conjugate nu este atât de simplă cum pare. Procedura
care este implementată reiniţializează un set de direcţii [U] după ce au fost efectuate
N iteraţii pentru a se evita problemele legate de algoritmul Powell de generare a
direcţiilor conjugate.

Funcţia C destinată optimizării unei probleme mutidimensionale este dată în


continuare.

// Librării şi declaraţii necesare în programul principal


#define TINY 1.0e-25 //Cel mai mic număr
#define ITMAX 200
// Funcţia Powell
int ncom; // variabila globala pentru schimb cu f1dim
double *pcom,*xicom,(*nrfunc)(double []);

void powell(double p[], double **xi, int n, double ftol, int *iter, double
*fret,double (*func)(double []))
{
/*
SCOP: Minimizarea unei functii de n variabile
INTRARI : Solutia initiala: p[1..n]
Matricea initiala xi[1..n][1..n] - pe coloane sunt directiile
initiale
ftol - abaterile fractionale ale functiilor sistemului
IESIRI : Solutia cautata in p[1..n]
xi[1..n][1..n] directiile curente de cautare
fret[] valorile extreme ale functiei in punctul p[1..n]
FUNCTII APELATE: linmin()

*/

void linmin(double p[], double xi[], int n, double *fret, double


(*func)(double []));

int i,ibig,j;
double del,fp,fptt,t,*pt,*ptt,*xit;

pt=m1ddouble(1,n);
ptt=m1ddouble(1,n);
xit=m1ddouble(1,n);
*fret=(*func)(p);
// salveaza punctului initial
for (j=1;j<=n;j++) pt[j]=p[j];
for (*iter=1;;++(*iter)) {
fp=(*fret);
ibig=0;
del=0.0;
// functia cu descresterea maxima
// pentru fiecare directie se calculeaza pina la numarul maxim de
iteratii
for (i=1;i<=n;i++) {
for (j=1;j<=n;j++) xit[j]=xi[j][i]; // se copiaza directia
fptt=(*fret);
// se determina descresterea maxima
linmin(p,xit,n,fret,func);
if (fptt-(*fret) > del) {
del=fptt-(*fret); // se memoreaza
descresterea maxima
ibig=i;
}
}
if (2.0*(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))+TINY) {
free_m1ddouble(xit,1,n); // Terminarea criteriului.
free_m1ddouble(ptt,1,n);
free_m1ddouble(pt,1,n);
return;
}

if (*iter == ITMAX) nrerror("powell exceeding maximum iterations.");


for (j=1;j<=n;j++) {
ptt[j]=2.0*p[j]-pt[j];
xit[j]=p[j]-pt[j];
pt[j]=p[j];
}

fptt=(*func)(ptt);
if (fptt < fp) {
t=2.0*(fp-2.0*(*fret)+fptt)*SQR(fp-(*fret)-del)-del*SQR(fp-
fptt);
if (t < 0.0) {
linmin(p,xit,n,fret,func);
for (j=1;j<=n;j++) {
xi[j][ibig]=xi[j][n];
xi[j][n]=xit[j];
}
}
}
} // inapoi la pasul iteratiilor

} // end func powell-mv

Optim. 5.2. Implementarea funcţiei C linMin.


Metoda adoptată pentru linMin se bazează pe cele descrise în 5.1-5.3 dar trebuie
făcute câteva mici modificări pentru a se ţine cont de punctul curent de căutare şi
abscisele (a,b,c) se referă în acest caz la vecinătăţi ale abscisei punctului curent. Se
construieşte astfel o funcţie ce depinde doar de variabila direcţiei dorite, f1D, iar
pentru această funcţie se utilizează procedurile abcDetermin cu derivBrent sau
minGolden pentru a determina minimul acesteia. Se utilizează astfel funcţiile deja
descrise în subcapitolele anterioare pentru a determina minimul căutat.

// Declaraţii librării şi variabile globale


#define TOL 2.0e-4
int ncom;
float *pcom,*xicom,nrFunctie(float []);

void linMin(double p[], double xi[], int n, double *fret, double (*func)(double []))
{

double brent(double ax, double bx, double cx,double (*f)(double), double tol,
double *xmin);
double f1dim(double x);
void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb,double
*fc, double (*func)(double));
int j;
double xx,xmin,fx,fb,fa,bx,ax;
ncom=n;

pcom=m1ddouble(1,n);
xicom=m1ddouble(1,n);
nrfunc=func;
for (j=1;j<=n;j++) {
pcom[j]=p[j];
xicom[j]=xi[j];
}

ax=0.0;
xx=1.0;
mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
*fret=brent(ax,xx,bx,f1dim,TOL,&xmin);
for (j=1;j<=n;j++) {
xi[j] *= xmin;
p[j] += xi[j];
}
free_m1ddouble(xicom,1,n);
free_m1ddouble(pcom,1,n);

} // end linMin

// Definirea funcţiei f1dim Declaraţii în header


// Variabile deja definită în linMin.
extern int ncom;
extern float *pcom,*xicom,(*nrfunc)(float []);
// Funcţie apelată de linMin
double f1dim(double x)
{
int j;
double f,*xt;
xt=m1ddouble(1,ncom);
for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
f=(*nrfunc)(xt);
free_m1ddouble(xt,1,ncom);
return f;
}

Optim. 5.3. Metoda gradienţilor conjugaţi pentru funcţii de mai multe


variabile.
Să presupunem că avem toate datele necesare pentru a determina într-un punc P atât
valoarea funcţiei cât şi valoarea derivatelor de ordinul întâi a acesteia.
Dacă se consideră dezvoltarea în serie Taylor în jurul unui punct, P, a funcţiei a cărui
optim dorim să-l determinăm, şi se plecă de la premisa că distanţa spre acesta se
obţine cu un minim efort prin urmărirea acelor direcţii pentru care gradienţii funcţiei
sunt maximi.
Se pot astfel stabili direcţiile cele mai avantajoase şi prin acesasta se poate micşora
substanţial efortul de calcul. Există însă cazuri când cu toată eficienţa algoritmului,
efortul de calcul al gradienţilor este atât de mare încât metodele descrise anterior sunt
mult mai rapide şi uşor de utilizat.
Dacă se pleacă de la ecuaţia 5.10 pusă sub formă matricială cu relaţiile 5.11 se ob se
oţine:
(Optim. 5.5)
ecuaţie care este pătratică. Se observă că numărul de parametrii necesari rezolvării
ecuaţiei (5.14) este dat de mărimea matricilor [B] şi [A], fiind 0,5N(N+1), deci de
ordinal N2. Modificarea unuia dintre aceştia conduce la modificarea poziţiei punctului
generat în procesul de optimizare. În metoda direcţuulor conjugate, sunt necesare N2
determinări ale valorii funcţie f pe aceste direcţii pentru a se putea găsi noua poziţie
spre minim.
Dacă utilizăm şi gradienţii vom mai adăuga N determinări şi pentru valoarea acestora.
Dar dacă folosim aceste informaţii putem să determinăm mult mai rapid direcţiile pe
care funcţia se îndreaptă spre minim şi ne putem aştepta să micşorăm substanţial
efortul de calcul. În acest scop se poate porni, caşi în metodele care nu utilizează
gradienţi, de la o soluţie arbitrară P0 şi un vector arbitrar g0 şi se consideră h0=g0 .
Se determină noile direcţii conjugate de forma:

(Optim. 5.6)
Se pun condiţiile ca vectorii gi+1 şi hi+1 să satisfacă condiţia de ortogonalitate şi să fie
conjugaţi:

(Optim. 5.7)
Mărimile scalare λi şi γi se pot determina cu relaţiile:

(Optim. 5.8)
Să presupunem că nu se cunoaşte matricea A şi nu putem determina direcţiile g şi h
cu ajutorul ecuaţiei (5.17) sau noua poziţie a optimului cu ajutorul multiplicatorilor
Lagrange ca în subcapitolul (4.3). De fapt se doreşte reducerea efortului de calcul
necesar determinării Hessianului în cazul unor expresii complicate ale derivatelor de
ordinul doi.
Evitarea acestor calcule se poate face prin considerarea în punctul Pi a vectorului
direcţiei gi de forma

(Optim. 5.9)
Se determină noul punct Pi+1 cu ajutorul funcţiei linMin şi se cunoaşte gi+1

(Optim. 5.10)
Se determină în continuare
(Optim. 5.11)
Programul de calcul se bazează pe descrierea făcută de Fletcher-Reeves-Polak-
Ribiere şi este implementat în funcţia principală frpr_gcm care apelează funcţia linmin
pentru a determina minimul pe direcţiile variabile, funcţia functieMin pentru a calcula
valoarea funcţiei ce se minimizează şi funcţia functieDeriv_1 pentru calculul
derivatelor de ordinal întâi al acesteia.

// Declaraţii în secţiunea variabilelor generale

#define ITMAX 200


#define EPS 1.0e-10
#define FREEALL free_vector(xi,1,n);free_vector(h,1,n);free_vector(g,1,n);

/* ----------------------------------------------------------------------------
SCOP
Calculeaza minimul functiei functieMin utilizând metoda gradientilor
gradientilor conjugati.
DATE DE INTRARE
P[1..n] - punctul iniţial
Ftol - criteriul de convergenta
DATE OBTINUTE
P[1..n] - punctul minimului
fret - valoarea minima a funcţiei
---------------------------------------------------------------------------------*/
void frprmn(double p[], int n, double ftol, int *iter, double *fret,double
functieMin(double []),
void functieDeriv_1(double [], double []))
{
void linmin(double p[], double xi[], int n, double *fret,double
functieMin(double []));

int j,its;
double gg,gam,fp,dgg;
double *g,*h,*xi;

g=m1ddouble(1,n);
h=m1ddouble(1,n);
xi=m1ddouble(1,n);

// INIŢIALIZĂRI FUNCŢII

fp=functieMin(p);
functieDeriv_1(p,xi);

for (j=1;j<=n;j++) {
g[j] = -xi[j];
xi[j]=h[j]=g[j];
}
// Ciclul iterativ
for (its=1;its<=ITMAX;its++) {
*iter=its;
// Caută noul punct
linmin(p,xi,n,fret,functieMin);
if (2.0*fabs(*fret-fp) <= ftol*(fabs(*fret)+fabs(fp)+EPS)) {
FREEALL1;
return;
}
fp= *fret;
functieDeriv_1(p,xi);
dgg=gg=0.0;

for (j=1;j<=n;j++) {
gg += g[j]*g[j];
// dgg += xi[j]*xi[j]; Criteriul Fletcher-Reeves.
dgg += (xi[j]+g[j])*xi[j]; //Criteriul Polak-Ribiere.
}

if (gg == 0.0) {//Solutie neaşteptată Gradient zero.


FREEALL1;
return;
}
gam=dgg/gg;

for (j=1;j<=n;j++) {
g[j] = -xi[j];
xi[j]=h[j]=g[j]+gam*h[j];
}
}
nrerror("Numarul maxim de iteratii depasit");
}

Optim. 5.3.1. Funcţia linMinDeriv_1 utilizând derivatele de ordinul întâi.


În cazul în care derivatele funcţiei pot fi calculate fără a întâmpina dificultăţi sau în
cazul în care se utilizează gradienţii este posibilă modificarea funcţiei linMin cu
linMinDeriv_1 care utilizează f1D şi df1dim.

#define TOL 2.0e-4 //Abaterea comună cu dbrent.


int ncom; //Nr. De variabile comune cu f1D.
float *pcom,*xicom,(*nrfunc)(float []);
void (*nrdfun)(float [], float []);
/*------------------------------------------------------------------------------
SCOP
Calculeaza valoarea minimă şi poziţia acesteia pentru direcţiile
considerate utilizând şi derivatele funcţiei.
DATE DE INTRARE
P[1..n] - punctul soluţiei curente
Xi[1..n] - direcţia curentă aplicată în punctul P
DATE RETURNATE
P[1..n] - punctul soluţiei ce minimizează funcţia
Xi[1..n] - direcţia nouă
Fret - valoarea funcţiei în noul punct
FUNCTII APELATE
abcDetermin
derivBrent
--------------------------------------------------------------------------------*/
void linMinDeriv_1(double p[], double xi[], int n, double *fret, double
functieMin(double []),
void functieDeriv_1(double [], double []))
{
double derivBrent(double ax, double bx, double cx,double (*f)(double), double
(*df)(double), double tol, double *xmin);
double f1D(double x);
double df1dim(double x);
void abcDetermin(double *ax, double *bx, double *cx, double *fa, double
*fb,double *fc, double functieMin(double));
int j;
double xx,xmin,fx,fb,fa,bx,ax;

ncom=n;
pcom=m1ddouble(1,n);
xicom=m1ddouble(1,n);
nrfunc=functieMin;
nrdfun=functieDeriv_1;

for (j=1;j<=n;j++) {
pcom[j]=p[j];
xicom[j]=xi[j];
xicom[j]=xi[j];
}
//Punctele iniţiale de căutare
ax=0.0;
xx=1.0;
abcDetermin(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
*fret=derivBrent(ax,xx,bx,f1dim,df1dim,TOL,&xmin);
// Construirea vectorilor rezultatelor.
for (j=1;j<=n;j++) {
xi[j] *= xmin;
p[j] += xi[j];
}
free_m1ddouble(xicom,1,n);
free_m1ddouble(pcom,1,n);
}

extern int ncom; // Definite în dlinmin.


extern double *pcom,*xicom,(*nrfunc)(double []);
extern void (*nrdfun)(double [], double []);
double df1dim(double x)
{
int j;
double df1=0.0;
double *xt,*df;
xt=m1ddouble(1,ncom);
df=m1ddouble(1,ncom);
for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
(*nrdfun)(xt,df);
for (j=1;j<=ncom;j++) df1 += df[j]*xicom[j];
free_m1ddouble(df,1,ncom);
free_m1ddouble(xt,1,ncom);
return df1;
}
Optim. 6. Metode bazate pe calculul derivatelor pentru variabile
multidimensionale

Metodele se bazează pe căutarea minimului prin iteraţii sucesive pe cele N dimensiuni


prin utilizarea primelor derivate ale funcţiei obiectiv. Dar spre deosebire de metoda
gradienţilor conjugaţi aceste metode memorează şi actualizează o cantitate mai mare
de date. Din punctul de vedere al eficienţei calculului ca şi al managementului
resurselor, multe softuri complexe moderne utilizează metoda gradienţilor.
Există implementate două variante ale acestor clase de metode, Davidon-Fletcher-
Powell (DFP) şi Broyden-Fletchel-Goldforb-Shanno (BFGS) variante care diferă în
modul de estimare a erorii de calcul a mărimii abaterii admise pentru determinarea
soluţiei. Să considerăm o dezvoltare a funcţiei în jurul unui punct curent x a funcţiei:
(optim. 6.1)
Sau:

(Optim. 6.2)
Dacă impunem pentru determinarea noii iteraţii condiţia: ∇f (x) = 0 se obţine sistemul
de ecuaţii:

Deci cu cât mai precisă este determinarea matricii A-1 cu atât mai precisă va fi
valoarea obţinută pentru noua poziţie a punctului curent în procesul de minimizare.
Dar în metodele de acest tip, valoarea A-1 se determină cu ajutorul unui proces iterativ
care s-a dovedit că este mai eficient decât calculul exact al Hessianului (H = A-1).
Metodele ce se bazează pe acest mod de abordare a problemelor de optimizare se
numesc “cvasi-Newtoniene” deoarece nu se foloseşte valoarea exactă a gradienţior ci
o valuare aproximativă, obţinută printr-un calcul iterativ:

Aceast mod de abordare pare la prima vedere “paradoxal”, dar dacă ţinem seama că
se caută un minim, deci ne găsim pe direcţii pentru care gradienţii trebuie să
îndeplinească condiţiile:

(optim. 6.3)
care impun ca matricea A să fie întotdeauna pozitiv definită. Dacă s-ar utiliza valoarea
exactă a Hessianului s-ar putea întâlni cazul când funcţia să prezinte o creştere a
valorii şi s-ar depăşi punctul de minim căutat.
Ideea de bază constă în pornirea cu o matrice A de test, de regulă matricea unitară şi
calculul matricii H astfel încât aceasta să rămână în permanenţă pozitiv definită şi
simetrică. Această abordare ne asigură că întotdeauna ne deplasăm spre minim către
valori descrescătoare ale funcţiei pe care o minimizăm. În apropierea minimului se
atinge abia valoarea reală a Hessianului şi se găseşte punctul căutat.
Această strategie este utilizată de metoda Broyden-Fletcher-Goldfarb-Shanon[5.7]
(BFGS) funcţiile C utilizate pentru a descrie metoda fiind bfgs şi funcţia linSrch
destinată căutării valorii minime a funcţiei după o direcţie dată.

#define ITMAX 200 // Nr.-ul mare de iteraţii


#define EPS 3.0e-8 // Precizia estimării.
#define TOLX (4*EPS) // Abaterea maximă admisă
#define STPMX 100.0 // Nr.-ul de încercări ptr. căutarea min.
#define FREEALL free_vector(xi,1,n);free_vector(pnew,1,n); \
free_matrix(hessin,1,n,1,n);free_vector(hdg,1,n);free_vector(g,1,n); \
free_vector(dg,1,n);
/*----------------------------------------------------------------------------------
SCOP
Determinarea minimului prin metoda Fletchel-Powell în varianta Broyden-
Fletchel-Goldfarb-Shanno.
INTRARE:
P[1..n] - punctul de pornire în căutarea minimului.
func - funcţia ce se minimizează
dFunc - gradienţii funcţiei
gTol - abaterile de la zero pentru gradienţii funcţiei.
REZULTATE:
P[1..n] - punctul de minim
fRet - valoarea minimă a funcţiei
FUNCTII APELATE:
lnSrc - se utilizează pentru a căuta minimul pe o direcţie.
*/
void bfgs(double p[], int n, double gtol, int *iter, double
*fret,double(*func)(double []),
void (*dfunc)(double [], double []))
{
void lnSrch(int n, double xold[], double fold, double g[], double p[], double
x[],
double *f, double stpmax, int *check, double (*func)(double []));

int check,i,its,j;
double den,fac,fad,fae,fp,stpmax,sum=0.0,sumdg,sumxi,temp,test;
double *dg,*g,*hdg,**hessin,*pnew,*xi;
dg=m1ddouble(1,n);
g=m1ddouble(1,n);
hdg=m1ddouble(1,n);
hessin=m2ddouble(1,n,1,n);
pnew=m1ddouble(1,n);
xi=m1ddouble(1,n);
// Calculează valoarea funcţiei şi a derivatelor şi iniţizeaă matricea
// Hessiană la matrice unitară.
fp=(*func)(p);
(*dfunc)(p,g);
for (i=1;i<=n;i++) {
for (j=1;j<=n;j++) hessin[i][j]=0.0;
hessin[i][i]=1.0;
xi[i] = -g[i];
sum += p[i]*p[i];
}
stpmax=STPMX*FMAX(sqrt(sum),(double)n);
// Ciclul peste numărul de iteraţii
for (its=1;its<=ITMAX;its++) {
*iter=its;
// Se evaluează cu lnSrch direcţia de căutare a minimului şi valoarea
// întoarsă se memorează în fp
lnSrch(n,p,fp,g,xi,pnew,fret,stpmax,&check,func);
fp = *fret;
for (i=1;i<=n;i++) {
xi[i]=pnew[i]-p[i];
p[i]=pnew[i];
}
test=0.0;
for (i=1;i<=n;i++) {
temp=fabs(xi[i])/FMAX(fabs(p[i]),1.0);
if (temp > test) test=temp;
}
if (test < TOLX) {
FREEALL;
return;
}

// Salvează valorile gradienţilor şi recalculează noile valori.


for (i=1;i<=n;i++) dg[i]=g[i];
(*dfunc)(p,g);
// Verifică dacă gradienţii sunt zero
test=0.0;
den=DMAX(*fret,1.0);
for (i=1;i<=n;i++) {
temp=fabs(g[i])*FMAX(fabs(p[i]),1.0)/den;
if (temp > test) test=temp;
}
if (test < gtol) {
FREEALL;
return;
}
for (i=1;i<=n;i++) dg[i]=g[i]-dg[i];
for (i=1;i<=n;i++) {
hdg[i]=0.0;
for (j=1;j<=n;j++) hdg[i] += hessin[i][j]*dg[j];
}
fac=fae=sumdg=sumxi=0.0;
for (i=1;i<=n;i++) {
fac += dg[i]*xi[i];
fae += dg[i]*hdg[i];
xi[i]=0.0;
for (j=1;j<=n;j++) xi[i] -= hessin[i][j]*g[j];
}
}
nrerror("Prea multe iteratii in bfgs");
FREEALL;
}

Bibliografie:
Dennis, J.E., and Schnabel, R.B. 1983, Numerical Methods for Unconstrained Optimization and
Nonlinear Equations (Englewood Cliffs, NJ: Prentice-Hall). [1]
Jacobs, D.A.H. (ed.) 1977, The State of the Art in Numerical Analysis (London: Academic Press),
Chapter III.1, §§3–6 (by K. W. Brodlie). [2]
Polak, E. 1971, Computational Methods in Optimization (New York: Academic Press), pp. 56ff. [3]
Acton, F.S. 1970, Numerical Methods That Work; 1990, corrected edition (Washington: Mathematical
Association of America), pp. 467–468.

S-ar putea să vă placă și