Programmering
Generelt
PYTHON: Her er Vegards intro til python. Her er et annet
krasjkurs i python for TMA4101.
Se også for eksempel her.
MATLAB: MTELSYS og MTTK bruker matlab. Dette språket er på noen måter bedre til matematikk enn python.
C++: MTELSYS og MTTK lærer dette i TDT4202.
Mørkens kompendium er også bra.
Kode fra forelesninger og øvingstimer
Trapesmetoden for standard normalfordeling (SND)
Trapesmetoden for standard normalfordeling (SND)
- SNDtrapes.py
# -*- coding: utf-8 -*- """ Created on Sun Nov 27 10:34:39 2022 @author: Sebas """ import numpy as np def SND(x): #Dette er funksjonen vår, standard normalfordeling return 1/np.sqrt(2*np.pi) * np.exp(-(x**2)/2) def trapesmetoden(f, a, b, N=1000): #Dette er en funksjon for å ta trapesmetoden mellom a og b for en hvilken som helst funksjon "f" som gis som argument h = (b-a)/N #steglengde mellom a og b med N steg x = np.linspace(a,b,N+1) #punktene til x mellom a og b res = 0 #tellevariabel for i in range(N): res += (f(x[i])+f(x[i+1]))/2 * h #trapesmetodens definisjon return res print(trapesmetoden(SND, 0, 1)) #Print standard normalfordelings sannsynlighet for et resultat mellom 0 og 1 (innenfor ett standardavvik over gjennomsnittet) #Forventet resultat er ~34.1% (altså: 0.341...)
Trapesmetoden for omkretsen av en ellipse
Trapesmetoden for omkretsen av en ellipse
- ellipseOmkrets.py
# -*- coding: utf-8 -*- """ Created on Tue Nov 22 08:48:23 2022 @author: Sebas """ import numpy as np import matplotlib.pyplot as plt a = 2 # halvakse 1 b = 1 # halvakse 2 N = 1000 #antall steg i trapesmetoden Dx = a/N #steglengde def df(x): #Den deriverte av en parametrisering y=f(x) for ellipsen. return -b/(a**2) * (1/(np.sqrt(1-(x**2)/(a**2)))) * x def phi(x): #Buelengde-funksjonen som skal integreres return np.sqrt(1+df(x)**2) def trapesmetoden(): #trapesmetoden tellevariabelen_min = 0 for i in range(N-1): x_i = 0 + Dx*i #0 er startpunktet vi integrerer fra tellevariabelen_min += (phi(x_i + Dx) + phi(x_i))*Dx/2 #Trapesmetode-definisjonen return tellevariabelen_min #Vi fant bare buelengden av en fjerdedel av ellipsen, så vi ganger med 4 print(trapesmetoden()*4)
Trapesmetoden med kommentarer i koden av Ylva
Trapesmetoden med kommentarer i koden av Ylva
- NumeriskDifLikning.py
# -*- coding: utf-8 -*- """ Created on Tue Nov 8 11:25:09 2022 @author: Ylva """ import numpy as np a = 0.00001 #start-x-verdi b = np.pi #slutt-x-verdi N = 10000 #antall x-punkter dX = (b - a)/N #lengden mellom punktene def sinc(x): return np.sin(x)/(x) #sinc kan også defineres som sin(pi*x)/(pi*x). Livet er trist def trapes(f): #MERK: denne funksjonen tar inn en funksjon! KULT! area = 0 for i in range(N): area += 1/2 * (f(a + dX * i) + f(a + dX * (i + 1))) * dX #Her går det ann å skrive x = a + dX*i og legge det inn #i funksjonen for å være enda tydeligere. return area print(trapes(sinc))
Riemann og trapesmetoden med kommentarer i koden av Seb
Riemann og trapesmetoden med kommentarer i koden av Seb
- NumeriskDifLikning.py
# -*- coding: utf-8 -*- """ Spyder Editor This is a temporary script file. """ import numpy as np def f(x): return np.exp(- x**2) #funksjonen vår a = 0 #start-x-verdi b = 1 #slutt-x-verdi n = 1000 #antall punkter på x res = 0 #variabel som lagrer summen "res" for "resultat" dx = (b-a)/n #Delta x x = np.zeros(n) #Våre x-verdier #alternativ: x = np.linspace(a,b,n) #Trenger da ikke x i for-løkke for i in range(0,n): x[i] = a + i*dx #MERK: starter i a res += f(x[i]) #Legger til rektangelets høyde #Skal egentlig også gange med dx, men tar det senere #for å spare prosessorkraft res *= dx #ganger med dx print("Riemann:",res) #Trapesmetoden på Seb-måten: res = 0 dx = (b-a)/n #Delta x x = np.linspace(a,b,n) for i in range(0,n-1): #antar vi brukte linspace tidligere res += (f(x[i])+f(x[i+1]))/2 res *= dx print("trapes:",res)
Numeriske metoder med kommentarer i koden av Mathias
Numeriske metoder med kommentarer i koden av Mathias
- NumeriskDifLikning.py
import numpy as np from tqdm import tqdm #Kun for å få progress bar, fordi det ser kult ut import matplotlib.pyplot as plt # g(x) er det som står på høyre side av likningen når x' står alene på venstre side. def g(x): return -(1/x**2)*((np.e**(1/x))/((np.e**(1/x)-1)**2))*(x-100) #Siste tall (100) er T_k. #Vi definerer den derriverte av g(x) siden den brukes i noen av metodene. def gDeriv(x): return (g(x+0.0001)-g(x-0.0001))/0.0002 x0 = 1 # x(0) maxT = 10 #hvor stor definisjonsmengden til grafen vi skal plotte er steps = 10 #hvor mange skritt vi tar, høyere verdi = bedre resultat men saktere h = maxT/steps #Lengden av hvert skritt def eulersMethod(): x = [x0] #Lager en liste med y-verdier til grafen til x(t), første element er initialverdien x0 ts = [0] #lager en liste med x-verdier for n in tqdm(range(steps)): ts.append((n+1)*h) #Listen med x-verdier starter på 0, og for hver iterasjon legger vi på (n+1)*h, # slik at den ender opp som [0, 1h, 2h, 3h, 4h ... ] x.append(x[n] + h*g(x[n])) #Her bruker vi eulers eksplisitte metode til å finne hva neste x er, og legger # den til i lista som heter x. return ts, x #Her returneres de to listene slik at de kan plottes (se bunnen av koden) def eulerImplicitMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) #Newtons metode #Her brukes newtons metode til å finne x_(n+1), ved å løse likningen x_(n+1) = x_n + h*g(x_(n+1)). #1: Skriv om likningen til 0 = -x_(n+1) + x_n + h*g(x_(n+1)), det som står på høyre side er nå f(x) funksjonen vi bruker i newtons metode. # altså, f(x) = -x_(n+1) + x_n + h*g(x_(n+1)) #2: Finn f'(x) ved å derrivere det over, da får vi f'(x) = h*g'(x_(n+1)) - 1 #3: Hvis vi nå setter inn f(x) og f'(x) i formelen for newtons metode, får vi at det man må gjøre hver # iterasjon er: x_(n+1) = x_(n+1) - (-x_(n+1) + x_n + h*g(x_(n+1))) / (h*g'(x_(n+1)) - 1) nextX = x[n] #Denne variabelen er x_(n+1) (det er ikke lov å bruke x_(n+1) som variabelnavn i python... ) for i in range(100): lastX = nextX #Dette er kun for å sjekke om newtons metode har konvergert nextX = nextX - ((-nextX+x[n]+h*g(nextX))/(h*gDeriv(nextX)-1)) #Her gjør vi iterasjonen if abs(nextX - lastX) < 0.000000001: break #Dersom den har konvergert avslutter vi loopen (for å ikke bruke unødvendig lang tid) x.append(nextX) #Nå når vi har funnet x_(n+1) med newtons metode legger vi den til i lista x return ts, x def trapesMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) #Newtons Metode nextX = x[n] for i in range(100): lastX = nextX nextX = nextX - ((-nextX+x[n]+(h/2)*g(x[n])+(h/2)*g(nextX))/((h/2)*gDeriv(nextX)-1)) if abs(nextX - lastX) < 0.000000001: break x.append(nextX) return ts, x def heunsMethod(): x = [x0] ts = [0] for n in tqdm(range(steps)): ts.append(n*h+h) x.append(x[n] + (h/2)*(g(x[n]) + g(x[n] + h*g(x[n])))) return ts, x #Her plottes det en løsning med eulers metode xs, ys = heunsMethod() plt.plot(xs, ys, color="blue") #Her plottes det en løsning med trapesmetoden xs, ys = trapesMethod() plt.plot(xs, ys, color="red") #Her endrer vi steps til et veldig høyt tall og plotter løsning med heuns metode for å få en "fasit" på hvordan #grafen skal se ut, slik at vi kan se hvilken av eulers metode og trapesmetoden som er best. steps = 1000000 h = maxT/steps xs, ys = heunsMethod() plt.plot(xs, ys, color="green") plt.show()
Øvingstime 16. september 2022, numeriske metoder, oppgave 13 og 14 uke 37
Øvingstime 16. september 2022, numeriske metoder, oppgave 13 og 14 uke 37
Oppgave 13:
from math import exp import matplotlib.pyplot as plt def g(T): return 2 - T T_0 = 1 / 10 h = 0.01 n = 1000 T_eksplisitt = [T_0] t = [0] x = [0, 1, 2, 3] x[2] for i in range(n): # Euler eksplisitt T_eksplisitt.append(T_eksplisitt[i] + h * g(T_eksplisitt[i])) t.append((i + 1) * h) plt.plot(t, T_eksplisitt) plt.show()
Oppgave 14:
from math import exp import matplotlib.pyplot as plt def g(T): return (T_k - T) * 1 / T ** 2 * exp(1 / T) / (exp(1 / T) - 1) ** 2 T_k = 2 T_0 = 1 / 10 n = 1000 h = 0.01 T_eksplisitt = [T_0] T_heuns = [T_0] x = [0] for i in range(n): # Euler eksplisitt T_eksplisitt.append(T_eksplisitt[i] + h * g(T_eksplisitt[i])) # Heuns metode T_heuns.append(T_heuns[i] + h * ((g(T_heuns[i]) + g(T_heuns[i] + h * g(T_heuns[i]))) / 2)) x.append((i + 1) * h) plt.plot(x, T_eksplisitt) plt.plot(x, T_heuns) plt.show()
Forelesning 9. september 2022, øl-graf, numeriske metoder, derav euler eksplisitt og heuns metode
Forelesning 9. september 2022, øl-graf, numeriske metoder, derav euler eksplisitt og heuns metode
Øl-graf: https://www.desmos.com/calculator/alhga7sjdb
#%% Den tingen som står på toppen # -*- coding: utf-8 -*- """ Created on Thu Sep 8 15:18:33 2022 @author: Sebastian Westerlund Kalland """ #%% Imports import numpy as np import matplotlib.pyplot as plt #%% Felles variabler N = 10 L = 1 h = L/N a = 2 t = np.linspace(0,L,N+1) #%% Vanlig graf def x(t): return np.exp(a*t) #%% dx def dx(x): # x derivert er lik a ganger x. Altså, denne funksjonen representerer x-derivert ved en verdi x return a*x #%% Euler eksplisitt x_n_exp = np.zeros(N+1) x_n_exp[0] = 1 for i in range(N): x_n_exp[i+1] = x_n_exp[i] + dx(x_n_exp[i])*h #%% Euler implisitt x_n_imp = np.zeros(N+1) x_n_imp[0] = 1 for i in range(N): #x_n_imp[i+1] = x_n_imp[i] + h*dx(x_n_imp[i+1]) #LØS FOR x_n_imp[n+1] #Her løst for dx = a*x: x_n_imp[i+1] = x_n_imp[i]/(1-a*h) #%% Trapesmetoden x_n_tra = np.zeros(N+1) x_n_tra[0] = 1 for i in range(N): #x_n_tra[i+1] = x_n_tra[i] + h*(dx(x_n_tra[i]) + dx(x_n_tra[i+1]))/2 #LØS FOR x_n_tra[n+1] #Her løst for dx = a*x: x_n_tra[i+1] = x_n_tra[i]*(1+h*a/2)/(1-a*h/2) #%% Midtpunktmetoden x_n_midt = np.zeros(N+1) x_n_midt[0] = 1 for i in range(N): #x_n_midt[i+1] = x_n_midt[i] + h*dx((x_n_midt[i] + x_n_midt[i+1])/2) #LØS FOR x_n_midt[n+1] #Her løst for dx = a*x: x_n_midt[i+1]= x_n_midt[i]*(1+h*a/2)/(1-h*a/2) #I akkurat dette tilfellet blir midtpunktmetoden og trapesmetoden like. Kan du se hvorfor? #%% Heuns metode x_n_H = np.zeros(N+1) x_n_H[0] = 1 for i in range(N): estimat = dx(x_n_H[i] + dx(x_n_H[i])*h) x_n_H[i+1] = x_n_H[i] + h*(dx(x_n_H[i]) + estimat)/2 #%% Masse figurting, bare ignorer plt.figure(dpi=300) plt.rc('axes',labelsize=12) plt.xlabel('$t$') plt.ylabel('$x$') plt.tick_params(axis="both", length=3) plt.minorticks_on() plt.grid(which="minor", axis="both", linestyle=":") plt.grid() #%% Plotting plt.plot(t, x(t), label='$x(t)=e^{at}$') plt.plot(t, x_n_exp, label='Euler eksplisitt for $\dot{x}=ax$') plt.plot(t, x_n_imp, label='Euler implisitt...') plt.plot(t, x_n_tra, label='Trapesmetoden...') plt.plot(t, x_n_midt, label='Midtpunktmetoden...') plt.plot(t, x_n_H, label='Heuns metode...') #%% liten ekstra plotte-ting plt.legend()
En veldig avansert realisering av Newtons metode, inspirert av Truls
En veldig avansert realisering av Newtons metode, inspirert av Truls
# -*- coding: utf-8 -*- """ Created on Wed Sep 7 17:41:55 2022 @author: Sebastian Westerlund Kalland og Truls """ import numpy as np def newtonsmetode(func, der_func, x=1, n=10, d=0): ''' Parameters ---------- func : String 0 = "func". This is a function expressed as string using x as its input. Example: "x - np.cos(x)" der_func: String Derivative of f. x : float Starting value. Default 1 n : integer Maximum number of iterations. Default 10. d : float Accepted error margin before quitting the iteration prematurely. Default 0, meaning no errors allowed. Returns ------- x : Value after n iterations of Newton's method ''' f = lambda x: eval(func) df = lambda x: eval(der_func) for i in range(n): x_pre = x x = x - (f(x)/df(x)) if abs(x_pre-x)<d: print("x =",x,"\tafter",i,"iteration, with an error margin of",d) return x if abs(x_pre-x)==0: print("x =",x,"\tafter",i,"iterations, the computer cannot represent x more accurately.") return x print("x =",x,"\tafter",n,"iterations.") return x newtonsmetode("x-np.cos(x)", "np.sin(x)+1", 1, 20, 1e-6) newtonsmetode("x-np.cos(x)", "np.sin(x)+1", 1, 3) newtonsmetode("x-np.cos(x)", "np.sin(x)+1")
Øvingstime 6. september 2022, Newtons metode \(~x^2=cos(x)\)
Øvingstime 6. september 2022, Newtons metode \(~x^2=cos(x)\)
# -*- coding: utf-8 -*- """ Created on Tue Sep 6 11:22:31 2022 @author: Sebastian Westerlund Kalland """ import numpy as np x = 1 for i in range(100): forrige_x = x x = np.sqrt(np.cos(x)) print(i, x) if abs(forrige_x-x) < 0.000001: break def f(x): return np.cos(x) - x**2 def df(x): return -np.sin(x) - 2*x x = 1 for i in range(10): forrige_x = x x = x - f(x)/df(x) print(i, x) if abs(forrige_x-x) < 0.000001: break #while-eksempel for de som er litt mer spenstig x = 1 forrige_x = 2 while abs(forrige_x-x) >= 0.000001: forrige_x = x x = x - f(x)/df(x) print(x)
Code for visualizing Taylor Expansions
Code for visualizing Taylor Expansions
import numpy as np from math import factorial, pi from sympy import diff, Symbol, lambdify, sin, cos from matplotlib import pyplot as plt # Sets variable x = Symbol('x') def taylor(f, n: int, a: int, x_values: list[float]): """ ´n´: Degree of taylor polynomial ´a´: X-value at which our approximation is the most exact """ num_values = len(x_values) # Fills in values for f(a) y_values = np.ones(num_values) * lambdify(x, f, "numpy")(np.array([a]))[0] # Differentiates function n times and adds it all up for i in range(n): f = f.diff(x) f_prime_a = lambdify(x, f, "numpy")([a])[0] y_values += f_prime_a / factorial(i + 1) * lambdify(x, (x - a) ** (i + 1), "numpy")(x_values) return y_values def main(): # Defines function we want to approximate f = cos(x) x_values = np.linspace(-2 * pi, 2 * pi, 100) y_values = taylor(f, 4, 0, x_values) plt.plot(x_values, lambdify(x, f, "numpy")(x_values)) plt.plot(x_values, y_values) plt.ylim([-5, 5]) plt.show() if __name__ == '__main__': main()