On trouvera :
- TD_simulnum_gauss.py : méthode du pivot de Gauss
- TD_simulnum_riemann.py : méthodes d'intégration
- TD_simulnum_solve.py : recherche du zéro d'une fonction
# -*- coding: utf8 -*- | |
# Pivot de Gauss | |
# ============== | |
# la fonction prend en argument m une matrice sous la forme d'une liste | |
# de listes (chaque liste constituant une ligne de la matrice) : | |
# | |
# Par exemple la matrice identité 3x3 sera : [[1,0,0],[0,1,0],[0,0,1]] | |
# | |
def pivot(m): | |
nbr_rows = len(m) # nombre de lignes | |
for i in range(nbr_rows): | |
# on cherche le meilleur pivot, c'est-à-dire le plus grand terme | |
# (en valeur absolue) pour la colonne i parmi les lignes non encore | |
# utilisées ; compte-tenu de l'algorithme, les colonnes de gauche | |
# (sauf pour la première itération évidemment) comporteront | |
# nécessairement une valeur nulle. | |
pivot = i # par défaut le pivot se trouve sur la ligne i | |
for j in range(i, nbr_rows): | |
if abs(m[j][i]) > abs(m[pivot][i]): | |
pivot = j | |
# s'il n'y a aucune colonne non nulle, la matrice est singulière | |
if m[pivot][i] == 0: | |
raise Exception("Singular matrix") | |
# on échange les lignes i et pivot | |
tmp = m[i] # variable temporairement utile pour l'échange | |
m[i] = m[pivot] | |
m[pivot] = tmp | |
# on normalise la ligne i (en mettant à 1 la colonne i) | |
p = m[i][i] | |
m[i] = [ x/p for x in m[i] ] | |
# on annule la colonne i dans toutes les autres lignes | |
for j in range(0,nbr_rows): | |
if j != i: | |
m[j] = [ x - m[j][i]*m[i][k] for k,x in enumerate(m[j]) ] | |
return m | |
# Exemples | |
# ======== | |
# | |
# 1) Inversion de la matrice | |
# | |
# / 2 -1 0 \ / 2 -1 0 | 1 0 0 \ | |
# | -1 2 -1 | en appliquant le pivot à | -1 2 -1 | 0 1 0 | | |
# \ 0 -1 2 / \ 0 -1 2 | 0 0 1 / | |
print(pivot([[2,-1,0,1,0,0],[-1,2,-1,0,1,0],[0,-1,2,0,0,1]])) | |
# 2) Résolution d'un système d'équations linéaires : | |
# , | |
# / x - y + 2.z = 5 | |
# +| 3.x + 2.y + z = 10 | |
# \ 2.x - 3.y - 2.z = -10 | |
# ` | |
# par application de l'algorithme du pivot à la matrice | |
# | |
# / 1 -1 2 | 5 \ | |
# | 3 2 1 | 10 | | |
# \ 2 -3 -2 | -10 / | |
print(pivot([[1,-1,2,5],[3,2,1,10],[2,-3,-2,-10]])) |
# -*- coding: utf8 -*- | |
# Intégration d'une fonction entre deux bornes selon plusieurs | |
# types d'approximation : | |
# | |
# * integr_rect1( f, a, b, epsilon ) | |
# Intégration par des rectangles dont la hauteur coïncide avec | |
# la courbe sur sa gauche | |
# | |
# * integr_rect2( f, a, b, epsilon ) | |
# Intégration par des rectangles dont la hauteur est la hauteur moyenne | |
# des deux points de la courbe à gauche et à droite | |
# (cela revient en fait à construire un trapèze) | |
# | |
# * integr_rect3( f, a, b, epsilon ) | |
# Intégration par des rectangles dont la hauteur est la plus petite | |
# des hauteurs des deux points de la courbe à gauche et à droite | |
# | |
# * integr_rect4( f, a, b, epsilon ) | |
# Intégration par des rectangles dont la hauteur est la plus grande | |
# des hauteurs des deux points de la courbe à gauche et à droite | |
# | |
# * integr_trap( f, a, b, epsilon ) | |
# Intégration par des trapèzes (en fait identique à integr_rect2) | |
def integr_rect1(f, a, b, epsilon): | |
s = 0 # somme des aires | |
n = int((b-a)/epsilon) # nombre d'intervalles de largeur epsilon | |
for i in range(n): | |
x = a + i*epsilon | |
s += f(x) * epsilon # hauteur x largeur | |
return s | |
def integr_rect2(f, a, b, epsilon): | |
s = 0 # somme des aires | |
n = int((b-a)/epsilon) # nombre d'intervalles de largeur epsilon | |
for i in range(n): | |
x = a + i*epsilon | |
s += ( f(x)+f(x+epsilon) ) / 2 * epsilon # hauteur x largeur | |
return s | |
def integr_rect3(f, a, b, epsilon): | |
s = 0 # somme des aires | |
n = int((b-a)/epsilon) # nombre d'intervalles de largeur epsilon | |
for i in range(n): | |
x = a + i*epsilon | |
s += min( f(x),f(x+epsilon) ) * epsilon # hauteur x largeur | |
return s | |
def integr_rect4(f, a, b, epsilon): | |
s = 0 # somme des aires | |
n = int((b-a)/epsilon) # nombre d'intervalles de largeur epsilon | |
for i in range(n): | |
x = a + i*epsilon | |
s += max( f(x),f(x+epsilon) ) * epsilon # hauteur x largeur | |
return s | |
integr_trap = integr_rect2 | |
# exemples | |
# ======== | |
from math import sin, atan, pi | |
f = lambda x: x*atan(x) | |
print( "integr_rect1 =",integr_rect1(f,0,1,1e-5) ) | |
print( "integr_rect2 =",integr_rect2(f,0,1,1e-5) ) | |
print( "integr_rect3 =",integr_rect3(f,0,1,1e-5) ) | |
print( "integr_rect4 =",integr_rect4(f,0,1,1e-5) ) | |
print( "integr_trap =",integr_trap(f,0,1,1e-5) ) | |
print( "valeur attendue =",pi/4-.5) | |
f = lambda x: sin(x)**2 | |
print( "integr_rect1 =",integr_rect1(f,0,pi/2,1e-5) ) | |
print( "integr_rect2 =",integr_rect2(f,0,pi/2,1e-5) ) | |
print( "integr_rect3 =",integr_rect3(f,0,pi/2,1e-5) ) | |
print( "integr_rect4 =",integr_rect4(f,0,pi/2,1e-5) ) | |
print( "integr_trap =",integr_trap(f,0,pi/2,1e-5) ) | |
print( "valeur attendue =",pi/4) |
# -*- coding: utf8 -*- | |
# résolution par dichotomie | |
# ========================= | |
# | |
# arguments : fonction, borne gauche, borne droite, epsilon | |
# | |
def solve_dichot(f,a,b,epsilon): | |
a,b = min(a,b), max(a,b) # on remet a et b dans le bon ordre | |
signe_a = f(a) < 0 # True si a est négatif | |
signe_b = f(b) < 0 # True si b est négatif | |
if not signe_a ^ signe_b: | |
raise Exception("les deux bornes n'encadrent pas un zéro de la fonction") | |
while b-a > epsilon: | |
c = (a+b)/2 | |
signe_c = f(c) < 0 | |
if signe_a ^ signe_c: | |
b = c # f(a) et f(c) sont de signes opposés | |
else: | |
a = c # f(a) et f(c) sont de signes identiques | |
return (a+b)/2 | |
# Newton-Raphson (avec la dérivée en argument) | |
# ============================================ | |
# | |
# arguments : fonction, dérivée, x initial, epsilon | |
# | |
def solve_newton1(f,ff,x,epsilon): | |
d = 8*epsilon # initialisation à une valeur "élevée" | |
while abs(d) > epsilon: | |
d = f(x)/ff(x) | |
x = x - d | |
return x | |
# Newton-Raphson (sans la dérivée en argument) | |
# ============================================ | |
# | |
# arguments : fonction, x initial, epsilon | |
# | |
def solve_newton2(f,x,epsilon): | |
d = 8*epsilon # initialisation à une valeur "élevée" | |
while abs(d) > epsilon: | |
deriv = ( f(x+epsilon/2.0) - f(x-epsilon/2.0) ) / epsilon | |
d = f(x)/deriv | |
x = x - d | |
return x | |
# test des fonctions | |
# ------------------ | |
from math import log | |
print( solve_dichot(lambda x: log(x) - 1, 2.0, 4.0, 1e-8) ) | |
print( solve_newton1(lambda x: log(x) - 1, lambda x: 1.0/x, 4.0, 1e-8) ) | |
print( solve_newton2(lambda x: log(x) - 1, 4.0, 1e-8) ) | |
from math import cos, sin | |
print( solve_dichot(lambda x: cos(x), 0.5, 3.0, 1e-8) ) | |
print( solve_newton1(lambda x: cos(x), lambda x: -sin(x), 0.5, 1e-8) ) | |
print( solve_newton2(lambda x:cos(x), 0.5, 1e-8) ) | |
import cProfile | |
cProfile.run("solve_dichot(lambda x: log(x) - 1, 2.0, 4.0, 1e-8)") | |
cProfile.run("solve_newton1(lambda x: log(x) - 1, lambda x: 1.0/x, 4.0, 1e-8)") | |
cProfile.run("solve_newton2(lambda x: log(x) - 1, 4.0, 1e-8)") |