3.5
Programmering av integrasjon

3.5 Programmering av integrasjon

Implementere integrasjonsalgoritmar i Python.

55 min
19 oppgaver
PythonProgrammeringAlgoritmarNumerisk metode
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 19 oppgaver
Kapitlets plass i kurset

I dette kapitlet skal vi bruke programmering til å rekne ut bestemte integral numerisk. Sjølv om mange integral kan løysast analytisk, finst det svært mange funksjonar som ikkje har ein lukka antiderivert. Då må vi ty til numeriske metodar.

Vi skal implementere tre klassiske metodar:
- Rektangelmetoden (den enklaste)
- Trapesmetoden (betre nøyaktigheit)
- Simpsons metode (svært god nøyaktigheit)

I tillegg skal vi sjå på desse metodane, som er fordjuping (utanfor læreplanen):
- Monte Carlo-integrasjon (stokastisk metode)
- Adaptiv integrasjon (automatisk steglengdejustering)
- Romberg-integrasjon (ekstrapolasjon)
- Gauss-kvadratur (optimal punktplassering)
- Dobbeltintegral (integrasjon i 2D)

Vi bruker Python-biblioteka NumPy og SciPy for effektiv implementering, og Matplotlib for visualisering.

Rektangelmetoden

Den enklaste tilnærminga til numerisk integrasjon er å dele opp arealet under kurva i rektangel. Idéen er at summen av areala til rektangla tilnærmar det bestemte integralet.

Rektangelmetoden (venstrepunkt)
For å tilnærme ∫abf(x) dx\displaystyle\int_a^b f(x)\,dx deler vi intervallet [a,b][a, b] i nn like store delintervall med breidd h=b−an\displaystyle h = \frac{b-a}{n}.

Venstrepunktsformelen:
∫abf(x) dx≈h∑i=0n−1f(xi)=h⋅[f(x0)+f(x1)+⋯+f(xn−1)]\begin{aligned} &\int_a^b f(x)\,dx \approx h \sum_{i=0}^{n-1} f(x_i) \\ = {}&h \cdot [f(x_0) + f(x_1) + \cdots + f(x_{n-1})] \end{aligned}

der xi=a+i⋅hx_i = a + i \cdot h for i=0,1,2,…,n−1i = 0, 1, 2, \ldots, n-1.

Midtpunktsformelen (ofte meir nøyaktig):
∫abf(x) dx≈h∑i=0n−1f(xi+h2)\int_a^b f(x)\,dx \approx h \sum_{i=0}^{n-1} f\left(x_i + \frac{h}{2}\right)

✏️Implementere rektangelmetoden i Python

Skriv ein Python-funksjon som reknar ut ∫01x2 dx\displaystyle\int_0^1 x^2\,dx ved hjelp av rektangelmetoden med n=1000n = 1000 delintervall. Den eksakte verdien er 13≈0,333333\displaystyle \frac{1}{3} \approx 0{,}333333.

def rektangelmetoden(f, a, b, n):
    """
    Bereknar det bestemte
    integralet av f frå a til b
    ved hjelp av rektangelmetoden
    (venstrepunkt).

    Parametrar:
        f: funksjonen som skal
        integrerast
        a: nedre grense
        b: øvre grense
        n: antal delintervall

    Returnerer:
        Tilnærma verdi av
        integralet
    """
    h = (b - a) / n
    total = 0

    for i in range(n):
        x_i = a + i * h
        total += f(x_i)

    return h * total


# Definer funksjonen f(x) = x^2
def f(x):
    return x**2


# Berekn integralet
resultat = rektangelmetoden(
    f, 0, 1, 1000
)
print(
    "Tilnærma verdi:"
    f" {resultat:.6f}"
)
print(f"Eksakt verdi: {1/3:.6f}")
print(
    "Feil:"
    f" {abs(resultat - 1/3):.6f}"
)

Utskrift:

Tilnærma verdi: 0.332833
Eksakt verdi: 0.333333
Feil: 0.000500

Feilen er ca. 0,00050{,}0005, noko som svarer til ein relativ feil på ca. 0,15 %0{,}15\,\%.

Svar: Rektangelmetoden gir ≈0,332833\approx 0{,}332833, medan den eksakte verdien er 13≈0,333333\displaystyle \frac{1}{3} \approx 0{,}333333. Feilen er ca. 0,00050{,}0005.

Midtpunktsmetoden
Midtpunktsmetoden bruker funksjonsverdien i midten av kvart delintervall:

∫abf(x) dx≈h∑i=0n−1f(a+(i+12)h)\int_a^b f(x)\,dx \approx h \sum_{i=0}^{n-1} f\left(a + \left(i + \frac{1}{2}\right)h\right)

Midtpunktsmetoden har faktisk dobbelt så god konvergensorden som venstrepunktsmetoden: O(h2)O(h^2) i staden for O(h)O(h).

✏️Samanlikning av venstre- og midtpunktsmetoden

Samanlikn venstrepunktsmetoden og midtpunktsmetoden for ∫01x2 dx\displaystyle\int_0^1 x^2\,dx.

def venstrepunkt(f, a, b, n):
    h = (b - a) / n
    return h * sum(
        f(a + i * h)
        for i in range(n)
    )


def midtpunkt(f, a, b, n):
    h = (b - a) / n
    return h * sum(
        f(a + (i + 0.5) * h)
        for i in range(n)
    )


def f(x):
    return x**2


eksakt = 1 / 3

print(
    "n\t\tVenstrepunkt\tMidtpunkt"
)
print("-" * 50)
for n in [10, 100, 1000]:
    v = venstrepunkt(f, 0, 1, n)
    m = midtpunkt(f, 0, 1, n)
    print(
        f"{n}\t\t"
        f"{abs(v - eksakt):.2e}\t"
        f"{abs(m - eksakt):.2e}"
    )

Utskrift:

n		Venstrepunkt	Midtpunkt
--------------------------------------------------
10		4.83e-02	8.33e-04
100		4.98e-03	8.33e-06
1000		5.00e-04	8.33e-08

Midtpunktsmetoden er dramatisk meir nøyaktig!

Svar: Med n=1000n = 1000 er feilen ca. 5,0⋅10−45{,}0 \cdot 10^{-4} med venstrepunktsmetoden og ca. 8,3⋅10−88{,}3 \cdot 10^{-8} med midtpunktsmetoden.

📝Oppgave 3.5.1

Implementer rektangelmetoden for å rekne ut ∫0πsin⁡(x) dx\displaystyle\int_0^{\pi} \sin(x)\,dx.

Den eksakte verdien er 22.

a) Bruk n=100n = 100 delintervall og finn tilnærma verdi.

b) Bruk n=1000n = 1000 delintervall og samanlikn feilen.

c) Kor mange delintervall treng du for at feilen skal vere mindre enn 0,00010{,}0001?

Oppgave 3.5.1
Medium
Python
Loading...

Trapesmetoden

Trapesmetoden gir betre nøyaktigheit enn rektangelmetoden ved å tilnærme kurva med trapes i staden for rektangel. Eit trapes fangar opp meir av forma til kurva.

Trapesmetoden
For å tilnærme ∫abf(x) dx\displaystyle\int_a^b f(x)\,dx med trapesmetoden bruker vi formelen:

∫abf(x) dx≈h2[f(x0)+2f(x1)+2f(x2)+⋯+2f(xn−1)+f(xn)]\begin{aligned} &\int_a^b f(x)\,dx \\ \approx {}&\frac{h}{2}\Big[f(x_0) + 2f(x_1) + 2f(x_2) \\ &\quad {} + \cdots + 2f(x_{n-1}) + f(x_n)\Big] \end{aligned}

der h=b−an\displaystyle h = \frac{b-a}{n} og xi=a+i⋅hx_i = a + i \cdot h.

Alternativt kan dette skrivast som:
∫abf(x) dx≈h[f(a)+f(b)2+∑i=1n−1f(xi)]\int_a^b f(x)\,dx \approx h\left[\frac{f(a) + f(b)}{2} + \sum_{i=1}^{n-1} f(x_i)\right]

📜Feilestimatet for trapesmetoden
Feilen i trapesmetoden er gitt ved:
ET=−(b−a)312n2f′′(ξ)E_T = -\frac{(b-a)^3}{12n^2} f''(\xi)
for ein eller annan ξ∈[a,b]\xi \in [a, b].

Dette betyr at feilen avtek som O(1/n2)O(1/n^2) når nn aukar, altså dobbelt så raskt som rektangelmetoden (O(1/n)O(1/n)).

✏️Implementere trapesmetoden i Python

Skriv ein Python-funksjon for trapesmetoden og rekn ut ∫01ex dx\displaystyle\int_0^1 e^x\,dx. Den eksakte verdien er e−1≈1,71828e - 1 \approx 1{,}71828.

import math


def trapesmetoden(f, a, b, n):
    """
    Bereknar det bestemte
    integralet av f frå a til b
    ved hjelp av trapesmetoden.
    """
    h = (b - a) / n

    # Første og siste ledd (med
    # vekt 1/2)
    total = (f(a) + f(b)) / 2

    # Alle indre punkt (med vekt
    # 1)
    for i in range(1, n):
        x_i = a + i * h
        total += f(x_i)

    return h * total


def f(x):
    return math.exp(x)


eksakt = math.e - 1

# Test med forskjellige n
for n in [10, 100, 1000]:
    resultat = trapesmetoden(
        f, 0, 1, n
    )
    feil = abs(resultat - eksakt)
    print(
        f"n = {n:4d}:"
        f" {resultat:.8f}, feil ="
        f" {feil:.2e}"
    )

Utskrift:

n =   10: 1.71971349, feil = 1.43e-03
n =  100: 1.71829615, feil = 1.43e-05
n = 1000: 1.71828197, feil = 1.43e-07

Merk at feilen reduserast med faktor 100 når nn aukar med faktor 10, som stadfestar O(1/n2)O(1/n^2)-oppførselen.

Svar: Trapesmetoden gir 1,719713491{,}71971349 med n=10n = 10 (feil 1,43⋅10−31{,}43 \cdot 10^{-3}) og 1,718281971{,}71828197 med n=1000n = 1000 (feil 1,43⋅10−71{,}43 \cdot 10^{-7}).

📝Oppgave 3.5.2

Samanlikn rektangelmetoden og trapesmetoden for integralet ∫131x dx\displaystyle \displaystyle\int_1^3 \frac{1}{x}\,dx.

Den eksakte verdien er ln⁡(3)≈1,0986\ln(3) \approx 1{,}0986.

a) Implementer begge metodane.

b) Rekn ut integralet med n=100n = 100 for begge metodane.

c) Kor mange gonger meir nøyaktig er trapesmetoden?

Oppgave 3.5.2
Medium
Python
Loading...

Simpsons metode

Simpsons metode tilnærmar kurva med parablar (andregradsfunksjonar) i staden for rette linjer. Dette gir endå betre nøyaktigheit enn trapesmetoden, særleg for glatte funksjonar.

Simpsons metode (1/3-regelen)
For å tilnærme ∫abf(x) dx\displaystyle\int_a^b f(x)\,dx med Simpsons metode krev vi at nn er eit partal. Formelen er:

∫abf(x) dx≈h3[f(x0)+4f(x1)+2f(x2)+4f(x3)+2f(x4)+⋯+4f(xn−1)+f(xn)]\begin{aligned} &\int_a^b f(x)\,dx \\ \approx {}&\frac{h}{3}\Big[f(x_0) + 4f(x_1) + 2f(x_2) + 4f(x_3) \\ &\quad {} + 2f(x_4) + \cdots + 4f(x_{n-1}) + f(x_n)\Big] \end{aligned}

der h=b−an\displaystyle h = \frac{b-a}{n}.

Mønsteret for koeffisientane er: 1,4,2,4,2,…,4,2,4,11, 4, 2, 4, 2, \ldots, 4, 2, 4, 1.

📜Feilestimatet for Simpsons metode
Feilen i Simpsons metode er gitt ved:
ES=−(b−a)5180n4f(4)(ξ)E_S = -\frac{(b-a)^5}{180n^4} f^{(4)}(\xi)
for ein eller annan ξ∈[a,b]\xi \in [a, b].

Dette betyr at feilen avtek som O(1/n4)O(1/n^4), altså mykje raskare enn trapesmetoden.

Bemerkelsesverdig: Simpsons metode er eksakt for polynom av grad 3 eller lågare!

✏️Implementere Simpsons metode i Python

Implementer Simpsons metode og rekn ut ∫0πsin⁡(x) dx\displaystyle\int_0^{\pi} \sin(x)\,dx med n=10n = 10. Samanlikn med trapesmetoden.

import math


def simpson(f, a, b, n):
    """
    Bereknar det bestemte
    integralet av f frå a til b
    ved hjelp av Simpsons metode.
    Krev at n er eit partal.
    """
    if n % 2 != 0:
        raise ValueError(
            "n må vere eit partal"
            " for Simpsons metode"
        )

    h = (b - a) / n

    # Første og siste ledd
    total = f(a) + f(b)

    # Odde indeksar (koeffisient
    # 4)
    for i in range(1, n, 2):
        total += 4 * f(a + i * h)

    # Like indeksar (koeffisient
    # 2), unntatt 0 og n
    for i in range(2, n, 2):
        total += 2 * f(a + i * h)

    return (h / 3) * total


def trapesmetoden(f, a, b, n):
    h = (b - a) / n
    total = (f(a) + f(b)) / 2
    for i in range(1, n):
        total += f(a + i * h)
    return h * total


def f(x):
    return math.sin(x)


eksakt = 2

# Samanlikn med n = 10
trapes_10 = trapesmetoden(
    f, 0, math.pi, 10
)
simpson_10 = simpson(
    f, 0, math.pi, 10
)

print(f"Eksakt verdi: {eksakt}")
print(
    "Trapes (n=10): "
    f" {trapes_10:.10f}, feil ="
    f" {abs(trapes_10 - eksakt):.2e}"
)
print(
    "Simpson (n=10):"
    f" {simpson_10:.10f}, feil ="
    f" {abs(simpson_10 - eksakt):.2e}"
)

Utskrift:

Eksakt verdi: 2
Trapes (n=10):  1.9835235375, feil = 1.65e-02
Simpson (n=10): 2.0001095173, feil = 1.10e-04

Med berre n=10n = 10 har Simpsons metode ein feil på ca. 1,1⋅10−41{,}1 \cdot 10^{-4}, medan trapesmetoden har feil på ca. 0,0170{,}017. Simpsons metode er ca. 150 gonger meir nøyaktig.

Svar: Med n=10n = 10 gir Simpsons metode 2,000112{,}00011 (feil ca. 1,1⋅10−41{,}1 \cdot 10^{-4}) og trapesmetoden 1,983521{,}98352 (feil ca. 0,0170{,}017).

📝Oppgave 3.5.3

Bruk Simpsons metode til å rekne ut ∫01e−x2 dx\displaystyle\int_0^1 e^{-x^2}\,dx.

Dette integralet har ingen lukka antiderivert, så vi må bruke numeriske metodar!

a) Implementer Simpsons metode.

b) Finn ein tilnærma verdi med n=100n = 100.

c) Den "eksakte" verdien (rekna ut med mange desimalar) er ca. 0,7468240{,}746824. Kva er feilen?

Oppgave 3.5.3
Vanskelig
Python
Loading...

Simpsons 3/8-regel (fordjuping, utanfor læreplanen)

Det finst òg ein variant av Simpsons metode som bruker kubisk interpolasjon over tre delintervall.

Simpsons 3/8-regel
Simpsons 3/8-regel tilnærmar integralet ved å dele i 3 delintervall:

∫abf(x) dx≈3h8[f(x0)+3f(x1)+3f(x2)+f(x3)]\int_a^b f(x)\,dx \approx \frac{3h}{8}\left[f(x_0) + 3f(x_1) + 3f(x_2) + f(x_3)\right]

For nn delintervall (der nn er deleleg med 3):
∫abf(x) dx≈3h8[f(x0)+3f(x1)+3f(x2)+2f(x3)+3f(x4)+⋯+f(xn)]\begin{aligned} &\int_a^b f(x)\,dx \\ \approx {}&\frac{3h}{8}\Big[f(x_0) + 3f(x_1) + 3f(x_2) \\ &\quad {} + 2f(x_3) + 3f(x_4) + \cdots + f(x_n)\Big] \end{aligned}

Mønsteret for koeffisientane er: 1,3,3,2,3,3,2,…,3,3,11, 3, 3, 2, 3, 3, 2, \ldots, 3, 3, 1.

Bruke NumPy og SciPy for integrasjon

I praksis treng vi ikkje alltid å implementere integrasjonsmetodar frå botnen av. Python-biblioteka NumPy og SciPy har ferdige, optimaliserte funksjonar for numerisk integrasjon.

SciPy integrate-modulen
scipy.integrate inneheld fleire funksjonar for numerisk integrasjon:

- quad(f, a, b): Adaptiv integrasjon med høg nøyaktigheit. Returnerer (resultat, feilestimering).
- trapezoid(y, x): Trapesmetoden på diskrete datapunkt.
- simpson(y, x): Simpsons metode på diskrete datapunkt.
- dblquad(f, a, b, g, h): Dobbeltintegral.
- tplquad(f, a, b, g, h, q, r): Trippelintegral.
- fixed_quad(f, a, b, n): Gauss-Legendre-kvadratur med nn punkt.

NumPy gir òg numpy.trapezoid(y, x) for enkel trapesintegrasjon (i eldre NumPy-versjonar heiter ho numpy.trapz).

✏️Integrasjon med SciPy

Bruk SciPy til å rekne ut ∫0∞e−x2 dx=π2\displaystyle \displaystyle\int_0^{\infty} e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}.

import numpy as np
from scipy import integrate


# Definer funksjonen
def f(x):
    return np.exp(-(x**2))


# Berekn integralet frå 0 til
# uendeleg
resultat, feil = integrate.quad(
    f, 0, np.inf
)

eksakt = np.sqrt(np.pi) / 2

print(
    "SciPy quad:  "
    f" {resultat:.10f}"
)
print(
    f"Eksakt verdi: {eksakt:.10f}"
)
print(
    "Feilestimering frå quad:"
    f" {feil:.2e}"
)
print(
    "Faktisk feil:"
    f" {abs(resultat - eksakt):.2e}"
)

Utskrift:

SciPy quad:   0.8862269255
Eksakt verdi: 0.8862269255
Feilestimering frå quad: 7.10e-09
Faktisk feil: 0.00e+00

Merk at quad handterer uendelege grenser automatisk og gir ei feilestimering!

Svar: quad gir 0,88622692550{,}8862269255, som er lik π2\displaystyle \frac{\sqrt{\pi}}{2} med ti desimalar.

✏️Trapesmetoden med NumPy på datapunkt

Gitt målepunkt (xi,yi)(x_i, y_i) frå eit eksperiment, rekn ut det tilnærma arealet under kurva.

import numpy as np

# Simulerte måledata (f.eks.
# hastigheit over tid)
# tid i sekund
t = np.array([0, 1, 2, 3, 4, 5])
# hastigheit i m/s
v = np.array([0, 5, 8, 10, 9, 6])

# Berekn tilbakelagd strekning
# (integral av hastigheit)
strekning = np.trapezoid(v, t)

print(f"Tidspunkt: {t}")
print(f"Hastigheiter: {v}")
print(
    "Tilbakelagd strekning:"
    f" {strekning:.1f} meter"
)

Utskrift:

Tidspunkt: [0 1 2 3 4 5]
Hastigheiter: [ 0  5  8 10  9  6]
Tilbakelagd strekning: 35.0 meter

Dette er svært nyttig når vi har diskrete måledata i staden for ein analytisk funksjon.

Svar: Tilbakelagd strekning er ca. 35,035{,}0 m.

📝Oppgave 3.5.4

Bruk SciPy til å rekne ut følgjande integral:

a) ∫0111+x2 dx=π4\displaystyle \displaystyle\int_0^1 \frac{1}{1+x^2}\,dx = \frac{\pi}{4}

b) ∫1eln⁡(x) dx=1\displaystyle\int_1^e \ln(x)\,dx = 1

c) ∫0π/2cos⁡2(x) dx=π4\displaystyle \displaystyle\int_0^{\pi/2} \cos^2(x)\,dx = \frac{\pi}{4}

Samanlikn med dei eksakte verdiane.

Oppgave 3.5.4
Medium
Python
Loading...

Visualisering av numerisk integrasjon

Ein viktig del av å forstå numeriske metodar er å visualisere kva som skjer. Med Matplotlib kan vi teikne funksjonen og rektangla/trapesa som blir brukte til å tilnærme arealet.

✏️Visualisere rektangelmetoden

Lag ei visualisering som viser rektangla som blir brukte i rektangelmetoden for f(x)=x2f(x) = x^2 på [0,2][0, 2] med n=8n = 8 delintervall.

import numpy as np
import matplotlib.pyplot as plt


def f(x):
    return x**2


a, b, n = 0, 2, 8
h = (b - a) / n

# Lag figur
fig, ax = plt.subplots(
    figsize=(10, 6)
)

# Tegn funksjonen
x_smooth = np.linspace(a, b, 200)
ax.plot(
    x_smooth,
    f(x_smooth),
    'b-',
    linewidth=2,
    label='$f(x) = x^2$',
)

# Tegn rektanglene
for i in range(n):
    x_left = a + i * h
    rect = plt.Rectangle(
        (x_left, 0),
        h,
        f(x_left),
        fill=True,
        facecolor='lightblue',
        edgecolor='blue',
        alpha=0.7,
    )
    ax.add_patch(rect)

# Beregn tilnærmet integral
integral_approx = h * sum(
    f(a + i * h) for i in range(n)
)
integral_exact = 8 / 3

ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('y', fontsize=12)
ax.set_title(
    'Rektangelmetoden: n ='
    f' {n}\nTilnærmet:'
    f' {integral_approx:.4f},'
    ' Eksakt:'
    f' {integral_exact:.4f}'
)
ax.legend()
ax.grid(True, alpha=0.3)
ax.set_xlim(a - 0.1, b + 0.1)
ax.set_ylim(0, f(b) + 0.5)

plt.tight_layout()
plt.show()

Denne koden produserer ein figur som viser:
- Den blå kurva f(x)=x2f(x) = x^2
- Lyseblå rektangel som representerer tilnærminga
- Tittel med både tilnærma og eksakt verdi

✏️Visualisere trapesmetoden

Lag ei visualisering som viser trapesmetoden for f(x)=sin⁡(x)f(x) = \sin(x) på [0,π][0, \pi] med n=6n = 6 delintervall.

import numpy as np
import matplotlib.pyplot as plt


def f(x):
    return np.sin(x)


a, b, n = 0, np.pi, 6
h = (b - a) / n

fig, ax = plt.subplots(
    figsize=(10, 6)
)

# Tegn funksjonen
x_smooth = np.linspace(a, b, 200)
ax.plot(
    x_smooth,
    f(x_smooth),
    'b-',
    linewidth=2,
    label='$f(x) = \sin(x)$',
)

# Tegn trapesene
x_trap = [
    a + i * h
    for i in range(n + 1)
]
y_trap = [f(x) for x in x_trap]

for i in range(n):
    x_corners = [
        x_trap[i],
        x_trap[i + 1],
        x_trap[i + 1],
        x_trap[i],
    ]
    y_corners = [
        0,
        0,
        y_trap[i + 1],
        y_trap[i],
    ]
    ax.fill(
        x_corners,
        y_corners,
        alpha=0.3,
        color='green',
        edgecolor='darkgreen',
    )

# Marker punktene
ax.plot(
    x_trap,
    y_trap,
    'go',
    markersize=8,
)

# Beregn integralet
integral_approx = h * (
    (f(a) + f(b)) / 2
    + sum(
        f(a + i * h)
        for i in range(1, n)
    )
)

ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('y', fontsize=12)
ax.set_title(
    'Trapesmetoden: n ='
    f' {n}\nTilnærmet:'
    f' {integral_approx:.4f},'
    ' Eksakt: 2.0000'
)
ax.legend()
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
📝Oppgave 3.5.5

Lag ei visualisering som samanliknar rektangelmetoden, trapesmetoden og Simpsons metode for f(x)=x3f(x) = x^3 på [0,1][0, 1] med n=4n = 4.

Vis tre subplot side om side som illustrerer kvar metode, og rekn ut feilen for kvar.

Oppgave 3.5.5
Vanskelig
Python
Loading...

Monte Carlo-integrasjon (fordjuping, utanfor læreplanen)

Ei heilt anna tilnærming til numerisk integrasjon er Monte Carlo-metoden, som bruker tilfeldige tal. Idéen er enkel: kast tilfeldige punkt i eit rektangel og tel kor mange som landar under kurva.

Monte Carlo-integrasjon
For å tilnærme ∫abf(x) dx\displaystyle\int_a^b f(x)\,dx med Monte Carlo-metoden:

1. Generer NN tilfeldige xx-verdiar uniformt fordelte på [a,b][a, b].
2. Rekn ut gjennomsnittleg funksjonsverdi: fˉ=1N∑i=1Nf(xi)\displaystyle \bar{f} = \frac{1}{N}\sum_{i=1}^{N} f(x_i)
3. Multipliser med lengda til intervallet:

∫abf(x) dx≈(b−a)⋅fˉ=b−aN∑i=1Nf(xi)\int_a^b f(x)\,dx \approx (b-a) \cdot \bar{f} = \frac{b-a}{N}\sum_{i=1}^{N} f(x_i)

Fordelar:
- Enkel å implementere
- Skalerer godt til høgare dimensjonar
- Robust mot diskontinuitetar

Ulempe: Konvergerer langsamt, med feil ∼O(1/N)\sim O(1/\sqrt{N}).

✏️Monte Carlo-integrasjon i Python

Bruk Monte Carlo-metoden til å estimere π\pi ved å rekne ut ∫−111−x2 dx=π2\displaystyle \displaystyle\int_{-1}^{1} \sqrt{1-x^2}\,dx = \frac{\pi}{2}.

import numpy as np


def monte_carlo_integral(
    f, a, b, N
):
    """
    Bereknar integralet av f frå a
    til b
    ved hjelp av Monte Carlo-
    metoden.
    """
    # Generer N tilfeldige
    # x-verdiar i [a, b]
    x_random = np.random.uniform(
        a, b, N
    )

    # Berekn funksjonsverdiane
    y_values = f(x_random)

    # Estimer integralet
    integral = (b - a) * np.mean(
        y_values
    )

    return integral


# Halvsirkel: f(x) = sqrt(1 - x^2)
def f(x):
    return np.sqrt(1 - x**2)


# Køyr fleire gonger for å sjå
# variansen
# For reproduserbarheit
np.random.seed(42)

for N in [
    100,
    1000,
    10000,
    100000,
    1000000,
]:
    resultat = (
        monte_carlo_integral(
            f, -1, 1, N
        )
    )
    # Heile sirkelen
    pi_estimat = 2 * resultat
    feil = abs(pi_estimat - np.pi)
    print(
        f"N = {N:7d}: pi ≈"
        f" {pi_estimat:.6f}, feil"
        f" = {feil:.6f}"
    )

Utskrift:

N =     100: pi ≈ 3.094681, feil = 0.046912
N =    1000: pi ≈ 3.114703, feil = 0.026890
N =   10000: pi ≈ 3.153273, feil = 0.011680
N =  100000: pi ≈ 3.144075, feil = 0.002482
N = 1000000: pi ≈ 3.141744, feil = 0.000151

Feilen avtek i gjennomsnitt som 1/N1/\sqrt{N}: for å halvere feilen må vi firedoble talet på punkt. Éi einskild køyring følgjer ikkje dette nøyaktig, fordi punkta er tilfeldige.

Svar: Med N=1 000 000N = 1\,000\,000 punkt gir programmet estimatet 3,1417443{,}141744 for π\pi, med feil ca. 0,000150{,}00015.

📝Oppgave 3.5.6

Bruk Monte Carlo-integrasjon til å rekne ut volumet av ei einingssfære i 3D.

Volumet av ei sfære med radius rr er V=43πr3\displaystyle V = \frac{4}{3}\pi r^3, så for r=1r = 1 er V=43π≈4,189\displaystyle V = \frac{4}{3}\pi \approx 4{,}189.

Hint: Generer tilfeldige punkt i kuben [−1,1]3[-1, 1]^3 og tel kor mange som er innanfor sfæren (dvs. x2+y2+z2≤1x^2 + y^2 + z^2 \leq 1).

Oppgave 3.5.6
Vanskelig
Python
Loading...

Feilanalyse og konvergens

Når vi bruker numeriske metodar, er det viktig å forstå kor nøyaktig resultatet er og korleis feilen oppfører seg når vi aukar talet på delintervall.

📜Konvergensordenar for integrasjonsmetodar
MetodeFeilorden
Rektangel (venstre)O(h)=O(1/n)O(h) = O(1/n)
Rektangel (midtpunkt)O(h2)=O(1/n2)O(h^2) = O(1/n^2)
TrapesO(h2)=O(1/n2)O(h^2) = O(1/n^2)
SimpsonO(h4)=O(1/n4)O(h^4) = O(1/n^4)
RombergO(h2k)O(h^{2k})
Monte CarloO(1/N)O(1/\sqrt{N})
MetodeDobling av nn
Rektangel (venstre)Halverer feilen
Rektangel (midtpunkt)Reduserer feilen med faktor 4
TrapesReduserer feilen med faktor 4
SimpsonReduserer feilen med faktor 16
RombergAvheng av ekstrapolasjonsnivå
Monte CarloReduserer feilen med faktor 2\sqrt{2}

Konvergensfaktor: Forholdet mellom feil for nn og feil for 2n2n bør tilnærme:
- Rektangel (venstre): 2
- Trapes/midtpunkt: 4
- Simpson: 16
✏️Verifisere konvergensorden

Rekn ut konvergensordenen til trapesmetoden for ∫01ex dx\displaystyle\int_0^1 e^x\,dx ved å samanlikne feil for n=10,20,40,80n = 10, 20, 40, 80.

import math


def trapesmetoden(f, a, b, n):
    h = (b - a) / n
    total = (f(a) + f(b)) / 2
    for i in range(1, n):
        total += f(a + i * h)
    return h * total


def f(x):
    return math.exp(x)


eksakt = math.e - 1

print("n\t\tFeil\t\tFaktor")
print("-" * 40)

prev_feil = None
for n in [
    10,
    20,
    40,
    80,
    160,
    320,
]:
    resultat = trapesmetoden(
        f, 0, 1, n
    )
    feil = abs(resultat - eksakt)

    if prev_feil is not None:
        faktor = prev_feil / feil
        print(
            f"{n}\t\t{feil:.2e}\t"
            f"{faktor:.2f}"
        )
    else:
        print(
            f"{n}\t\t{feil:.2e}\t"
            "-"
        )

    prev_feil = feil

Utskrift:

n		Feil		Faktor
----------------------------------------
10		1.43e-03	-
20		3.58e-04	4.00
40		8.95e-05	4.00
80		2.24e-05	4.00
160		5.59e-06	4.00
320		1.40e-06	4.00

Faktoren er konsistent 4, som stadfestar at trapesmetoden har konvergensorden O(1/n2)O(1/n^2).

Svar: Feilen blir 4 gonger mindre kvar gong nn doblast, så trapesmetoden har konvergensorden 2.

📝Oppgave 3.5.7

Lag eit program som samanliknar konvergensen til rektangelmetoden, trapesmetoden og Simpsons metode for ∫0πsin⁡(x) dx=2\displaystyle\int_0^{\pi} \sin(x)\,dx = 2.

a) Rekn ut feilen for n=10,20,40,80,160n = 10, 20, 40, 80, 160 for alle tre metodane.

b) Lag eit log-log-plott av feil mot nn for alle tre metodane.

c) Stadfest konvergensordenane frå plottet (stigingstalet skal vere −1-1, −2-2 og −4-4 for dei respektive metodane).

Oppgave 3.5.7
Vanskelig
Python
Loading...

Adaptiv integrasjon (fordjuping, utanfor læreplanen)

Så langt har vi brukt jamt fordelte delintervall. Men nokre funksjonar varierer meir i nokre område enn andre. Adaptiv integrasjon justerer steglengda automatisk: små steg der funksjonen varierer mykje, store steg der han er jamn.

Adaptiv Simpson-integrasjon
Adaptiv integrasjon fungerer rekursivt:

1. Rekn ut integralet over heile intervallet: S1=S(a,b)S_1 = S(a, b)
2. Del intervallet i to og rekn ut summen: S2=S(a,m)+S(m,b)S_2 = S(a, m) + S(m, b) der m=a+b2\displaystyle m = \frac{a+b}{2}
3. Samanlikn: Dersom ∣S1−S2∣<ε|S_1 - S_2| < \varepsilon (toleransen), godta S2S_2 som svar
4. Elles: Bruk adaptiv integrasjon rekursivt på [a,m][a, m] og [m,b][m, b]

Dette gir høg nøyaktigheit der det trengst, utan unødvendig utrekning der funksjonen er glatt.

✏️Implementere adaptiv Simpson

Implementer adaptiv Simpson-integrasjon for funksjonar som varierer mykje lokalt, som f(x)=1(x−0,3)2+0,01\displaystyle f(x) = \frac{1}{(x-0{,}3)^2 + 0{,}01} på [0,1][0, 1].

import numpy as np


def simpson_enkel(f, a, b):
    """Simpson over eitt
    intervall [a, b]"""
    m = (a + b) / 2
    h = (b - a) / 6
    return h * (
        f(a) + 4 * f(m) + f(b)
    )


def adaptiv_simpson(
    f,
    a,
    b,
    tol=1e-8,
    max_depth=50,
):
    """
    Adaptiv Simpson-integrasjon.

    Parametrar:
        f: funksjonen
        a, b: integrasjonsgrenser
        tol: toleranse for feil
        max_depth: maksimum
        rekursjonsdybde
    """

    def _adaptive(
        a, b, S_ab, tol, depth
    ):
        m = (a + b) / 2
        S_am = simpson_enkel(
            f, a, m
        )
        S_mb = simpson_enkel(
            f, m, b
        )
        S_sum = S_am + S_mb

        # Sjekk om vi er nøyaktige
        # nok
        if (
            depth >= max_depth
            or abs(S_sum - S_ab)
            < 15 * tol
        ):
            # Richardson-
            # ekstrapolering
            return (
                S_sum
                + (S_sum - S_ab)
                / 15
            )

        # Rekursivt kall på kvar
        # halvdel
        return _adaptive(
            a,
            m,
            S_am,
            tol / 2,
            depth + 1,
        ) + _adaptive(
            m,
            b,
            S_mb,
            tol / 2,
            depth + 1,
        )

    S_ab = simpson_enkel(f, a, b)
    return _adaptive(
        a, b, S_ab, tol, 0
    )


# Test på funksjon med skarp topp
def f(x):
    return 1 / (
        (x - 0.3) ** 2 + 0.01
    )


# Berekn integralet
resultat = adaptiv_simpson(
    f, 0, 1
)

# Samanlikn med SciPy
from scipy import integrate

scipy_resultat, _ = (
    integrate.quad(f, 0, 1)
)

print(
    "Adaptiv Simpson:"
    f" {resultat:.10f}"
)
print(
    "SciPy quad:     "
    f" {scipy_resultat:.10f}"
)
print(
    "Forskjell:      "
    f" {abs(resultat - scipy_resultat):.2e}"
)

Utskrift:

Adaptiv Simpson: 26.7794504459
SciPy quad:      26.7794504459
Forskjell:       1.82e-12

Den adaptive metoden konsentrerer berekningane rundt toppen ved x=0,3x = 0{,}3.

Svar: Integralet er ≈26,7794504459\approx 26{,}7794504459. Adaptiv Simpson og quad gir same verdi (forskjell ca. 2⋅10−122 \cdot 10^{-12}).

📝Oppgave 3.5.8
Samanlikn talet på funksjonsevalueringar for vanleg Simpson og adaptiv Simpson for funksjonen

f(x)=sin⁡(100x)f(x) = \sin(100x)

på intervallet [0,1][0, 1].

a) Implementer ein teljar for funksjonsevalueringar.

b) Finn kor mange evalueringar vanleg Simpson treng for å oppnå feil <10−8< 10^{-8}.

c) Tel evalueringar for adaptiv Simpson med toleranse 10−810^{-8}.

Oppgave 3.5.8
Vanskelig
Python
Loading...

Romberg-integrasjon (fordjuping, utanfor læreplanen)

Romberg-integrasjon kombinerer trapesmetoden med Richardson-ekstrapolering for å oppnå høgare nøyaktigheit. Idéen er å bruke resultata frå trapesmetoden med forskjellige nn til å "ekstrapolere bort" feila.

Romberg-algoritmen
Romberg-algoritmen byggjer opp ein tabell Ri,jR_{i,j}:

Kolonne 0: Trapesmetoden med n=1,2,4,8,…,2in = 1, 2, 4, 8, \ldots, 2^i:
Ri,0=T(2i)R_{i,0} = T(2^i)

Kolonne j > 0: Richardson-ekstrapolering:
Ri,j=Ri,j−1+Ri,j−1−Ri−1,j−14j−1R_{i,j} = R_{i,j-1} + \frac{R_{i,j-1} - R_{i-1,j-1}}{4^j - 1}

Tabellen ser slik ut:

R[0,0]
R[1,0]  R[1,1]
R[2,0]  R[2,1]  R[2,2]
R[3,0]  R[3,1]  R[3,2]  R[3,3]
...

Kvart ekstrapolasjonssteg aukar konvergensordenen med 2: O(h2),O(h4),O(h6),…O(h^2), O(h^4), O(h^6), \ldots

✏️Implementere Romberg-integrasjon

Implementer Romberg-integrasjon og rekn ut ∫01ex dx=e−1\displaystyle\int_0^1 e^x\,dx = e - 1.

import numpy as np


def romberg(
    f,
    a,
    b,
    max_iter=10,
    tol=1e-12,
):
    """
    Romberg-integrasjon.

    Returnerer:
        (resultat, tabell) -
        tilnærma verdi og Romberg-
        tabellen
    """
    R = np.zeros(
        (max_iter, max_iter)
    )

    # Første kolonne:
    # trapesmetoden
    h = b - a
    R[0, 0] = (
        h * (f(a) + f(b)) / 2
    )

    for i in range(1, max_iter):
        h = h / 2
        n = 2**i

        # Legg til nye midtpunkt
        sum_new = sum(
            f(a + (2 * k - 1) * h)
            for k in range(
                1, n // 2 + 1
            )
        )
        R[i, 0] = (
            R[i - 1, 0] / 2
            + h * sum_new
        )

        # Richardson-
        # ekstrapolering
        for j in range(1, i + 1):
            R[i, j] = R[
                i, j - 1
            ] + (
                R[i, j - 1]
                - R[i - 1, j - 1]
            ) / (
                4**j - 1
            )

        # Sjekk konvergens
        if (
            i > 0
            and abs(
                R[i, i]
                - R[i - 1, i - 1]
            )
            < tol
        ):
            return (
                R[i, i],
                R[
                    : i + 1,
                    : i + 1,
                ],
            )

    return (
        R[
            max_iter - 1,
            max_iter - 1,
        ],
        R,
    )


def f(x):
    return np.exp(x)


eksakt = np.e - 1

resultat, tabell = romberg(
    f, 0, 1, max_iter=6
)

print("Romberg-tabell:")
print("-" * 70)
for i in range(tabell.shape[0]):
    row = "  ".join(
        f"{tabell[i,j]:.10f}"
        for j in range(i + 1)
    )
    print(f"i={i}: {row}")

print(
    f"\nResultat: {resultat:.12f}"
)
print(f"Eksakt:   {eksakt:.12f}")
print(
    "Feil:    "
    f" {abs(resultat - eksakt):.2e}"
)

Utskrift:

Romberg-tabell:
----------------------------------------------------------------------
i=0: 1.8591409142
i=1: 1.7539310925  1.7188611519
i=2: 1.7272219046  1.7183188419  1.7182826879
i=3: 1.7205185922  1.7182841547  1.7182818422  1.7182818288
i=4: 1.7188411286  1.7182819741  1.7182818287  1.7182818285  1.7182818285
i=5: 1.7184216603  1.7182818376  1.7182818285  1.7182818285  1.7182818285  1.7182818285

Resultat: 1.718281828459
Eksakt:   1.718281828459
Feil:     4.44e-16

Merk den raske konvergensen: etter berre 5-6 iterasjonar har vi maskin-presisjon!

Svar: Romberg gir 1,718281828459=e−11{,}718281828459 = e - 1 med feil ca. 4⋅10−164 \cdot 10^{-16}.

📝Oppgave 3.5.9

Bruk romberg-funksjonen frå dømet «Implementere Romberg-integrasjon» til å rekne ut ∫0πsin⁡(x) dx=2\displaystyle\int_0^{\pi} \sin(x)\,dx = 2.

a) Samanlikn med scipy.integrate.quad.

b) Skriv ut Romberg-tabellen og undersøk kor raskt diagonalen nærmar seg 2.

Oppgave 3.5.9
Vanskelig
Python
Loading...

Gauss-kvadratur (fordjuping, utanfor læreplanen)

Gauss-kvadratur er ein familie av integrasjonsmetodar som oppnår maksimal nøyaktigheit for eit gitt tal på funksjonsevalueringar. I staden for å bruke jamt fordelte punkt, bruker Gauss-metodane optimalt plasserte punkt og vekter.

Gauss-Legendre-kvadratur
Gauss-Legendre-kvadratur tilnærmar integralet som:
∫−11f(x) dx≈∑i=1nwif(xi)\int_{-1}^{1} f(x)\,dx \approx \sum_{i=1}^{n} w_i f(x_i)

der punkta xix_i (nullpunkta til Legendre-polynoma) og vektene wiw_i er optimalt valde.

Nøkkeleigenskap: Med nn punkt er Gauss-Legendre eksakt for alle polynom av grad ≤2n−1\leq 2n-1.

For generelle grenser [a,b][a, b] bruker vi variabelskiftet:
∫abf(x) dx=b−a2∫−11f(b−a2t+a+b2) dt\int_a^b f(x)\,dx = \frac{b-a}{2}\int_{-1}^{1} f\left(\frac{b-a}{2}t + \frac{a+b}{2}\right)\,dt

✏️Gauss-Legendre-kvadratur med SciPy

Bruk Gauss-Legendre-kvadratur til å rekne ut ∫01e−x2 dx\displaystyle\int_0^1 e^{-x^2}\,dx med forskjellig tal på punkt.

import numpy as np
from scipy import integrate


def f(x):
    return np.exp(-(x**2))


# Eksakt verdi (frå scipy.quad)
eksakt, _ = integrate.quad(
    f, 0, 1
)

print("Gauss-Legendre-kvadratur:")
print("-" * 50)

for n in [2, 3, 4, 5, 6, 8, 10]:
    resultat, _ = (
        integrate.fixed_quad(
            f, 0, 1, n=n
        )
    )
    feil = abs(resultat - eksakt)
    print(
        f"n = {n:2d}:"
        f" {resultat:.12f}, feil"
        f" = {feil:.2e}"
    )

# Manuell implementasjon
print(
    "\nManuell Gauss-Legendre med"
    " numpy.polynomial.legendre:"
)
from numpy.polynomial.legendre import (
    leggauss,
)


def gauss_legendre(f, a, b, n):
    """Gauss-Legendre-kvadratur
    med n punkter."""
    # Få punkter og vekter for
    # [-1, 1]
    x, w = leggauss(n)

    # Transformer til [a, b]
    halvbredde = (b - a) / 2
    sentrum = (a + b) / 2
    x_trans = halvbredde * x + sentrum
    scale = halvbredde

    return scale * np.sum(
        w * f(x_trans)
    )


for n in [3, 5, 7]:
    resultat = gauss_legendre(
        f, 0, 1, n
    )
    print(
        f"n = {n}:"
        f" {resultat:.12f}, feil"
        " ="
        f" {abs(resultat - eksakt):.2e}"
    )

Utskrift:

Gauss-Legendre-kvadratur:
--------------------------------------------------
n =  2: 0.746594688283, feil = 2.29e-04
n =  3: 0.746814584191, feil = 9.55e-06
n =  4: 0.746824468131, feil = 3.35e-07
n =  5: 0.746824126766, feil = 6.05e-09
n =  6: 0.746824132890, feil = 7.77e-11
n =  8: 0.746824132812, feil = 6.44e-15
n = 10: 0.746824132812, feil = 1.11e-16

Manuell Gauss-Legendre med numpy.polynomial.legendre:
n = 3: 0.746814584191, feil = 9.55e-06
n = 5: 0.746824126766, feil = 6.05e-09
n = 7: 0.746824132812, feil = 7.89e-13

Med berre 10 punkter oppnår vi maskin-presisjon!

Svar: Gauss-Legendre med 10 punkter gir 0,7468241328120{,}746824132812, med feil ca. 10−1610^{-16}.

📝Oppgave 3.5.10

Samanlikn Gauss-Legendre-kvadratur med Simpsons metode for følgjande integral:

a) ∫01x5 dx=16\displaystyle \displaystyle\int_0^1 x^5\,dx = \frac{1}{6} (polynom av grad 5)

b) ∫0πcos⁡(x) dx=0\displaystyle\int_0^{\pi} \cos(x)\,dx = 0 (oscillerande)

c) ∫01x dx=23\displaystyle \displaystyle\int_0^1 \sqrt{x}\,dx = \frac{2}{3} (singulær derivert ved x=0x = 0)

For kvar: finn talet på punkt/delintervall som gir feil <10−10< 10^{-10}.

Oppgave 3.5.10
Vanskelig
Python
Loading...

Dobbeltintegral numerisk (fordjuping, utanfor læreplanen)

Numerisk integrasjon i to dimensjonar er ei naturleg utviding av metodane vi har sett. Vi kan rekne ut

∬Rf(x,y) dA\iint_R f(x, y)\,dA

ved å gjenta éin-dimensjonal integrasjon.

Dobbeltintegral med iterert integrasjon
For eit rektangulært område R=[a,b]×[c,d]R = [a, b] \times [c, d]:

∫ab∫cdf(x,y) dy dx≈∑i=0n−1∑j=0m−1wiwjf(xi,yj)\int_a^b \int_c^d f(x, y)\,dy\,dx \approx \sum_{i=0}^{n-1} \sum_{j=0}^{m-1} w_i w_j f(x_i, y_j)

For meir generelle område bruker vi scipy.integrate.dblquad:
∫ab∫g(x)h(x)f(x,y) dy dx\int_a^b \int_{g(x)}^{h(x)} f(x, y)\,dy\,dx

der grensene for yy kan avhenge av xx.

✏️Rekne ut dobbeltintegral med SciPy

Rekn ut ∬Re−(x2+y2) dA\displaystyle\iint_R e^{-(x^2 + y^2)}\,dA der R=[0,1]×[0,1]R = [0, 1] \times [0, 1].

import numpy as np
from scipy import integrate


# NB: dblquad bruker rekkjefølgja
# (y, x)
def f(y, x):
    return np.exp(-(x**2 + y**2))


# Berekn dobbeltintegralet
resultat, feil = (
    integrate.dblquad(
        f, 0, 1, 0, 1
    )
)

print(
    "Dobbeltintegral:"
    f" {resultat:.10f}"
)
print(
    f"Feilestimering:  {feil:.2e}"
)


# Samanlikn med manuell iterert
# integrasjon
def inner_integral(x):
    """Integrerer f over y for
    fast x"""
    result, _ = integrate.quad(
        lambda y: np.exp(
            -(x**2 + y**2)
        ),
        0,
        1,
    )
    return result


resultat_iterert, _ = (
    integrate.quad(
        inner_integral, 0, 1
    )
)
print(
    "Iterert:        "
    f" {resultat_iterert:.10f}"
)


# Manuell 2D Simpson
def simpson_2d(
    f, ax, bx, ay, by, nx, ny
):
    """2D Simpson-integrasjon"""
    hx = (bx - ax) / nx
    hy = (by - ay) / ny

    def simpson_1d(g, a, b, n):
        h = (b - a) / n
        return (h / 3) * (
            g(a)
            + 4
            * sum(
                g(a + i * h)
                for i in range(
                    1, n, 2
                )
            )
            + 2
            * sum(
                g(a + i * h)
                for i in range(
                    2, n, 2
                )
            )
            + g(b)
        )

    def inner(x):
        return simpson_1d(
            lambda y: f(x, y),
            ay,
            by,
            ny,
        )

    return simpson_1d(
        inner, ax, bx, nx
    )


def f_xy(x, y):
    return np.exp(-(x**2 + y**2))


resultat_simpson = simpson_2d(
    f_xy, 0, 1, 0, 1, 20, 20
)
print(
    "Simpson 2D:     "
    f" {resultat_simpson:.10f}"
)

Utskrift:

Dobbeltintegral: 0.5577462854
Feilestimering:  8.29e-15
Iterert:         0.5577462854
Simpson 2D:      0.5577463616

Svar: Dobbeltintegralet er ≈0,5577462854\approx 0{,}5577462854.

✏️Dobbeltintegral over ikkje-rektangulært område

Rekn ut arealet av einingssirkelen ved å rekne ut ∬D1 dA\displaystyle\iint_D 1\,dA der DD er sirkelen x2+y2≤1x^2 + y^2 \leq 1.

import numpy as np
from scipy import integrate


# f(y, x) = 1 (vi bereknar areal)
def f(y, x):
    return 1.0


# Grenser for y som funksjon av x
def y_lower(x):
    return -np.sqrt(1 - x**2)


def y_upper(x):
    return np.sqrt(1 - x**2)


# Berekn dobbeltintegralet
areal, feil = integrate.dblquad(
    f, -1, 1, y_lower, y_upper
)

print(
    f"Berekna areal: {areal:.10f}"
)
print(
    "Eksakt (pi):   "
    f" {np.pi:.10f}"
)
print(
    "Feil:          "
    f" {abs(areal - np.pi):.2e}"
)

# Alternativ: Monte Carlo
# For reproduserbarheit
np.random.seed(42)
N = 1000000
x = np.random.uniform(-1, 1, N)
y = np.random.uniform(-1, 1, N)
inside = np.sum(x**2 + y**2 <= 1)
# 4 = areal av kvadratet [-1,1] x
# [-1,1]
areal_mc = 4 * (inside / N)

print(
    "\nMonte Carlo:   "
    f" {areal_mc:.4f}"
)
print(
    "Feil MC:       "
    f" {abs(areal_mc - np.pi):.4f}"
)

Utskrift:

Berekna areal: 3.1415926536
Eksakt (pi):    3.1415926536
Feil:           5.33e-15

Monte Carlo:    3.1399
Feil MC:        0.0017

Svar: dblquad gir arealet 3,1415926536=π3{,}1415926536 = \pi. Monte Carlo med 10610^6 punkt gir 3,13993{,}1399 (feil ca. 0,00170{,}0017).

📝Oppgave 3.5.11

Rekn ut volumet under paraboloiden z=4−x2−y2z = 4 - x^2 - y^2 over sirkelen x2+y2≤4x^2 + y^2 \leq 4.

Det eksakte svaret er ∬D(4−x2−y2) dA=8π\displaystyle\iint_D (4 - x^2 - y^2)\,dA = 8\pi.

a) Bruk scipy.integrate.dblquad.

b) Bruk Monte Carlo med N=100000N = 100000 punkt.

c) Visualiser paraboloiden og integrasjonsområdet.

Oppgave 3.5.11
Vanskelig
Python
Loading...

Praktiske bruksområde

Numerisk integrasjon har svært mange bruksområde i vitskap og ingeniørfag. Her ser vi på nokre eksempel.

✏️Rekne ut arbeid utført av ei variabel kraft

Ei fjør følgjer Hookes lov med F(x)=kxF(x) = kx for små deformasjonar, men for store deformasjonar blir ho ikkje-lineær: F(x)=kx+αx3F(x) = kx + \alpha x^3. Rekn ut arbeidet som krevst for å strekkje fjøra frå x=0x = 0 til x=Lx = L.

import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt

# Parametrar
k = 100  # N/m (fjørstivheit)
# N/m^3 (ikkje-lineær koeffisient)
alpha = 500
L = 0.1  # m (strekning)


def F(x):
    """Kraft som funksjon av
    posisjon"""
    return k * x + alpha * x**3


# Berekn arbeidet W = integral av
# F(x) dx frå 0 til L
arbeid, feil = integrate.quad(
    F, 0, L
)

# Samanlikn med lineær fjør (berre
# kx)
arbeid_linear = 0.5 * k * L**2

print(f"Ikkje-lineær fjør:")
print(
    f"  Arbeid = {arbeid:.4f} J"
)
print(f"\nLineær fjør:")
print(
    "  Arbeid ="
    f" {arbeid_linear:.4f} J"
)
forskjell = (
    (arbeid - arbeid_linear)
    / arbeid_linear
    * 100
)
print(f"\nForskjell: {forskjell:.1f}%")

# Visualiser
x = np.linspace(0, L, 100)
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.plot(
    x,
    F(x),
    'b-',
    label=(
        r'Ikkje-lineær: $F = kx +'
        r' \alpha x^3$'
    ),
)
plt.plot(
    x,
    k * x,
    'r--',
    label='Lineær: $F = kx$',
)
plt.fill_between(
    x, 0, F(x), alpha=0.3
)
plt.xlabel('x (m)')
plt.ylabel('F (N)')
plt.title('Kraft vs. posisjon')
plt.legend()
plt.grid(True, alpha=0.3)

plt.subplot(1, 2, 2)
# Kumulativt arbeid
arbeid_kumulativ = [
    integrate.quad(F, 0, xi)[0]
    for xi in x
]
plt.plot(
    x,
    arbeid_kumulativ,
    'b-',
    label='Arbeid',
)
plt.xlabel('x (m)')
plt.ylabel('W (J)')
plt.title('Kumulativt arbeid')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

Svar: Arbeidet er 0,51250{,}5125 J for den ikkje-lineære fjøra og 0,50000{,}5000 J for den lineære, ein forskjell på 2,5 %2{,}5\,\%.

✏️Rekne ut buelengd (fordjuping, utanfor læreplanen)

Rekn ut buelengda til kurva y=sin⁡(x)y = \sin(x) frå x=0x = 0 til x=2πx = 2\pi.

import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt

# Buelengde: L = integral av
# sqrt(1 + (dy/dx)^2) dx
# For y = sin(x): dy/dx = cos(x)


def integrand(x):
    return np.sqrt(
        1 + np.cos(x) ** 2
    )


# Berekn buelengda
buelengde, feil = integrate.quad(
    integrand, 0, 2 * np.pi
)

print(
    f"Buelengde av sin(x) frå 0"
    f" til 2*pi:"
)
print(f"L = {buelengde:.6f}")
print(
    "(Dette er ca."
    f" {buelengde/np.pi:.4f}"
    " * pi)"
)

# For referanse: lengda av ei rett
# linje frå (0,0) til (2*pi,0) er
# 2*pi
print(
    f"\nRett linje: {2*np.pi:.6f}"
)
forlengelse = (
    (buelengde - 2 * np.pi)
    / (2 * np.pi)
    * 100
)
print(f"Forlengelse: {forlengelse:.1f}%")

# Visualiser
x = np.linspace(0, 2 * np.pi, 200)
y = np.sin(x)

plt.figure(figsize=(10, 4))
plt.plot(x, y, 'b-', linewidth=2)
plt.axhline(
    0,
    color='gray',
    linestyle='--',
    alpha=0.5,
)
plt.fill_between(
    x,
    0,
    y,
    where=(y > 0),
    alpha=0.2,
    color='blue',
)
plt.fill_between(
    x,
    0,
    y,
    where=(y < 0),
    alpha=0.2,
    color='red',
)
plt.xlabel('x')
plt.ylabel('y')
plt.title(
    '$y = \sin(x)$, buelengde $L'
    f' = {buelengde:.4f}$'
)
plt.grid(True, alpha=0.3)
plt.axis('equal')
plt.show()

Svar: Buelengda er L≈7,640396L \approx 7{,}640396.

📝Oppgave 3.5.12
Fysikkoppgåve: Ein partikkel rører seg med farten v(t)=10sin⁡(t)e−0,1tv(t) = 10\sin(t)e^{-0{,}1t} m/s.

a) Finn total tilbakelagd strekning i tidsintervallet t∈[0,20]t \in [0, 20] s.
(Hint: strekning = ∫∣v(t)∣ dt\int |v(t)|\,dt, ikkje ∫v(t) dt\int v(t)\,dt)

b) Finn netto forflytning (endeleg posisjon minus startposisjon).

c) Visualiser v(t)v(t), posisjonen x(t)x(t), og kumulativ strekning.

Oppgave 3.5.12
Vanskelig
Python
Loading...
📝Oppgave 3.5.13
Prosjektoppgåve: Normalfordelinga (fordjuping, utanfor læreplanen)

Sannsynstettpunktet for normalfordelinga (Gauss-fordelinga) med gjennomsnitt μ=0\mu = 0 og standardavvik σ=1\sigma = 1 er:

f(x)=12πe−x2/2f(x) = \frac{1}{\sqrt{2\pi}} e^{-x^2/2}

a) Verifiser at ∫−∞∞f(x) dx=1\displaystyle\int_{-\infty}^{\infty} f(x)\,dx = 1 ved bruk av scipy.integrate.quad.

b) Berekn sannsynet P(−1≤X≤1)P(-1 \leq X \leq 1), altså arealet under kurva frå −1-1 til 11. Dette skal vere ca. 0,68270{,}6827 (68,27 %).

c) Berekn P(−2≤X≤2)P(-2 \leq X \leq 2) og P(−3≤X≤3)P(-3 \leq X \leq 3). Samanlikn med 68–95–99,7-regelen.

d) Visualiser normalfordelinga og skuggelegg området frå −1-1 til 11.

Oppgave 3.5.13
Vanskelig
Python
Loading...
📝Oppgave 3.5.14
Bonusoppgåve: Lag ei interaktiv samanlikning (fordjuping, utanfor læreplanen)

Lag eit program som:

a) Tek inn ein funksjon f(x)f(x), grenser [a,b][a, b], og tal på punkt nn.

b) Reknar ut integralet med alle metodane: rektangel, midtpunkt, trapes, Simpson, Romberg og Gauss-Legendre.

c) Viser ein tabell med resultata og feila (bruk scipy.quad som referanse).

d) Rangerer metodane etter nøyaktigheit for den gitte funksjonen.

Test med:
- f(x)=x4f(x) = x^4 på [0,1][0, 1] (polynom)
- f(x)=sin⁡(10x)f(x) = \sin(10x) på [0,π][0, \pi] (oscillerande)
- f(x)=e−x2f(x) = e^{-x^2} på [−2,2][-2, 2] (Gaussisk)

Oppgave 3.5.14
Vanskelig
Python
Loading...

Oppsummering

I dette kapittelet har du lært:

- Rektangelmetoden: Tilnærmar integralet med ∑f(xi)Δx\sum f(x_i)\Delta x; venstrepunkt, høgrepunkt eller midtpunkt kan brukast.
- Trapesmetoden: T=Δx2(f(x0)+2f(x1)+⋯+2f(xn−1)+f(xn))\displaystyle T = \frac{\Delta x}{2}\left(f(x_0) + 2f(x_1) + \cdots + 2f(x_{n-1}) + f(x_n)\right), med feil av orden 1n2\displaystyle \frac{1}{n^2}.
- Simpsons metode: Bruker parablar gjennom tre og tre punkt, med feil av orden 1n4\displaystyle \frac{1}{n^4} — eksakt for polynom av grad ≤3\leq 3.
- Python-implementasjon: Alle metodane kan skrivast som korte løkker eller med NumPy/SciPy (scipy.integrate).
- Monte Carlo-integrasjon: Bruker tilfeldige punkt til å estimere integral, nyttig i høge dimensjonar.

Nøkkelomgrep


OmgrepForklaring
RektangelmetodenSum av rektangelareal
TrapesmetodenSum av trapesareal, feil ∼1/n2\sim 1/n^2
Simpsons metodeParabeltilnærming, feil ∼1/n4\sim 1/n^4
Monte CarloEstimat basert på tilfeldige punkt

Viktige formlar


- Δx=b−an\displaystyle \Delta x = \frac{b-a}{n}
- Trapes: T=Δx2(f(x0)+2∑i=1n−1f(xi)+f(xn))\displaystyle T = \frac{\Delta x}{2}\left(f(x_0) + 2\sum_{i=1}^{n-1} f(x_i) + f(x_n)\right)
- Simpson: S=Δx3(f(x0)+4f(x1)+2f(x2)+⋯+4f(xn−1)+f(xn))\displaystyle S = \frac{\Delta x}{3}\left(f(x_0) + 4f(x_1) + 2f(x_2) + \cdots + 4f(x_{n-1}) + f(x_n)\right)
Repetisjonsoppgåver
Din fremgang
0deloppgaver0 / 5 oppgaver

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.