Ce dépôt contient des implémentations pédagogiques en Python pour des méthodes numériques courantes : résolution de systèmes linéaires, décompositions matricielles, interpolation, méthodes itératives et résolution d'équations différentielles ordinaires.
- But : fournir des codes simples, lisibles et utilisables en TD/TP, avec des variantes pure‑Python (pour la pédagogie) et
numpy(pour la performance). - Langage : Python 3 (tests effectués sous Python 3.13).
TPMTH300/: code des travaux et exemples.TPMTH300/EquationLineaire/: méthodes directes et itératives (Crout, Doolittle, Gauss, Cholesky, pivot partiel/total, etc.).TPMTH300/INTERPOLATION/: Lagrange, Newton, moindres carrés.TPMTH300/EQUADIFF/: Euler explicite, Runge‑Kutta 2/4.TPMTH300/ITERACTIVES/: Jacobi, Gauss‑Seidel.
- Ajout d'un
.gitignore. - Ajout de blocs
if __name__ == '__main__'pour des tests rapides dans plusieurs modules (Gauss, pivot partiel/total, Gauss‑Jordan, Doolittle, etc.). - Harmonisation partielle des API (certaines fonctions acceptent
numpy.ndarray, d'autreslist).
Ci‑dessous, pour chaque méthode implémentée, tu trouveras : la formule mathématique essentielle, l'idée algorithmique et les choix concrets d'implémentation en Python.
- Principe mathématique : transformer la matrice
$A$ en une matrice triangulaire supérieure$U$ par opérations élémentaires de ligne, ce qui produit un second membre modifié$\tilde b$ tel que$U x = \tilde b$ . - Étapes algorithmiques :
- Pour chaque colonne k de 0 à n−2 :
- prendre pivot
$p=A_{k,k}$ ; - pour chaque ligne i>k, calculer factor =
$A_{i,k}/p$ puis mettre à jour la ligne i :$A_{i,j} \leftarrow A_{i,j} - factor\cdot A_{k,j}$ pour j≥k ;$b_i \leftarrow b_i - factor\cdot b_k$ .
- prendre pivot
- Substitution arrière pour calculer x à partir de U et
$\tilde b$ .
- Pour chaque colonne k de 0 à n−2 :
- Implémentation en Python :
- Variante pédagogique : listes de listes pour
Aet liste pourb, bouclesforimbriquées, copies de travail pour ne pas modifier les entrées originales. - Vérification de pivot nul (raise ValueError). Complexité O(n^3).
- Variante pédagogique : listes de listes pour
- Principe : à chaque étape, choisir la ligne dont l'élément dans la colonne k a la plus grande valeur absolue ; échanger les lignes pour limiter les erreurs numériques puis éliminer.
- Implémentation : fonction
PivotPartiel(A,k,n)qui renvoie l'indice de la meilleure ligne, échange simple de lignes (A[i], A[p] = A[p], A[i]pour listes; slicing pournumpy).
- Principe : choisir le coefficient maximal en valeur absolue dans la sous‑matrice restante et permuter lignes et colonnes ; enregistrer la permutation de colonnes pour reconstruire la solution.
- Implémentation : parcours double boucle pour trouver l'indice (i*,j*), swap de colonnes et lignes, vecteur
col_orderpour réordonner la solution finale.
- Principe : normaliser la ligne pivot et éliminer dans toutes les autres lignes, obtenant directement la solution sur la colonne augmentée.
- Implémentation : construire la matrice augmentée
M = [A|b], normaliser ligne pivotM[k,k:] /= M[k,k], éliminerM[i,k:] -= M[i,k] * M[k,k:]pour i≠k.
- Formules clefs :
-
$U_{k,j} = A_{k,j} - \sum_{r=0}^{k-1} L_{k,r} U_{r,j}$ (pour$j\ge k$ ), -
$L_{i,k} = \dfrac{1}{U_{k,k}}\left(A_{i,k} - \sum_{r=0}^{k-1} L_{i,r} U_{r,k}\right)$ (pour$i>k$ ).
-
- Implémentation : initialiser
L = I,U = zeros, boucles k→ calcul U puis L. Résolution via substitution avant/arrière.
- Formules clefs (Crout) :
-
$L_{i,k} = A_{i,k} - \sum_{r=0}^{k-1} L_{i,r} U_{r,k}$ pour$i\ge k$ , -
$U_{k,j} = \dfrac{1}{L_{k,k}}\left(A_{k,j} - \sum_{r=0}^{k-1} L_{k,r} U_{r,j}\right)$ pour$j>k$ .
-
- Implémentation :
Uavec diagonale unité,Lstocke les pivots ; option pivot partiel disponible dans la version pédagogique.
- Principe : pour
$A$ symétrique définie positive,$A = L L^T$ avec-
$L_{k,k} = \sqrt{A_{k,k} - \sum_{r=0}^{k-1} L_{k,r}^2}$ , -
$L_{i,k} = \dfrac{1}{L_{k,k}}\left(A_{i,k} - \sum_{r=0}^{k-1} L_{i,r}L_{k,r}\right)$ pour$i>k$ .
-
- Implémentation : calcul en place, vérifier symétrie et positivité définie (test sur
$L_{k,k}^2$ non négatif). Plus efficace qu'une LU générale (≈ moitié du coût).
- Formules : décomposer
$A=D+L+U$ (D diag),- Jacobi :
$x^{(k+1)} = D^{-1}(b - (L+U)x^{(k)})$ , - Gauss‑Seidel :
$x^{(k+1)} = (D+L)^{-1}(b - U x^{(k)})$ .
- Jacobi :
- Implémentation : boucle d'itérations, calculer norme du résidu pour la convergence, tolérance et nombre maximal d'itérations en paramètres.
- Lagrange :
$P(x)=\sum_i y_i \ell_i(x)$ avec$\ell_i(x)=\prod_{j\ne i} \dfrac{x-x_j}{x_i-x_j}$ ; implémenté en évaluant les polynômes de base pour chaque point d'évaluation. - Newton : calcul des différences divisées (tableau triangulaire), coefficients pour la forme de Newton, évaluation par Horner généralisé.
- Résoudre
$\min_c ||V c - y||_2$ où$V$ est la matrice de Vandermonde ; équations normales$V^T V c = V^T y$ . - Implémentation : construction de
Vpuis résolution via décomposition (LU) ou méthode plus stable (QR) si nécessaire.
- Euler explicite :
$y_{n+1}=y_n+h f(t_n,y_n)$ — implémenté dansEQUADIFF/euler_explicite.py; attention stabilité pour pas trop grands. - RK2 (point milieu / Heun) : deux évaluations de
fpar pas ; RK4 : quatre évaluations et combinaison pondérée (ordre 4).
- Types acceptés : certaines fonctions acceptent
numpy.ndarray, d'autreslist(les versions pure‑Python vérifient les types). Si besoin, je peux homogénéiser pour accepter les deux (np.asarrayou conversion interne en listes). - Gestion des erreurs : l'implémentation lève des exceptions claires (ValueError) quand elle détecte des cas singuliers (pivot nul, matrice non symétrique pour Cholesky, etc.).
- Performances : les versions
numpysont vectorisées et plus rapides ; les versions pédagogiques privilégient la lisibilité (boucles explicites).
Si tu veux, je peux :
- extraire ces descriptions en fichiers
docs/(un fichier par méthode), - créer des notebooks pédagogiques montrant étapes numériques pas à pas,
- committer ces changements sur la branche
poly.
Licence : voir LICENSE.
Cette section est conçue comme un mini‑cours pour chaque méthode numérique implémentée dans le dépôt. Chaque sous‑section présente :
- le contexte et l'objectif ;
- les équations mathématiques essentielles (formalisme) ;
- l'algorithme étape par étape (pseudocode) ;
- remarques d'implémentation et points numériques importants.
Remarque : les équations sont écrites en notation LaTeX (KaTeX) pour une lecture mathématique claire.
Contexte : résoudre
Formulation : appliquer des opérations élémentaires de lignes pour obtenir une matrice triangulaire supérieure
Pseudocode (Gauss sans pivot) :
Input: A (n×n), b (n)
for k in 0..n-2:
p = A[k,k]
if |p| < eps: raise PivotError
for i in k+1..n-1:
factor = A[i,k] / p
for j in k..n-1:
A[i,j] -= factor * A[k,j]
b[i] -= factor * b[k]
# substitution arrière
x = zeros(n)
for i in n-1..0:
s = sum(A[i,j]*x[j] for j in i+1..n-1)
x[i] = (b[i] - s) / A[i,i]
return x
Remarques : complexité O(n^3). Sans pivot, la méthode peut échouer numériquement si un pivot est proche de zéro.
Pivot partiel : à l'étape k, choisir la ligne p≥k telle que
Pivot total : chercher
Pseudocode (Pivot partiel) :
for k in 0..n-2:
p = argmax_{i=k..n-1} |A[i,k]|
swap_rows(A,k,p); swap(b,k,p)
pivot = A[k,k]
... (élimination comme Gauss) ...
Pseudocode (Pivot total) :
col_order = [0..n-1]
for k in 0..n-2:
(p,q) = argmax_{i=k..n-1, j=k..n-1} |A[i,j]|
swap_rows(A,k,p); swap(b,k,p)
swap_cols(A,k,q); swap(col_order[k], col_order[q])
pivot = A[k,k]
... (élimination) ...
# après substitution arrière, permuter x selon col_order inverse
Remarque : pivot total est plus coûteux mais utile pour matrices pathologiques.
Objectif : factoriser
Doolittle (L avec diagonale unité) :
Pseudocode (Doolittle) :
L = I; U = zeros(n,n)
for k in 0..n-1:
for j in k..n-1:
U[k,j] = A[k,j] - sum(L[k,r]*U[r,j] for r in 0..k-1)
for i in k+1..n-1:
L[i,k] = (A[i,k] - sum(L[i,r]*U[r,k] for r in 0..k-1)) / U[k,k]
Crout (U avec diagonale unité) :
Remarques d'implémentation :
- Faire attention aux divisions par zéro (tester
$U_{k,k}$ ou$L_{k,k}$ ).\ - Après décomposition, résoudre
$L y = b$ puis$U x = y$ (substitution avant/arrière).
Applicable si
Pseudocode :
L = zeros(n,n)
for k in 0..n-1:
sum_sq = sum(L[k,r]**2 for r in 0..k-1)
L[k,k] = sqrt(A[k,k] - sum_sq)
for i in k+1..n-1:
s = sum(L[i,r]*L[k,r] for r in 0..k-1)
L[i,k] = (A[i,k] - s) / L[k,k]
Notes : moitié du coût d'une LU générale en opérations; vérifier la positivité définie via
Formulation :
Jacobi :
Gauss‑Seidel :
Pseudocode (Jacobi) :
x_new = zeros(n)
while not converged:
for i in 0..n-1:
s = sum(A[i,j]*x_old[j] for j in 0..i-1) + sum(A[i,j]*x_old[j] for j in i+1..n-1)
x_new[i] = (b[i] - s) / A[i,i]
check convergence; x_old = x_new
Pseudocode (Gauss‑Seidel) : on remplace x_old par x (mise à jour en place) et on utilise les valeurs récentes dans la boucle.
Convergence : garanties sous conditions (diagonale dominante, ou matrice symétrique définie positive pour certaines variantes).
Lagrange :
Newton : construire le tableau des différences divisées
Implémentation : Lagrange est direct mais coûteux si on évalue pour beaucoup de points ; Newton est plus pratique pour ajouter des points.
Construire la matrice de Vandermonde
Pseudocode (équations normales) :
V = vandermonde(x, deg)
G = V.T @ V
h = V.T @ y
c = solve(G, h) # par LU ou autre
Euler explicite :
RK2 (point milieu) :
RK4 :
Implémentation : stocker t et y sur la grille, boucle de pas, évaluer f aux temps requis