Programmation Python pour les scientifiques

Utilisation de modules sous Python - Cours avec exercices corrigés

Jean-Philippe PREAUX

Ce cours a été préparé pour le niveau CPGE MPSI, il est enseigné au Lycée Thiers. Retrouvez les exercices corrigés accompagnant ce cours à la fin de chaque partie.

Retrouvez également les parties précédentes du cours :

- Premier contact

- Premiers programmes

- Listes et autres structures de données

Les commentaires et les suggestions d'amélioration sont les bienvenus, alors, après votre lecture, n'hésitez pas. Commentez

- Titre : Programmation Python pour les scientifiques

- Auteur : Jean-Philippe PREAUX

- Parution : 23 février 2015

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2015 Jean-Philippe PREAUX. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Utilisation d'un module

- I-A. Importer un module

- I-B. Exemple : le module random

- I-C. Application : méthode de Monte-Carlo

- II. NumPy et matplotlib

- II-A. Modules scientifiques

- II-B. Le module NumPy

- II-C. Le module matplotlib

- II-C-1. Illustration : approximation de pi

- III. Énoncés des exercices

- III-A. Systèmes linéaires d'équations

- III-B. Interpolation polynomiale

- III-C. Tracés avec pyplot

- III-D. Calcul d'aire d'une ellipse

- III-E. Tracé du graphe de la dérivée d'une fonction

- IV. Corrigés des exercices

- IV-A. Systèmes linéaires d'équations : solution

- IV-A-1. système d'équations 1

- IV-A-2. Système d'équations 2

- IV-B. Interpolation polynomiale : solution

- IV-C. Tracés avec pyplot : solution

- IV-D. Calcul d'aire d'une ellipse : solution

- IV-E. Tracé du graphe de la dérivée d'une fonction : solution

- V. Remerciements Developpez

I - Utilisation d'un module

I-A - Importer un module

Si le programme que vous rédigez est un peu long, vous voudriez peut-être le scinder en plusieurs fichiers pour maintenir le code plus facilement. Certains de ces fichiers contiendront alors des définitions de classes, constantes et fonctions spécialisées dans un certain domaine, et qui pourront être importées à la demande dans plusieurs programmes sans avoir besoin de recopier tout le code à chaque fois.

Ces fichiers qui peuvent constituer des bibliothèques logicielles sont appelés modules en Python. Un module peut alors être importé dans un autre module ou dans le module principal (main).

Tout programmeur Python peut réaliser un module et nous en avons même utilisés plusieurs provenant de la bibliothèque standard de Python :

- math : ensemble de fonctions mathématiques ;

- fractions : fonctions arithmétiques des nombres rationnels ;

- random : génération de nombres pseudoaléatoires ;

- time : fonctions de gestion du temps ;

- et bien d'autres encore, voir PyPI - the Python Package Index.

Pour importer un module :

- à l'aide de l'instruction from

importer une fonction ou constante

>>> from math import sqrt
>>> sqrt(2)
1.4142135623730951
>>> from math import cos, pi
>>> cos(pi/4)
0.7071067811865476

importer toute la bibliothèque

>>> from math import *
>>> sin(pi/4)
0.7071067811865476

- sans l'instruction from

>>> import math
>>> math.sqrt(2)
1.4142135623730951
>>> math.cos(math.pi/4)
0.7071067811865476

Fonctions et constantes doivent être précédées d'un préfixe : le nom du module suivi d'un point '.'.
La méthode import nom_du_module est généralement conseillée, car elle évite des conflits de noms potentiels (on sait toujours de quel module vient telle ou telle fonction).
On peut définir un alias à l'aide de l'instruction as quand un nom de module est un peu long :

>>> import numpy as np
>>> x = np.array([1, 2, 3])
>>> print x
[1 2 3]

I-B - Exemple : le module random

Voici quelques fonctions fournies par le module random :

randrange(a,b,k)

Choisit un entier int aléatoirement dans range(a,b,k)

randint(a,b)

Choisit un entier int aléatoirement dans [a, b]

choice(List)

Choisit un entier int aléatoirement dans la liste List

random()

Choisit un float aléatoirement dans [0, 1[

uniform(a,b)

Choisit un float aléatoirement dans [a, b[

Ici « aléatoirement » signifie selon une loi uniforme (quasiment).

Exemple : que fait le programme suivant ?

import random as rand
def de6(n):
tirs = [0, 0, 0, 0, 0, 0]
for i in range(n):
t = rand.randint(1,6)
tirs[t-1] += 1
for j in range(6):
tirs[j] = tirs[j]*100.0/n
tirs[j] = {:.2f}.format(tirs[j]) + '%' # 2 nombres après la virgule
return tirs

À l'aide de la méthode format pour le type str, l'expression {:.2f}.format(x), pour un float x, retourne une chaîne de caractères représentant l'écriture décimale du nombre x avec 2 chiffres après la virgule. Voir Format Specification Mini-Language.

Réponse : le programme simule n lancers d'un dé à six faces, et compte le nombre de fois où chaque face apparaît pour finalement retourner le pourcentage d'apparition de chaque face.

Maintenant, vérifions le théorème des grands nombres : pour un grand nombre de tirs, les fréquences d'apparition de chaque face devraient tendre vers leur probabilité de tir, ici donc être égales (la loi est uniforme : le dé est non pipé).

>>> de6(10)
['30.00%', '0.00%', '20.00%', '20.00%', '10.00%', '20.00%']
>>> de6(100)
['10.00%', '22.00%', '19.00%', '20.00%', '15.00%', '14.00%']
>>> de6(1000)
['16.00%', '15.40%', '16.10%', '16.90%', '18.50%', '17.10%']
>>> de6(10000)
['16.45%', '16.66%', '16.50%', '16.84%', '17.37%', '16.18%']
>>> de6(100000)
['16.57%', '16.67%', '16.80%', '16.62%', '16.66%', '16.68%']
>>> de6(1000000)
['16.65%', '16.69%', '16.66%', '16.64%', '16.63%', '16.74%']
>>> de6(10000000)
['16.66%', '16.66%', '16.65%', '16.66%', '16.69%', '16.68%']

I-C - Application : méthode de Monte-Carlo

Les méthodes de simulation de Monte-Carlo permettent le calcul approché de valeurs numériques par des procédés aléatoires. Elles sont particulièrement employées pour le calcul approché d'intégrales en dimension supérieure à 1 (pour le calcul d'aire, de volume).

Le calcul approché d'intégrales de fonctions réelles d'une variable repose sur le résultat suivant :

Pour n suffisamment grand, et pour , une variable aléatoire suivant une loi uniforme sur l'intervalle [a, b] (c'est-à-dire n points tirés au hasard dans [a, b] selon une loi uniforme), alors avec une probabilité proche de 1 :

Exercice : écrire une fonction montecarlo(f, a, b, n) qui retourne une valeur approchée de l'intégrale de f sur [a, b] selon la méthode de Monte-Carlo et avec n points.

Cliquez sur l'icône pour dévoiler la solution.

import random as rand
def montecarlo(f, a, b, n): # Calcul approché de l'intégrale de f sur [a, b]
s = 0
for i in range(n):
x = rand.uniform(a, b)
s += f(x)
s *= (b-a)/float(n)
return s

Par exemple avec sur [0, 1] le résultat devrait être proche de  :

>>> f = lambda x:x**2
>>> montecarlo(f, 0, 1, 100)
0.32889436948779177
>>> montecarlo(f, 0, 1, 1000)
0.3400354481596589
>>> montecarlo(f, 0, 1, 1000)
0.31687077247647943
>>> montecarlo(f, 0, 1, 10000)
0.3347958934090399
>>> montecarlo(f, 0, 1, 100000)
0.3328616254606106

En Python, une fonction lambda est une fonction anonyme (à laquelle on n'a pas donné de nom), et qu'on peut appliquer « à la volée » dans une expression. Ainsi, les constructions suivantes sont équivalentes :

>>> def f(x) :
return x**2
>>> f(3)
9

avec lambda

>>> f = lambda x : x**2
>>> f(3)
9
>>> (lambda x : x**2)(3)
9

Nous aurions pu alors utiliser une construction plus compacte, en déclarant la fonction « à la volée » :

>>> montecarlo(lambda x : x**2, 0, 1, 100000)
0.3328616254606106

Exercice : en déduire un calcul approché de par la méthode de Monte-Carlo.

Avec , l'intégrale sur [0, 1] vaut (aire d'un quart du disque unitaire).

>>> f = lambda x : 4*(1-x**2)**0.5
>>> montecarlo(f, 0, 1, 100000)
3.1427991454635724
>>> montecarlo(f, 0, 1, 10000000)
3.1413319841070737
>>> pi
3.141592653589793

II - NumPy et matplotlib

II-A - Modules scientifiques

Il existe de nombreux modules scientifiques sous Python :

- NumPy : puissant outil pour créer, manipuler, et appliquer de nombreuses opérations sur des tableaux de nombres (matrices). Stable et bien documenté ;

- SciPy : fonctions mathématiques puissantes s'appliquant aux tableaux générés par NumPy. C'est la boîte à outil numérique pour les tableaux NumPy. Elle contient des opérations spécifiques (algèbre linéaire, statistique…) de manipulation de tableaux, de plus haut niveau que celles de NumPy ;

- matplotlib : permet le tracé de graphes de fonctions.

Nous allons voir de plus près les modules NumPy et matplotlib.

II-B - Le module NumPy

Le module NumPy permet de créer, de manipuler, des tableaux de nombres, ou matrices, et de leur appliquer des opérations mathématiques courantes.

La fonction array() permet de créer un tableau, ou array, à partir d'un tableau Python c'est-à-dire d'une liste de listes de nombres (de même longueur) :

>>> import numpy as np
>>> A = np.array([[1,1,1],[0,1,1],[0,0,1]])
>>> A
array([[1, 1, 1],
[0, 1, 1],
[0, 0, 1]])
>>> print A
[[1 1 1]
[0 1 1]
[0 0 1]]

La fonction arange() crée une matrice ligne de façon assez analogue à la façon dont range() crée une liste, à ceci près que les coefficients ne sont pas forcément entiers :

>>> v = np.arange(0, 1.5, 0.5)
>>> v
array([ 0., 0.5, 1. ])
>>> 2*v
array([ 0., 1., 2. ])
>>> -2*v + 10
array([ 10., 9., 8. ])

On peut appliquer sur les tableaux de nombreuses opérations arithmétiques, certaines étant comprises terme à terme.

On accède aux éléments d'un tableau comme en Python, grâce à un indice entre crochets :

>>> A[0], A[1]
(array([1, 1, 1]), array([0, 1, 1]))
>>> A[1][0]
0

On peut échantillonner (slicing) :

>>> A[0:1]
array([[1, 1, 1]])
>>> A[::-1]
array([[0, 0, 1],
[0, 1, 1],
[1, 1, 1]])

Le type d'une matrice s'obtient grâce à la fonction shape(), son nombre d'éléments grâce à size(). La fonction reshape() permet de changer la forme (=type) d'une matrice :

>>> L=np.arange(0,10)
>>> np.size(L)
10
>>> np.reshape(L,(2,5))
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> L
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> M = np.reshape(L,(2,5)) ; np.shape(M)
(2, 5)

Le produit matriciel s'obtient à l'aide de la fonction dot(). Si le deuxième argument est une matrice ligne, dot() la traitera si besoin est comme une matrice colonne, ou vecteur, en la transposant. C'est en effet plus pratique de saisir v= np.arange(0,3) ou v=array([0, 1, 2]) que v=array([[0],[1],[2]]).

Exemple : avec et .

Le produit n'est pas défini ; le produit . Le produit .

Voilà ce que dot() retourne :

>>> np.dot(A,v)
array([3, 3, 2])
>>> np.dot(v,A)
array([0, 1, 3])

On le voit, lorsque la multiplication est impossible, pour , la fonction effectue , qui a retourné pour résultat .

On pourra saisir les « vecteurs » sous forme de matrice ligne (leur transposée). Ce fonctionnement est commun aux logiciels de calcul sur des matrices (Matlab et Scilab).

Pour effectuer le produit scalaire de deux « vecteurs », utiliser la fonction vdot().

La fonction transpose() permet d'obtenir la transposée :

>>> np.transpose(A)
array([[1, 0, 0],
[1, 1, 0],
[1, 1, 1]])

La transposée d'un « vecteur » est encore un « vecteur ».

Attention, l'opération A ** 2 correspond à une élévation au carré terme à terme :

>>> A ** 2
array([[1 1 1]
[0 1 1]
[0 0 1]])
>>> (2*A) ** 2
array([[4 4 4]
[0 4 4]
[0 0 4]])

Pour élever A au carré, faire plutôt :

>>> np.dot(A,A)
array([[1, 2, 3],
[0, 1, 2],
[0, 0, 1]])

Pour élever une matrice carrée A à une puissance n :

>>> B = A
>>> for i in range(1,n):
B = np.dot(A,B) # à la sortie de boucle B contient A^n

De même l'inversion A ** -1 se fait terme à terme. Elle produira ici une erreur (division par 0) alors même que la matrice A est inversible.

Certaines fonctions plus spécifiques sont disponibles dans un sous-module. Pour l'algèbre linéaire. C'est le sous-module linalg de NumPy. Toutes les fonctions de ce sous-module devront être saisies avec le préfixe np.linalg.

Pour l'inversion de matrice : utiliser la fonction inv() du sous-module linalg :

>> np.linalg.inv(A)
array([[ 1., -1., 0.],
[ 0., 1., -1.],
[ 0., 0., 1.]])

Le sous-module linalg contient aussi, entre autres :

1. La fonction det() qui retourne le déterminant d'une matrice ;

2. La fonction solve(A, b) qui résout le système linéaire de matrice A et de second membre b (vecteur ou ligne).

Exemple : résoudre le système linéaire :

Solution : cliquez sur l'icône pour dévoiler le code.

>>> A = np.array([[1,-1,1], [-1,1,1], [2,-1,-1]])
>>> b = np.array([1,1,0])
>>> np.linalg.solve(A, b) # avec solve()
array([ 1., 1., 1.])
>>> np.dot(np.linalg.inv(A), b) # en inversant A
array([ 1., 1., 1.])

array(liste)

Crée un tableau à partir d'une liste.

arange(a, b, k)

Crée un vecteur dont les coefficients sont les a+k.N entre a (inclus) et b (exclu).

linspace(a, b, n)

Crée un vecteur de n valeurs régulièrement espacées entre a et b (inclus).

zeros(p)

Crée un tableau de taille p rempli de zéros.

zeros((p, q))

Crée un tableau de taille (p, q) rempli de zéros.

ones(p)

Crée un tableau de taille p rempli de uns.

ones((p, q))

Crée un tableau de taille (p, q) rempli de uns.

shape()

Pour obtenir la taille d'un tableau (= type d'une matrice).

size()

Pour obtenir le nombre d'éléments d'un tableau.

reshape()

Pour redimensionner un tableau.

dot()

Pour effectuer un produit matriciel de deux matrices.

vdot()

Pour effectuer un produit scalaire de deux « vecteurs ».

transpose()

Pour transposer une matrice.

rank()

Rang d'une matrice.

mean()

Valeur moyenne d'un tableau.

odeint()

Pour intégrer une équation différentielle.

linalg :

inv()

Inversion d'une matrice.

det()

Déterminant d'une matrice.

solve(A, b)

Résolution du système linéaire Ax=b.

NumPy contient aussi constantes et fonctions mathématiques usuelles.

II-C - Le module matplotlib

Pour le simple tracé de courbes, nous n'utiliserons que le sous-module pyplot importé, avec alias, à l'aide de la commande :

>>> import matplotlib.pyplot as pp

Voir la documentation Matplotlib.

● Les fonctions essentielles de pyplot sont :

- plot() pour le tracé de points, de courbes ;

- show() pour afficher le graphique créé.

● Utiliser plot() avec :

- en premier argument la liste des abscisses ;

- en deuxième argument la liste des ordonnées ;

- en troisième argument (optionnel) le motif des points :

- '.' pour un petit point,

- 'o' pour un gros point,

- '+' pour une croix,

- '*' pour une étoile,

- '-' points reliés par des segments,

- '--' points reliés par des segments en pointillés,

- '-o' gros points reliés par des segments (on peut combiner les options),

- 'b', 'r', 'g', 'y' pour de la couleur (bleu, rouge, vert, jaune, etc.).

Voir la documentation pyplot.

Exemple : pour le tracé d'un nuage de points, le code saisi en ligne de commande suivant

>>> import matplotlib.pyplot as pp
>>> abs = [0, 1, 2, 3, 4, 5]
>>> ord = [0, 1, 1.5, 1, 2.5, 2]
>>> pp.plot(abs, ord, 'o')
[<matplotlib.lines.Line2D object at 0x10c6610d0>]
>>> pp.show()

va produire un graphique (au format .png) :

Exemple : pour le tracé d'une ligne brisée :

>>> import matplotlib.pyplot as pp
>>> abs = [n/2. for n in range(10)]
>>> ord = [n % 2 for n in range(10)]
>>> pp.plot(abs,ord,'-b')
[<matplotlib.lines.Line2D object at 0x10dd1fa10>]
>>> pp.show()

Exemple : pour le tracé de courbes représentatives de fonctions réelles :

>>> import matplotlib.pyplot as pp
>>> import numpy as np # pour linspace() et les fonctions mathématiques
>>> X = np.linspace(0, 2*np.pi, 256) # X = 256 pts régulièrement espac#es
>>> Ycos = np.cos(X) # image directe de X par cos
>>> Ysin = np.sin(X) # image directe de X par sin
>>> pp.plot(X,Ycos,'b') # tracé de la courbe de cos en bleu
[<matplotlib.lines.Line2D object at 0x10d5e2b50>]
>>> pp.plot(X,Ysin,'r') # tracé de la courbe de sin en rouge
[<matplotlib.lines.Line2D object at 0x1073aad90>]
>>> pp.show()

On améliore le tracé en remplissant quelques options avant de le sauvegarder (au format .png dans le répertoire utilisateur).

>>> pp.plot(X, Ycos, 'b', X, Ysin, 'r') # Tracé simultané des deux courbes
>>> pp.grid(True) # Affiche la grille
>>> pp.legend(('cos','sin'), 'upper right', shadow = True) # Légende
>>> pp.xlabel('axe des x') # Label de l'axe des abscisses
>>> pp.ylabel('axe des y') # Label de l'axe des ordonnées
>>> pp.title('Fonctions cosinus et sinus') # Titre
>>> pp.savefig('ExempleTrace') # sauvegarde du fichier ExempleTrace.png
>>> pp.show()

On peut tout aussi bien tracer des courbes paramétrées :

>>> T = np.linspace(0,2*np.pi,256) # paramètre t
>>> X = [ t * np.cos(t) for t in T ] # x(t) = t.cos(t)
>>> Y = [ t * np.sin(t) for t in T ] # y(t) = t.sin(t)
>>> pp.plot(X,Y,'b') # Tracé de la courbe paramétrée {(x(t),y(t))}
[<matplotlib.lines.Line2D object at 0x10c044ed0>]
>>> pp.show()

Exemple : tracé du cercle unitaire :

>>> T = np.linspace(0,2*np.pi,256) # paramètre t
>>> X = np.cos(T) # x(t) = cos(t)
>>> Y = np.sin(T) # y(t) = sin(t)
>>> pp.plot(X,Y,'b') # Tracé de la courbe paramétrée {(x(t),y(t))}
>>> pp.axis('equal') # Pour que le repère soit orthonormé
>>> pp.title('Le cercle unitaire')
>>> pp.show()

II-C-1 - Illustration : approximation de pi

Encore une approximation de par une méthode de type Monte-Carlo, mais avec illustration graphique.

On tire au sort N points dans le domaine carré [−1, 1] × [−1, 1] selon une loi uniforme. La probabilité pour un point d'être choisi dans le disque unitaire est égale au quotient de l'aire du disque unitaire par l'aire du domaine carré, soit :

Ainsi d'après le théorème des grands nombres, si l'on tire un grand nombre de points, c'est-à-dire si N est suffisamment grand, la proportion des points tirés se trouvant dans le disque unitaire, avec , est presque sûrement proche de .

import matplotlib.pyplot as pp # pyplot
import numpy as np # numpy
import random as rand # random

def monpi(N):
X = [rand.uniform(-1,1) for i in range(N)] # choix aléatoire
Y = [rand.uniform(-1,1) for i in range(N)]
oui = non = 0 # Calcul de la proportion dans le disque
for i in range(N):
if X[i]**2 + Y[i]**2 <= 1:
oui += 1
else:
non += 1
print 'approximation de pi trouvée :' # impression du résultat
print 4 * oui / float(oui+non)
print np.pi
# Tracé du graphique
pp.plot([-1,1,1,-1,-1],[-1,-1,1,1,-1], 'b-') # tracé du carré
T = np.linspace(0,2*np.pi,256)
Xdisk = np.cos(T)
Ydisk = np.sin(T)
pp.plot(Xdisk,Ydisk,'b') # tracé du disque
for i in range(N): # tracé du nuage de points
if X[i]**2 + Y[i]**2 <= 1:
pp.plot([X[i]],[Y[i]], 'g+') # vert si dedans
else:
pp.plot([X[i]],[Y[i]], 'r+') # rouge si dehors
pp.axis('equal')
pp.show()

>>> monpi(10000)
approximation de pi trouvée :
3.152
3.14159265359

III - Énoncés des exercices

III-A - Systèmes linéaires d'équations

À l'aide de Numpy, résoudre les systèmes d'équations linéaires suivants d'inconnues de deux façons différentes, avec ou sans le module linalg de NumPy. Que constatez-vous ?

2. avec

Solution

III-B - Interpolation polynomiale

Déterminer tous les polynômes de degré au plus 2 prenant pour valeur 1, 4 et 3 respectivement en 0, 1 et 2.

Solution

III-C - Tracés avec pyplot

Tracer à l'aide de pyplot :

1. La courbe représentative de la fonction  ;

2. Les courbes représentatives de et de pour  ;

3. La courbe paramétrée pour  ;

4. L'ellipse de grand axe et de petit axe .

Solution

III-D - Calcul d'aire d'une ellipse

Calculer une valeur approchée de l'aire de l'ellipse représentée dans l'exercice précédent.

On peut appliquer la méthode des trapèzes déjà étudiée.

Solution

III-E - Tracé du graphe de la dérivée d'une fonction

Écrire une fonction trace(f,a,b) qui trace à l'aide de pyplot les courbes représentatives d'une fonction réelle f dérivable sur [a, b] et de sa dérivée. f sera définie à l'aide de l'instruction lambda et l'on s'interdira d'utiliser le module de calcul formel SymPy.

Solution

IV - Corrigés des exercices

IV-A - Systèmes linéaires d'équations : solution

IV-A-1 - système d'équations 1

On peut utiliser la fonction solve() du sous-module linalg de NumPy :

import numpy as np
def reponse():
A = np.array([[1,1,1],[1,-2,1],[2,-1,1]])
B = np.array([1,0,2])
return np.linalg.solve(A,B)

>>> reponse()
array([ 1.66666667, 0.33333333, -1. ])

La solution exacte est . En effet les solutions sont rationnelles (car tous les coefficients du système sont entiers), à petit dénominateur (on peut prendre pour dénominateur le déterminant de la matrice du système).

IV-A-2 - Système d'équations 2

avec

Soit A la matrice du premier système, U = (a; b; c) et X = (x; y; z). Alors, U = A.X

Soit B la matrice du second système et V = (3; 3; 1). Alors, V = B.U

Première solution : à l'aide de solve(). On trouve d'abord U pour en déduire ensuite X :

>>> A = np.array([[1,1,1],[1,-2,1],[2,-1,1]])
>>> B = np.array([[3,1,-1],[1,1,1],[1,-2,2]])
>>> V = np.array([3,3,1])
>>> U = np.linalg.solve(B,V)
>>> np.linalg.solve(A,U)
array([ 0., -0., 1.])

Ainsi (0; 0; 1) est solution (remarquer les 0. et -0. apparaissant). La solution est correcte. Avec ces valeurs, on trouve a = b = c = 1 qui est bien solution du deuxième système.

Deuxième solution : à l'aide de inv(). On vérifie que A et B sont inversibles grâce à la fonction det() qui donne le déterminant (A est inversible si, et seulement si, det(A) ≠ 0). Alors, X = A−1U = A−1B−1V

>>> a = np.linalg.inv(A)
>>> b = np.linalg.inv(B)
>>> np.dot(np.dot(a,b),V)
array([ -2.22044605e-16, -1.11022302e-16, 1.00000000e+00]

On ne trouve pas la valeur exacte, mais seulement une valeur approchée à 10−15 près. L'inversion des matrices a inséré des erreurs d'arrondis qui se sont propagées et amplifiées. La fonction solve() s'avère plus efficace.

IV-B - Interpolation polynomiale : solution

Cela revient à déterminer tous les triplets de réels (a; b; c) tels que le polynôme prenne les valeurs 1, 4, 3 en 0, 1 et 2. C'est-à-dire les (a; b; c) solutions du système linéaire :

Soit,

>>> A = np.array([[1,0,0],[1,1,1],[1,2,4]])
>>> V = np.array([1,4,3])
>>> np.linalg.solve(A,V)
array([ 1., 5., -2.])

Il n'y a qu'une solution : c'est le polynôme .

IV-C - Tracés avec pyplot : solution

Fonction  :

>>> import matplotlib.pyplot as pp
>>> import numpy as np
>>> X = np.linspace(-5,5,1000)
>>> Ytan = np.tan(X)
>>> pp.plot(X,Ytan,'b')
>>> pp.grid(True)
>>> pp.show()

Fonction  :

>>> X = np.linspace(0,10,1000)
>>> Yln = np.log(X)
main :1: RuntimeWarning: divide by zero encountered in log
>>> X = X[1:] # Slicing pour éviter le premier nombre, 0.
>>> Yln = np.log(X)
>>> pp.plot(X,Yln,'b')
>>> pp.grid(True)
>>> pp.show()

De même pour la fonction  :

>>> X = np.linspace(0,10,1000)
>>> X = X[1:] # Slicing pour éviter le premier nombre, 0.
>>> Y = [np.sin(x)/float(x) for x in X]
>>> pp.plot(X,Y)
>>> pp.grid(True)
>>> pp.show()

Tracé de la courbe paramétrée :

pour

>>> import numpy as np
>>> import matplotlib.pyplot as pp
>>> T = np.linspace(0,10,256)
>>> X = T * np.cos(T)
>>> Y = T * np.sin(T)
>>> pp.plot(X,Y,'b')
>>> pp.grid(True)
>>> pp.axis('equal')
>>> pp.show()

Pour une ellipse :

>>> a = 2; b = 1
>>> T = np.linspace(0,2*np.pi,1000)
>>> pp.plot(a*np.cos(T),b*np.sin(T),'b')
>>> pp.grid(True)
>>> pp.show()

IV-D - Calcul d'aire d'une ellipse : solution

De l'équation découle que les parties supérieure et inférieure de l'ellipse ont pour équation .

Ainsi l'aire de l'ellipse est :

>>> a = 2 ; N = 100
>>> f = lambda x: (a**2-x**2)**0.5
>>> X = np.linspace(-a,a,N) # N pts régulièrement espacés
>>> X = X[1:-1] # On supprime les 1er et dernier éléments
>>> Y = f(X) # Images par f
>>> 2 * 2 * a / float(N) * (sum(Y) + (f(-a) + f(a)) / 2.)
12.4273434352

IV-E - Tracé du graphe de la dérivée d'une fonction : solution

def derive(f,x,h): # Calcul approché de la dérivée en 1 point
return (f(x+h)-f(x-h))/float(2*h)

import numpy as np
import matplotlib.pyplot as pp

def trace(f,a,b):
N = 100
X = np.linspace(a,b,N)
Yf = f(X)
Yd = np.empty(N) # tableau vide de N éléments
for i in range(N):
Yd[i] = derive(f,X[i],0.01)
pp.plot(X,Yf,'b',X,Yd,'r')
pp.grid(True)
pp.legend(('fonction','derivée'),'lower right')
pp.show()

En utilisant le calcul sur les tableaux, plutôt qu'en calculant la dérivée en chaque point à l'aide d'une boucle for.

def derive(f,x,h=0.01): # Calcul approché de la dérivée
return (f(x+h)-f(x-h))/float(2*h)

import numpy as np
import matplotlib.pyplot as pp

def trace(f,a,b):
N = 100
X = np.linspace(a,b,N)
Yf = f(X)
Yd = np.empty(N)
Yd = derive(f,X) # Le 2e argument passé est un tableau
pp.plot(X,Yf,'b',X,Yd,'r')
pp.grid(True)
pp.legend(('fonction','derivée'),'lower right')
pp.show()

>>> f = lambda x: x**3
>>> trace(f,-4,4)

Tracé des graphes de et de sa dérivée sur [−4, 4] :

V - Remerciements Developpez

Nous remercions Jean-Philippe Préaux pour la publication de ces cours avec exercices sur Developpez. Merci à toute l'équipe de rédaction ayant contribué à cette publication et particulièrement à f-leb et -Nikopol-. Un grand merci également à Claude Leloup pour ses corrections orthographiques.