Całkowanie numeryczne metodą Simpsona
superdurszlak
Wstęp
Metoda Simpsona jest bardziej zaawansowaną metodą obliczania całki przez przybliżenie pola pod wykresem, która od metody trapezów różni się stopniem wielomianu, którym przybliżana jest funkcja w poszczególnych przedziałach - o ile w metodzie trapezów wielomian był pierwszego stopnia (f. liniowa) przechodzący przez 2 punkty, to w metodzie Simpsona stosujemy wielomian interpolacyjny drugiego stopnia (parabola) przechodzący przez 3 punkty.
Z tego względu dla 2N + 1 punktów (czyli 2N przedziałów) funkcja będzie przybliżana przez N wielomianów:
Całkę przybliżamy stosując następujący wzór:
Gdzie:
Ponieważ obliczenie całki wprost z tego wzoru wymagałoby (pomijając obliczanie xi) 3N - 1 dodawań, 2N mnożeń oraz N dzieleń, możemy dokonać przekształcenia, pozwalającego zredukować liczbę operacji arytmetycznych do 2N dodawań, 3 mnożeń i 1 dzielenia:
Implementacja w Pythonie
Dla przejrzystości pominiemy walidację argumentów i obsługę błędów.
Postać oryginalna
def simpson_integration_simple(my_func, a, b, n):
# Szerokość pojedynczego przedziału
delta_x = (b-a)/n
# x_i liczymy każdorazowo od nowa by uniknąć kumulowania
# się błędów numerycznych - kosztem dużej ilości mnożeń
total = 0
# pamiętamy że n = 2N
for i in range(0, n, 2):
x = a + delta_x * 2 * i
total += delta_x * (my_func(x) + 4 * my_func(x + delta_x) + my_func(x + 2 * delta_x) / 3
return total
# Wywołujemy naszą funkcję całkującą, przekazując wzór całkowanej funkcji jako lambdę
integral = simpson_integration_simple(lambda x: x**2, 0.0, 1.0, 100)
Postać przekształcona
def simpson_integration_modified(my_func, a, b, n):
# Szerokość pojedynczego przedziału
delta_x = (b-a)/n
total = my_func(a) + my_func(b)
subtotal_sum_1 = 0
subtotal_sum_2 = 0
# pierwsza suma, pamiętamy że n = 2N
for i in range(0, n, 2):
x = a + i * delta_x
subtotal_sum_1 += my_func(x)
# druga suma, pamiętamy że n = 2N
for i in range(1, n-1, 2):
x = a + i * delta_x
subtotal_sum_2 += my_func(x)
return delta_x * (total + 4 * subtotal_sum_1 + 2 * subtotal_sum_2) / 3
# Wywołujemy naszą funkcję całkującą, przekazując wzór całkowanej funkcji jako lambdę
integral = simpson_integration_modified(lambda x: x**2, 0.0, 1.0, 100)
Przykłady
Przykład 1: funkcja kwadratowa
TODO: przedstawić przykład krok po kroku z wynikami
Przykład 2: funkcja cosinus
TODO: przedstawić przykład krok po kroku z wynikami