I dette eksempelet skal vi finna eit eller fleire nullpunkt for ein funksjon vha. Newton Raphson-metoden.
Den første funksjonen vi skal bruka er $ f(x) = x^3 - 2x +2 $, samt den deriverte av funksjonen, som er: $ f'(x) = 3x^2 - 2 $
No kan vi like godt begynna å koda ved å definera disse som to funksjonar:
def f(x):
return x**3-2*x+2
def df(x):
return 3*x**2-2
print("Vi tester: f(-1)=",f(1),"og f'(-1) =",df(-1))
Det funkar! Så no er vi klar for å bruka formelen i Newtons metode:
$ x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$
La oss starta med verdien x0 = -1, rekna ut neste verdi med formelen vår, og skriva den ut:
x0 = -1 #Startverdi for x0. Dette er vår gjetning på nullpunktet.
x0 = x0 - f(x0)/df(x0)
print("x0=",x0)
Men stopp litt! Korfor bruker vi x0 både på venstre og høgre side i formelen no? Svaret er vi har ikkje tenkt å ta vare på alle verdiane $x_n$, så vi treng bare ein variabel, som vi har kalla x0. Før vi bruker formelen er den lik -1. Etter at vi har brukt formelen er den lik -4. Dermed kan vi bruka denne formelen inne i ei løkke for å stadig finna betre (forhåpentlig) verdiar for x0:
x0 = -1
n = 0 #Tellevariabel som vi set lik 0 før løkka.
while n < 10:
n += 1 #Vi aukar tellevariabelen med 1 for kvar iterasjon
x0 = x0 - f(x0)/df(x0)
print("Vi fant rota x = ",x0)
Hurra, det stemte! GeoGebra gir det samme svaret, så vi har grunn til å tru at dette vart suksess. Her har vi brukt n som ein tellevariabel og stoppa løkka når n vart 9. Men det kan henda at vi treng fleire iterasjonar for å finna eit svar. Så vi vil heller innføra eit anna stoppkriterium. Vi innfører ein variabel toleranse, som vi kan setja til det vi vil, og så stoppar vi når funksjonsverdien vår er lavare enn denne toleransen:
x0 = -1
n = 0
toleranse = 1e-12 #Vi stoppar når absoluttverdien av f(x) er mindre enn denne.
while abs(f(x0)) > toleranse and n < 100:
n += 1
x0 = x0 - f(x0)/df(x0)
print("Vi fant rota x = ",x0,"etter",n,"iterasjonar")
Merk to ting:
No er det på tide å skriva opp heile programmet. Det innfører ein del nye ting som vi kommenterer under.
"""
Newtons metode
"""
def f(x):
return x**3-2*x+2
def df(x):
return 3*x**2-2
def g(x): #Alternativ funksjon
return 6*x**5 -5*x**4 -4*x**3 +3*x**2
def dg(x):
return 30*x**4 -20*x**3 -12*x**2 +6*x
#Definerer funksjonen newtons_metode som tar navnet på den matematiske funksjonen og dens deriverte som input
#Den treng også startverdien, toleransen og ein Boolsk variabel "skriv"
def newtons_metode(funksjon, derivert, x0, toleranse, skriv=False):
start = x0 #brukt bare i utskriften
n = 0
while abs(funksjon(x0)) > toleranse and n < 100:
n += 1
x0 = x0 - funksjon(x0)/derivert(x0)
if skriv: #Vi testar om skriv er lik True
print ("Startverdi",start,"gav rota:", x0,"med y-verdi",funksjon(x0))
print ("Antal iterasjonar:",n)
return x0
#Her begynnar hovedprogrammet:
startverdiar = [-1, -0.5, 0.1, 0.5, 1.2]
for x0 in startverdiar:
newtons_metode(f, df, x0, 1e-12, True)
Det første du sikkert la merke til er at vi også har definert ein ny funksjon g(x), og dens deriverte. Det er fordi vi nedanfor har laga funksjonen newtons_metode, der vi kan gi navnet til funksjonen vår og til den deriverte som input.
Logikken inne i newtons_metode er som før, men vi har bytta ut f(x) med funksjon(x) og df(x) med derivert(x). Disse to variablane vil då visa til enten f(x) og df(x) eller g(x) og dg(x), eller det vi vil. Dermed kan vi finna nullpunkt til den funksjonen som vi måtte foretrekkja.
For å starta funksjonen newtons_metode må vi då nederst kjøra den i hovedprogrammet. Vi skriv feks.: newtons_metode(f, df, x0, 1e-12, True). Det betyr at funksjonen vår er f, den deriverte er df, toleransen er 1e-12, og vi skal ha utskrift (skriv er lik True).
Det siste vi legg merke til er at vi har laga ei liste med startverdiar. Nederst kan vi dermed kjøra newtons_metode i ei løkke som går gjennom alle verdiane i startverdiar og bruker som input-verdien x0.
No kan vi kjøre metoden vår med startverdien -2 og ein litt romsligare toleranse (1e-6), samt setta skriv=False. Det betyr at ingen av dei printsetningane inne i newtons_metode vil bli brukt. Derfor må vi skriva ut svaret eksmplisitt med ein print-setning. Merk at newton_metode har "return x0" som siste statement. Det betyr at vi kan fanga opp dette talet, og her har vi putta det inn i variabelen nullpkt.
nullpkt = newtons_metode(f, df, -2, 1e-6, False)
print("nullpunkt = ",nullpkt)
Til slutt skal vi sjå eit eksempel på at Newtons metode ikkje klarer å finna nullpunktet. Denne gongen gir vi inn x0 = 1.1 og ser kva som skjer.
newtons_metode(f, df, 1.1, 1e-6, True)
Som vi ser: vi fant ikkje nullpunktet, og algoritmen gjekk derfor derfor heilt til n = 100 før den stoppa.