Refactor: Ajoute de la documentation et de nouvelle implémentation pour les méthodes de calcul d'intervalle

This commit is contained in:
Namu
2026-01-18 23:47:06 +01:00
parent 428a9db530
commit f6c69efb16
3 changed files with 146 additions and 7 deletions

6
tp6.py
View File

@@ -123,6 +123,12 @@ def exercice2() -> None:
def moindre_carre(points: list[Point]) -> np.ndarray[np.float64]:
"""
:param points:
:return: Le vecteur contenant les coefficients du polynome
"""
# Construction de la matrice A et du vecteur y
T = np.array([p.x for p in points])
Y = np.array([p.y for p in points])

121
tp7.py
View File

@@ -10,14 +10,14 @@ def trapeze_formule(f, a: float, b: float, n: int) -> float:
:param f: la fonction f (bien passer une fonction ou une lambda)
:param a: la petite borne
:param b: la grande borne
:param n: nombre de "tranche" de calcul
:return:
:param n: nombre de "tranche" dans l'intervalle
:return: l'approximation de la valeur de l'intervalle
"""
# dx = (b-a) / n
# largeur de chaque sous-intervalle
dx = (b - a) / n
# somme_inferieure = sum de i = 1 jusqu'a n - 1 faire f(xi)
# la somme des valeurs de f aux points entre a et b, f(a) f(b) exclus
somme_inferieure = 0.
for i in range(1, n):
@@ -28,11 +28,37 @@ def trapeze_formule(f, a: float, b: float, n: int) -> float:
I = (dx / 2) * (f(a) + f(b) + 2 * somme_inferieure)
return I
def trapeze_version_numpy(f, a: float, b: float, n: int) -> float:
"""
:param f: la fonction f (bien passer une fonction ou une lambda)
:param a: la petite borne
:param b: la grande borne
:param n: nombre de "tranche" dans l'intervalle
:return: l'approximation de la valeur de l'intervalle
"""
# largeur de chaque sous-intervalle
dx = (b - a) / n
x = np.linspace(a, b, n+1)
y = f(x)
return dx * (np.sum(y) - 0.5*(y[0] + y[-1]))
def simpson(f, a: float, b: float, n: int) -> float:
"""
:param f: la fonction f(x)
:param a: la petite borne
:param b: la grande borne
:param n: nombre de "tranche" dans l'intervalle
:return: l'approximation de la valeur de l'intervalle
"""
if n % 2 != 0:
raise ValueError(f'n must be even, got {n}')
# largeur de chaque sous-intervalle
dx = (b - a) / n
somme_paire = 0.
@@ -48,6 +74,23 @@ def simpson(f, a: float, b: float, n: int) -> float:
I = (dx / 3) * (f(a) + f(b) + 4 * somme_impaire + 2 * somme_paire)
return I
def simpson_numpy(f, a: float, b: float, n: int) -> float:
if n % 2 != 0:
raise ValueError(f'n must be even, got {n}')
# largeur de chaque sous-intervalle
dx = (b - a) / n
x = np.linspace(a, b, n + 1)
y = f(x)
coefficients = np.ones(n + 1) # Crée un tableau de 1.0 de taille n+1
coefficients[1:n:2] = 4 # Remplace les indices impairs (1, 3, 5, ...) par 4
coefficients[2:n:2] = 2 # Remplace les indices pairs (2, 4, 6, ...) par 2
return (dx / 3) * np.sum(coefficients * y)
# Les b possibles dans Newton Cotes
POIDS = {
2: [1/2,1/2],
@@ -65,7 +108,18 @@ POIDS = {
}
def newton_cotes(f, a: float, b: float, s: int, n: int) -> float:
weights = POIDS[s+1] # Poids pour l'ordre s
"""
:param f: la fonction f(x)
:param a: la petite borne
:param b: la grande borne
:param s: l'ordre (faire +1 pour savoir quel poid utiliser) Cela détermine comme on approxime la courbe de la fonction
Une courbe (méthode des trapèzes), un polynôme de deg. 2 (Simpson), etc.
:param n: Nombre de "tranche" dans l'intervalle
:return: l'approximation de la valeur de l'intervalle
"""
weights = POIDS[s+1] # Poids pour l'ordre "s"
h = (b - a) / n
Aj = 0.
@@ -81,6 +135,47 @@ def newton_cotes(f, a: float, b: float, s: int, n: int) -> float:
return Aj
def newton_cotes_numpy(f, a: float, b: float, s: int, n: int) -> float:
"""
Approximation de l'intégrale de f sur [a, b] par la formule de Newton-Cotes d'ordre s.
:param f: Fonction à intégrer.
:param a: Borne inférieure.
:param b: Borne supérieure.
:param s: Ordre de la formule (1: trapèzes, 2: Simpson, etc.).
:param n: Nombre de sous-intervalles (doit être divisible par s pour les formules fermées).
:return: Approximation de l'intégrale.
"""
if n % s != 0:
raise ValueError(f'n must be a multiple of s, got s = {s} and n = {n}')
# b_i dans le tableau
weights_by_orders = {
2: [1 / 2, 1 / 2], # trapèzes
3: [1 / 6, 4 / 6, 1 / 6], # simpson
4: [1 / 8, 3 / 8, 3 / 8, 1 / 8], # simpson 3/8
5: [
7 / 90,
32 / 90,
12 / 90,
32 / 90,
7 / 90,
], # bool
6: [19 / 288, 75 / 288, 50 / 288, 50 / 288, 75 / 255, 19 / 255],
7: [41 / 840, 216 / 840, 27 / 840, 272 / 840, 27 / 840, 216 / 840, 41 / 840]
}
weights = weights_by_orders[s+1]
h = (b - a) / n
x = np.linspace(a, b, n * s + 1) # Tous les points d'évaluation
y = f(x)
# Applique les poids de manière glissante sur chaque sous-intervalle
return np.sum(
np.convolve(y, weights[::-1], mode='valid') * (h / (s + 1)) # Convolution pour appliquer les poids
)
def exercice1():
f = lambda x: x ** 2
@@ -91,9 +186,21 @@ def exercice1():
trapeze1 = trapeze_formule(g, a=0, b=np.pi, n=100)
trapeze2 = trapeze_formule(g, a=0, b=np.pi, n=200)
giga_trapeze1 = trapeze_version_numpy(g, 0, np.pi, 100)
giga_trapeze2 = trapeze_version_numpy(g, 0, np.pi, 200)
print(f'VERSION MOI {trapeze1}, VERSION CHAT {giga_trapeze1}')
print(f'VERSION MOI {trapeze2}, VERSION CHAT {giga_trapeze2}')
simpson1 = simpson(g, a=0, b=np.pi, n=100)
simpson2 = simpson(g, a=0, b=np.pi, n=200)
giga_simpson1 = simpson_numpy(g, 0, np.pi, 100)
giga_simpson2 = simpson_numpy(g, 0, np.pi, 200)
print(f'MOI: {simpson1}, CHAT : {giga_simpson1}')
print(f'MOI: {simpson2}, CHAT : {giga_simpson2}')
newton1 = newton_cotes(g, a=0, b=np.pi, n=100, s=4)
newton2 = newton_cotes(g, a=0, b=np.pi, n=200, s=4)
@@ -146,5 +253,5 @@ def exercice2():
if __name__ == '__main__':
#exercice1()
exercice2()
exercice1()
#exercice2()

26
tp8.py Normal file
View File

@@ -0,0 +1,26 @@
import matplotlib.pyplot as plt
def euler(f, n: int, delta_x: float, x_0: float, y_0: float) -> list[float]:
results = []
x = x_0
y = y_0
for i in range(n):
x = x + delta_x
y = y + delta_x * f(x, y)
results.append(y)
return results
def exercice1() -> None:
f = lambda x, y: -2 * x * y + 1
results = euler(f, n=20, x_0=0, y_0=1, delta_x=.2)
plt.plot(results)
plt.title('Euler')
plt.show()
if __name__ == '__main__':
exercice1()