Calcolo numerico/Metodo di Brent

Da testwiki.
Vai alla navigazione Vai alla ricerca

Template:Calcolo numerico

Struttura del metodo

È una combinazione del metodo di bisezione e delle secanti, in cui si sfruttano la sicurezza di convergenza del metodo di bisezione e la velocità di convergenza di quello delle secanti.

Il metodo richiede come input una bracket (b,c) con f(b)∗f(c)<0. Restituisce come output lo zero della funzione nella variabile chiamata b. Nell'algoritmo, b rappresenta l'approssimazione della radice cercata. Il metodo si basa sull'idea che se

|f(b)|<|f(c)|

allora b è più vicino alla radice di quanto lo sia c. Questo in realtà non è sempre vero, infatti se consideriamo una funzione che interseca l'asse x in (0,α) e poi decresce lentamente dopo tale punto, si ha che, pur scegliendo b lontano dalla radice, segue che |f(b)|<|f(c)| ma c è più vicina alla radice di quanto lo sia b.

Nell'algoritmo, a,b rappresentano le due iterate con cui il metodo delle secanti calcola l'iterata successiva, cioè b=xk, a=xk−1, mentre b e c sono gli estremi della bracket.

Algoritmo

1. Definizione di a,b,c: in base all'idea precedente, se |f(b)|>|f(c)| allora scambio fra loro b e c. Poniamo poi a=c per far partire il metodo delle secanti.

2. Test d'arresto sull'ampiezza della bracket: finché |b−c|>ε le istruzioni vengono eseguite.

3. Nuovo passo: ci si avvicina alla radice attraverso l'assegnamento

b=b+dd

dove dd può essere posto uguale al passo del metodo delle secanti oppure uguale al passo del metodo di bisezione, e questa scelta viene valutata a ogni iterazione.

4. Valutazione dei due passi possibili: per scegliere quali dei due metodi usare, si valuta di quanto ci si sposta da b in entrambi i metodi:

dm=(c−b)/2passo di bisezione

Prima di calcolare ds (passo del metodo delle secanti), si valuta df=f(b)−f(a). Se df=0, si pone dd=dm, perché ds non è applicabile. Altrimenti

ds=a−b−af(b)−f(a)∗f(b)

5. Scelta del passo: se entrambi i passi sono applicabili, si eseguono le seguenti istruzioni:

if(sgndm==sgnds∧|ds|<=|dm|)

dd=ds

else

dd=dm

end

Nota: queste istruzioni si giustificano nel seguente modo. Il passo di bisezione rimane sempre nella bracket per definizione del metodo, invece, se il passo di secanti ha direzione opposta, si esce dalla bracket. Una volta assicurato che entrambi i metodi stanno dentro la bracket, si sceglie il passo di ampiezza più piccola, che fa allontanare di meno dall'approssimazione corrente della radice.

6. Controllo[1]

7. Applicazione del passo scelto: d=b+dd

8. Preparazione della terna di punti per un eventuale passo successivo:

a1=a

b1=d

if(sgnf(d)≠sgnf(c))

c1=c

else

c1=b

end

Nota: se sgnf(d)≠sgnf(c), allora segue necessariamente che sgnf(d)≠sgnf(b), perché b,c erano una bracket)

9. Assegnamento:

b=b1

c=c1

if(|f(b)|>|f(c)|)

temp=b;

b=c;

c=temp;

end

a1=c

Metodo implementato:

function [b,it] = Mybrent(f,a,b,c)
if(abs(feval(f,b))>=abs(feval(f,c)))
temp = b;
b = c;
c = temp;
end
while(abs(b-c)>eps)
dm = (c-b)/2;
q = feval(f,a)-feval(f,b);
if(q==0)
ds = dm;
else
ds = a-(b-a)/(feval(f,b)-feval(f,a))*feval(f,b);
end
if(sign(ds)==sign(dm)&&abs(ds)<=abs(dm))
dd = ds;
else
dd = dm;
end
if(dd<eps)
d = eps/2*sign(dd);
end
d = b+dd;
b1 = d;
if(sign(b1)==sign(b))
c1 = c;
else
c1 = b;
end
b = b1;
c = c1;
if(abs(feval(f,c))<=abs(feval(f,b)))
temp = b;
b = c;
c = temp;
end
end

Note

  1. ↑ Prima di usare il passo scelto, bisogna fare un controllo. Se si continua ad applicare il metodo delle secanti, l'ampiezza della bracket non si riduce, e il metodo continua a fare iterazioni anche vicino alla radice, perché la condizione del test di arresto sulla bracket non viene verificata. Allora si aggiunge il seguente test: se |dd|<ε (quindi se il metodo delle secanti sta convergendo), si pone: d=ε/2∗sgndd Nel momento in cui d scavalca la radice, la bracket si riduce velocemente e il metodo si blocca.

Template:Avanzamento