3.5
Programmering av integrasjon

3.5 Programmering av integrasjon

Implementere integrasjonsalgoritmer i Python.

55 min
19 oppgaver
PythonProgrammeringAlgoritmerNumerisk 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 å beregne bestemte integraler numerisk. Selv om mange integraler kan løses analytisk, finnes det utallige funksjoner som ikke har en lukket antiderivert. Da må vi ty til numeriske metoder.

Vi skal implementere tre klassiske metoder:
- Rektangelmetoden (den enkleste)
- Trapesmetoden (bedre nøyaktighet)
- Simpsons metode (svært god nøyaktighet)

I tillegg skal vi se på disse metodene, som er fordypning (utenfor læreplanen):
- Monte Carlo-integrasjon (stokastisk metode)
- Adaptiv integrasjon (automatisk steglengdejustering)
- Romberg-integrasjon (ekstrapolasjon)
- Gauss-kvadratur (optimal punktplassering)
- Dobbeltintegraler (integrasjon i 2D)

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

Rektangelmetoden

Den enkleste tilnærmingen til numerisk integrasjon er å dele opp arealet under kurven i rektangler. Ideen er at summen av arealene til rektanglene tilnærmer 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 delintervaller med bredde 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 mer 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 en Python-funksjon som beregner ∫01x2 dx\displaystyle\int_0^1 x^2\,dx ved hjelp av rektangelmetoden med n=1000n = 1000 delintervaller. Den eksakte verdien er 13≈0,333333\displaystyle \frac{1}{3} \approx 0{,}333333.

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

    Parametere:
        f: funksjonen som skal
        integreres
        a: nedre grense
        b: øvre grense
        n: antall delintervaller

    Returnerer:
        Tilnærmet 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


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

Utskrift:

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

Feilen er ca. 0,00050{,}0005, noe som tilsvarer en relativ feil på ca. 0,15 %0{,}15\,\%.

Svar: Rektangelmetoden gir ≈0,332833\approx 0{,}332833, mens 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 hvert 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 stedet for O(h)O(h).

✏️Sammenlikning av venstre- og midtpunktsmetoden

Sammenlign 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 mer 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 å beregne ∫0πsin⁡(x) dx\displaystyle\int_0^{\pi} \sin(x)\,dx.

Den eksakte verdien er 22.

a) Bruk n=100n = 100 delintervaller og finn tilnærmet verdi.

b) Bruk n=1000n = 1000 delintervaller og sammenlign feilen.

c) Hvor mange delintervaller trenger du for at feilen skal være mindre enn 0,00010{,}0001?

Oppgave 3.5.1
Medium
Python
Loading...

Trapesmetoden

Trapesmetoden gir bedre nøyaktighet enn rektangelmetoden ved å tilnærme kurven med trapeser i stedet for rektangler. Et trapes fanger opp mer av kurvens form.

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 skrives 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 en eller annen ξ∈[a,b]\xi \in [a, b].

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

✏️Implementere trapesmetoden i Python

Skriv en Python-funksjon for trapesmetoden og beregn ∫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):
    """
    Beregner det bestemte
    integralet av f fra 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 punkter (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 reduseres med faktor 100 når nn øker med faktor 10, som bekrefter 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

Sammenlign 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 metodene.

b) Beregn integralet med n=100n = 100 for begge metoder.

c) Hvor mange ganger mer nøyaktig er trapesmetoden?

Oppgave 3.5.2
Medium
Python
Loading...

Simpsons metode

Simpsons metode tilnærmer kurven med parabler (andregradsfunksjoner) i stedet for rette linjer. Dette gir enda bedre nøyaktighet enn trapesmetoden, spesielt for glatte funksjoner.

Simpsons metode (1/3-regelen)
For å tilnærme ∫abf(x) dx\displaystyle\int_a^b f(x)\,dx med Simpsons metode krever vi at nn er et partall. 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 koeffisientene 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 en eller annen ξ∈[a,b]\xi \in [a, b].

Dette betyr at feilen avtar som O(1/n4)O(1/n^4), altså mye raskere enn trapesmetoden.

Bemerkelsesverdig: Simpsons metode er eksakt for polynomer av grad 3 eller lavere!

✏️Implementere Simpsons metode i Python

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

import math


def simpson(f, a, b, n):
    """
    Beregner det bestemte
    integralet av f fra a til b
    ved hjelp av Simpsons metode.
    Krever at n er et partall.
    """
    if n % 2 != 0:
        raise ValueError(
            "n må være et partall"
            " for Simpsons metode"
        )

    h = (b - a) / n

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

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

    # Like indekser (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

# Sammenlign 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 bare n=10n = 10 har Simpsons metode en feil på ca. 1,1⋅10−41{,}1 \cdot 10^{-4}, mens trapesmetoden har feil på ca. 0,0170{,}017. Simpsons metode er ca. 150 ganger mer 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 å beregne ∫01e−x2 dx\displaystyle\int_0^1 e^{-x^2}\,dx.

Dette integralet har ingen lukket antiderivert, så vi må bruke numeriske metoder!

a) Implementer Simpsons metode.

b) Finn en tilnærmet verdi med n=100n = 100.

c) Den "eksakte" verdien (beregnet med mange desimaler) er ca. 0,7468240{,}746824. Hva er feilen?

Oppgave 3.5.3
Vanskelig
Python
Loading...

Simpsons 3/8-regel (fordypning, utenfor læreplanen)

Det finnes også en variant av Simpsons metode som bruker kubisk interpolasjon over tre delintervaller.

Simpsons 3/8-regel
Simpsons 3/8-regel tilnærmer integralet ved å dele i 3 delintervaller:

∫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 delintervaller (der nn er delelig 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 koeffisientene 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 trenger vi ikke alltid å implementere integrasjonsmetoder fra bunnen av. Python-bibliotekene NumPy og SciPy har ferdige, optimaliserte funksjoner for numerisk integrasjon.

SciPy integrate-modulen
scipy.integrate inneholder flere funksjoner for numerisk integrasjon:

- quad(f, a, b): Adaptiv integrasjon med høy nøyaktighet. Returnerer (resultat, feilestimering).
- trapezoid(y, x): Trapesmetoden på diskrete datapunkter.
- simpson(y, x): Simpsons metode på diskrete datapunkter.
- 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 punkter.

NumPy gir også numpy.trapezoid(y, x) for enkel trapesintegrasjon (i eldre NumPy-versjoner heter den numpy.trapz).

✏️Integrasjon med SciPy

Bruk SciPy til å beregne ∫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))


# Beregn integralet fra 0 til
# uendelig
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 fra quad:"
    f" {feil:.2e}"
)
print(
    "Faktisk feil:"
    f" {abs(resultat - eksakt):.2e}"
)

Utskrift:

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

Merk at quad håndterer uendelige grenser automatisk og gir et feilestimering!

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

✏️Trapesmetoden med NumPy på datapunkter

Gitt målepunkter (xi,yi)(x_i, y_i) fra et eksperiment, beregn det tilnærmede arealet under kurven.

import numpy as np

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

# Beregn tilbakelagt strekning
# (integral av hastighet)
strekning = np.trapezoid(v, t)

print(f"Tidspunkter: {t}")
print(f"Hastigheter: {v}")
print(
    "Tilbakelagt strekning:"
    f" {strekning:.1f} meter"
)

Utskrift:

Tidspunkter: [0 1 2 3 4 5]
Hastigheter: [ 0  5  8 10  9  6]
Tilbakelagt strekning: 35.0 meter

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

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

📝Oppgave 3.5.4

Bruk SciPy til å beregne følgende integraler:

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}

Sammenlign med de eksakte verdiene.

Oppgave 3.5.4
Medium
Python
Loading...

Visualisering av numerisk integrasjon

En viktig del av å forstå numeriske metoder er å visualisere hva som skjer. Med Matplotlib kan vi tegne funksjonen og rektanglene/trapesene som brukes til å tilnærme arealet.

✏️Visualisere rektangelmetoden

Lag en visualisering som viser rektanglene brukt i rektangelmetoden for f(x)=x2f(x) = x^2 på [0,2][0, 2] med n=8n = 8 delintervaller.

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 en figur som viser:
- Den blå kurven f(x)=x2f(x) = x^2
- Lyseblå rektangler som representerer tilnærmingen
- Tittel med både tilnærmet og eksakt verdi

✏️Visualisere trapesmetoden

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

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 en visualisering som sammenligner rektangelmetoden, trapesmetoden og Simpsons metode for f(x)=x3f(x) = x^3 på [0,1][0, 1] med n=4n = 4.

Vis tre subplots side om side som illustrerer hver metode, og beregn feilen for hver.

Oppgave 3.5.5
Vanskelig
Python
Loading...

Monte Carlo-integrasjon (fordypning, utenfor læreplanen)

En helt annen tilnærming til numerisk integrasjon er Monte Carlo-metoden, som bruker tilfeldige tall. Ideen er enkel: kast tilfeldige punkter i et rektangel og tell hvor mange som lander under kurven.

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-verdier uniformt fordelt på [a,b][a, b].
2. Beregn gjennomsnittlig funksjonsverdi: fˉ=1N∑i=1Nf(xi)\displaystyle \bar{f} = \frac{1}{N}\sum_{i=1}^{N} f(x_i)
3. Multipliser med intervallets lengde:

∫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)

Fordeler:
- Enkel å implementere
- Skalerer godt til høyere dimensjoner
- Robust mot diskontinuiteter

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

✏️Monte Carlo-integrasjon i Python

Bruk Monte Carlo-metoden til å estimere π\pi ved å beregne ∫−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
):
    """
    Beregner integralet av f fra a
    til b
    ved hjelp av Monte Carlo-
    metoden.
    """
    # Generer N tilfeldige
    # x-verdier i [a, b]
    x_random = np.random.uniform(
        a, b, N
    )

    # Beregn funksjonsverdiene
    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)


# Kjør flere ganger for å se
# variansen
# For reproduserbarhet
np.random.seed(42)

for N in [
    100,
    1000,
    10000,
    100000,
    1000000,
]:
    resultat = (
        monte_carlo_integral(
            f, -1, 1, N
        )
    )
    # Hele 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 avtar i gjennomsnitt som 1/N1/\sqrt{N}: for å halvere feilen må vi firedoble antall punkter. Én enkelt kjøring følger ikke dette nøyaktig, fordi punktene er tilfeldige.

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

📝Oppgave 3.5.6

Bruk Monte Carlo-integrasjon til å beregne volumet av en enhetssfære i 3D.

Volumet av en 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 punkter i kuben [−1,1]3[-1, 1]^3 og tell hvor mange som er innenfor 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 metoder, er det viktig å forstå hvor nøyaktig resultatet er og hvordan feilen oppfører seg når vi øker antall delintervaller.

📜Konvergensordener for integrasjonsmetoder
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
RombergAvhenger 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

Beregn konvergensordenen til trapesmetoden for ∫01ex dx\displaystyle\int_0^1 e^x\,dx ved å sammenligne 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 bekrefter at trapesmetoden har konvergensorden O(1/n2)O(1/n^2).

Svar: Feilen blir 4 ganger mindre hver gang nn dobles, så trapesmetoden har konvergensorden 2.

📝Oppgave 3.5.7

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

a) Beregn feilen for n=10,20,40,80,160n = 10, 20, 40, 80, 160 for alle tre metoder.

b) Lag et log-log-plott av feilen mot nn for alle tre metoder.

c) Bekreft konvergensordenene fra plottet (stigningstallet skal være −1-1, −2-2 og −4-4 for de respektive metodene).

Oppgave 3.5.7
Vanskelig
Python
Loading...

Adaptiv integrasjon (fordypning, utenfor læreplanen)

Så langt har vi brukt jevnt fordelte delintervaller. Men noen funksjoner varierer mer i noen områder enn andre. Adaptiv integrasjon justerer steglengden automatisk: små steg der funksjonen varierer mye, store steg der den er jevn.

Adaptiv Simpson-integrasjon
Adaptiv integrasjon fungerer rekursivt:

1. Beregn integralet over hele intervallet: S1=S(a,b)S_1 = S(a, b)
2. Del intervallet i to og beregn 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. Sammenlign: Hvis ∣S1−S2∣<ε|S_1 - S_2| < \varepsilon (toleransen), godta S2S_2 som svar
4. Ellers: Bruk adaptiv integrasjon rekursivt på [a,m][a, m] og [m,b][m, b]

Dette gir høy nøyaktighet der det trengs, uten unødvendig beregning der funksjonen er glatt.

✏️Implementere adaptiv Simpson

Implementer adaptiv Simpson-integrasjon for funksjoner som varierer mye 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 ett 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.

    Parametere:
        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å hver
        # 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
    )


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

# Sammenlign 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 beregningene rundt toppen ved x=0,3x = 0{,}3.

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

📝Oppgave 3.5.8
Sammenlign antall funksjonsevalueringer for vanlig Simpson og adaptiv Simpson for funksjonen

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

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

a) Implementer en teller for funksjonsevalueringer.

b) Finn hvor mange evalueringer vanlig Simpson trenger for å oppnå feil <10−8< 10^{-8}.

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

Oppgave 3.5.8
Vanskelig
Python
Loading...

Romberg-integrasjon (fordypning, utenfor læreplanen)

Romberg-integrasjon kombinerer trapesmetoden med Richardson-ekstrapolering for å oppnå høyere nøyaktighet. Ideen er å bruke resultatene fra trapesmetoden med forskjellige nn til å "ekstrapolere bort" feilene.

Romberg-algoritmen
Romberg-algoritmen bygger opp en 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]
...

Hvert ekstrapolasjonssteg øker 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 beregn ∫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ærmet 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 midtpunkter
        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 bare 5-6 iterasjoner 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 fra eksempelet «Implementere Romberg-integrasjon» til å beregne ∫0πsin⁡(x) dx=2\displaystyle\int_0^{\pi} \sin(x)\,dx = 2.

a) Sammenlign med scipy.integrate.quad.

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

Oppgave 3.5.9
Vanskelig
Python
Loading...

Gauss-kvadratur (fordypning, utenfor læreplanen)

Gauss-kvadratur er en familie av integrasjonsmetoder som oppnår maksimal nøyaktighet for et gitt antall funksjonsevalueringer. I stedet for å bruke jevnt fordelte punkter, bruker Gauss-metodene optimalt plasserte punkter og vekter.

Gauss-Legendre-kvadratur
Gauss-Legendre-kvadratur tilnærmer 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 punktene xix_i (nullpunktene til Legendre-polynomene) og vektene wiw_i er optimalt valgt.

Nøkkelegenskap: Med nn punkter er Gauss-Legendre eksakt for alle polynomer 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 å beregne ∫01e−x2 dx\displaystyle\int_0^1 e^{-x^2}\,dx med forskjellige antall punkter.

import numpy as np
from scipy import integrate


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


# Eksakt verdi (fra 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 bare 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

Sammenlign Gauss-Legendre-kvadratur med Simpsons metode for følgende integraler:

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 (oscillerende)

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

For hver: finn antall punkter/delintervaller som gir feil <10−10< 10^{-10}.

Oppgave 3.5.10
Vanskelig
Python
Loading...

Dobbeltintegraler numerisk (fordypning, utenfor læreplanen)

Numerisk integrasjon i to dimensjoner er en naturlig utvidelse av metodene vi har sett. Vi kan beregne

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

ved å gjenta én-dimensjonal integrasjon.

Dobbeltintegral med iterert integrasjon
For et 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 mer generelle områder 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.

✏️Beregne dobbeltintegral med SciPy

Beregn ∬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 rekkefølgen
# (y, x)
def f(y, x):
    return np.exp(-(x**2 + y**2))


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

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


# Sammenlign 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 ikke-rektangulært område

Beregn arealet av enhetssirkelen ved å beregne ∬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 beregner 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)


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

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

# Alternativ: Monte Carlo
# For reproduserbarhet
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:

Beregnet 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 punkter gir 3,13993{,}1399 (feil ca. 0,00170{,}0017).

📝Oppgave 3.5.11

Beregn 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 punkter.

c) Visualiser paraboloiden og integrasjonsområdet.

Oppgave 3.5.11
Vanskelig
Python
Loading...

Praktiske anvendelser

Numerisk integrasjon har utallige anvendelser i vitenskap og ingeniørfag. Her ser vi på noen eksempler.

✏️Beregne arbeid utført av en variabel kraft

En fjær følger Hookes lov med F(x)=kxF(x) = kx for små deformasjoner, men for store deformasjoner blir den ikke-lineær: F(x)=kx+αx3F(x) = kx + \alpha x^3. Beregn arbeidet som kreves for å strekke fjæren fra x=0x = 0 til x=Lx = L.

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

# Parametre
k = 100  # N/m (fjærstivhet)
# N/m^3 (ikke-lineær koeffisient)
alpha = 500
L = 0.1  # m (strekning)


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


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

# Sammenlign med lineær fjær (kun
# kx)
arbeid_linear = 0.5 * k * L**2

print(f"Ikke-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'Ikke-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 ikke-lineære fjæra og 0,50000{,}5000 J for den lineære, en forskjell på 2,5 %2{,}5\,\%.

✏️Beregne buelengde (fordypning, utenfor læreplanen)

Beregn buelengden til kurven y=sin⁡(x)y = \sin(x) fra 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
    )


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

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

# For referanse: lengden av en
# rett linje fra (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: Buelengden er L≈7,640396L \approx 7{,}640396.

📝Oppgave 3.5.12
Fysikkoppgave: En partikkel beveger seg med hastighet v(t)=10sin⁡(t)e−0,1tv(t) = 10\sin(t)e^{-0{,}1t} m/s.

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

b) Finn netto forflytning (endelig 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
Prosjektoppgave: Normalfordelingen (fordypning, utenfor læreplanen)

Sannsynlighetstettheten for normalfordelingen (Gauss-fordelingen) 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) Beregn sannsynligheten P(−1≤X≤1)P(-1 \leq X \leq 1), altså arealet under kurven fra −1-1 til 11. Dette skal være ca. 0,68270{,}6827 (68,27 %).

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

d) Visualiser normalfordelingen og skyggelegg området fra −1-1 til 11.

Oppgave 3.5.13
Vanskelig
Python
Loading...
📝Oppgave 3.5.14
Bonusoppgave: Lag en interaktiv sammenlikning (fordypning, utenfor læreplanen)

Lag et program som:

a) Tar inn en funksjon f(x)f(x), grenser [a,b][a, b], og antall punkter nn.

b) Beregner integralet med alle metodene: rektangel, midtpunkt, trapes, Simpson, Romberg og Gauss-Legendre.

c) Viser en tabell med resultatene og feilene (bruk scipy.quad som referanse).

d) Rangerer metodene etter nøyaktighet 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] (oscillerende)
- 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ærmer integralet med ∑f(xi)Δx\sum f(x_i)\Delta x; venstrepunkt, høyrepunkt eller midtpunkt kan brukes.
- 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 parabler gjennom tre og tre punkter, med feil av orden 1n4\displaystyle \frac{1}{n^4} — eksakt for polynomer av grad ≤3\leq 3.
- Python-implementasjon: Alle metodene kan skrives som korte løkker eller med NumPy/SciPy (scipy.integrate).
- Monte Carlo-integrasjon: Bruker tilfeldige punkter til å estimere integraler, nyttig i høye dimensjoner.

Nøkkelbegreper


BegrepForklaring
RektangelmetodenSum av rektangelarealer
TrapesmetodenSum av trapesarealer, feil ∼1/n2\sim 1/n^2
Simpsons metodeParabeltilnærming, feil ∼1/n4\sim 1/n^4
Monte CarloEstimat basert på tilfeldige punkter

Viktige formler


- Δ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)
Repetisjonsoppgaver
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.