Simulation Numérique
Simulation Numérique
Simulation Numérique
Applications
Aide-Mémoire pour la préparation de l’épreuve
d’Informatique du Concours National d’Entrée aux
Ecoles d’Ingénieurs BG 2020
Elaboré par :
-- Avril 2020 --
[Tapez ici]
Préambule
Ce document est destiné aux étudiants de deuxième année BG des Instituts Préparatoires
aux Etudes d’Ingénieurs.
Le but de ces supports est d’accompagner les étudiants de tout le territoire Tunisien dans
leur révision en leur fournissant à tous les mêmes documents, afin d’assurer une équité
entre eux, qu’ils bénéficient ou non d’un enseignement ou tutorat à distance.
Toutefois, ces documents sont considérés comme des aide-mémoires et ne remplacent pas
les cours assurés en présentiel.
Pour les différentes bibliothèques, quelques fonctions seulement parmi les plus utilisées
sont décrites. Aussi, toutes les applications présentées sont données juste à titre d’exemple
et ne constituent en aucun cas un ensemble complet.
I Introduction
Python offre une panoplie de bibliothèques intéressantes pour, entre autres, la simulation numérique et le calcul
scientifique. Dans ce but, nous exposerons dans ce qui suit les principales fonctionnalités de Numpy, Matplotlib
et Scipy. Nous présenterons ensuite des applications liées au traitement d’image et à la bio-informatique, en plus
de plusieurs exercices d’application avec leurs corrigés.
>>>import numpy as np
>>>a=np.array([1,4,5,8])
>>>b=np.array([[1,2],[3,4],[5,6]],dtype=float)
>>>c=np.array([[[1,2],[1,2]],[[1,2],[1,2]]])
>>>print(a)
[1 4 5 8]
>>>print(b)
[[ 1. 2.]
[ 3. 4.]
[ 5. 6.]]
>>>print(c)
[[[1 2]
[1 2]]
[[1 2]
[1 2]]]
>>>c[1,1,1]
2
Nous limiterons notre propos aux tableaux uni et bi-dimensionnel appelés aussi vecteurs et matrices.
II.1.1 Vecteurs
En Python la fonction numpy.array permet de créer un vecteur qui est un tableau à une dimension. Pour
créer un vecteur il suffit de passer l'itérable contenant les éléments comme argument.
Les fonctions size retourne le nombre d’éléments d’un vecteur et la fonction ndim retourne la dimension
qui est 1 dans le cas d’un vecteur (2 pour une matrice).
Les fonctions empty, zeros, ones, arange, linspace permettent aussi la création de vecteurs
particuliers.
Empty Construit un vecteur non initialisé (le contenu est totalement np.empty(taille)
imprédictible ou aléatoire).
Exemple
>>>v1=np.linspace(-1,1,10)
>>>print(v1)
[-1. -0.77777778 -0.55555556 -0.33333333 -0.11111111 0.11111111
0.33333333 0.55555556 0.77777778 1. ]
>>>v2=np.arange(10)
>>>print(v2)
[0 1 2 3 4 5 6 7 8 9]
>>>type(v2)
<type 'numpy.ndarray'>
>>>v3=np.arange(2,10,2)
>>>print(v3)
[2 4 6 8]
>>>v4=np.zeros(8);v5=np.ones(6,dtype=int)
>>>print(v4);print(v5)
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[1 1 1 1 1 1]
1
Les opérations sur les vecteurs sont possibles avec les opérateurs classiques de Python, tels que décrit ci-
dessous.
>>>u=np.array([1,2,3,4]);v=np.array([5,6,7,8])
>>>u+v
>>>v-u
>>>u*2
>>>v**3
>>>u*v
>>>v/u
II.1.2 Matrices
Pour créer une matrice en Python, qui est un tableau à deux dimensions, il suffit de passer un itérable
d'itérables (liste de listes, liste de tuples, tuple de tuples, etc.) comme argument à la fonction array.
Les fonctions size, shape et ndim retournent respectivement le nombre d’élément, nombre de
lignes/colonnes et la dimension. Par exemple :
La fonction reshape permet de redimensionner un vecteur ou une matrice, comme décrit ci-après :
>>>m1=np.reshape(np.arange(10),(2,5))
#ou bien m1 = np.arange(10).reshape((2,5))
>>>print(m1)
[[0 1 2 3 4]
[5 6 7 8 9]]
>>>m.reshape(2,3)
array([[ 1.2, 2.5, 3.2],
[ 1.8, 1.1, 4.3]])
Les fonctions empty, zeros, ones, eye et diag permettent de créer des matrices particulières.
ones Construit une matrice dont les éléments sont tous 1 np.ones((l,c))
Exemple
>>>m2=np.zeros((2,4));m3=np.ones((3,3),dtype=int);
>>>m4=np.eye(4); m5=np.diag([1,2,3])
>>> print('m2=',m2);print('m3=',m3);print('m4=',m4);print('m5=',m5)
m2= [[0. 0. 0. 0.]
[0. 0. 0. 0.]]
m3= [[1 1 1]
[1 1 1]
[1 1 1]]
m4= [[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
m5= [[1 0 0]
[0 2 0]
[0 0 3]]
L’accès à un élément d’une matrice se fait à l’aide d’indexage 𝐴[𝑖, 𝑗] où 𝑖 désigne la ligne et 𝑗 la colonne. On
peut également récupérer une partie d’une matrice : ligne, colonne et sous-matrice. Par exemple :
>>>A=np.array([[1,2,3],[4,5,6],[7,8,9]],dtype=int)
>>>A[1,0];A[2,2]
4
9
>>>A[0,:];A[:,1]
array([1, 2, 3])
array([2, 5, 8])
>>>A[0:1,:];A[:,1:2]
array([[1, 2, 3]])
array([[2],
[5],
[8]])
Les opérations algébriques sur les matrices sont possibles avec les opérateurs classiques de Python.
>>>A+A
array([[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]])
>>>A-A
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
>>>A*2
array([[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]])
Pour le produit matriciel, il faut utiliser la fonction dot, comme l’exemple suivant :
La trace et la transposé s’obtiennent avec les fonctions trace et transpose. Par exemple :
Le déterminant, le rang, l’inverse, les valeurs propres et les vecteurs propres s’obtiennent respectivement par
les fonctions det, matrix_rank, inv, eigvals et eig du module numpy.linalg. Par exemple :
>>>np.linalg.det(A)
6.66133814775e-16
>>>np.linalg.matrix_rank(A)
2
>>>np.linalg.inv(A)
[[ -4.50359963e+15 9.00719925e+15 -4.50359963e+15]
[ 9.00719925e+15 -1.80143985e+16 9.00719925e+15]
[ -4.50359963e+15 9.00719925e+15 -4.50359963e+15]]
>>>np.linalg.eigvals(A)
[ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]
>>>np.linalg.eig(A)
(array([ 1.61168440e+01, -1.11684397e+00, -1.30367773e-15]),
array([[-0.23197069, -0.78583024, 0.40824829],
[-0.52532209, -0.08675134, -0.81649658],
[-0.8186735 , 0.61232756, 0.40824829]]))
Pour finir, la fonction solve du module numpy.linalg permet de résoudre le système linéaire 𝐴 ⋅ 𝑥 = 𝑏
>>>print(np.linalg.solve(A,np.array([1,0,1])))
[ -9.00719925e+15 1.80143985e+16 -9.00719925e+15]
Cette fonction peut être utilisée de nombreuses manières différentes, pour obtenir des résultats assez fins.
L’idée générale est de lui donner en argument deux tableaux de nombres, décrivant respectivement les
abscisses et les ordonnées des points à tracer. Sans autre option, ces points sont reliés par des segments
bleus, en traits pleins.
Exemple 1
Les options graphiques permettent notamment de modifier le type de segment (pointillés, sans segment),
d’afficher ou non un marqueur au niveau de chaque point et de changer la couleur de ces objets.
Exemple 2
On peut enfin appeler plusieurs fois la fonction plot successivement. Les tracés sont alors superposés.
Exemple 3
Pour tracer une fonction, on trace en fait des cordes de cette fonction, à partir d’une subdivision de
l’intervalle considéré. La fonction linespace() de la bibliothèque numpy permet de créer automatiquement
de telles subdivisions, avec un nombre de points à régler manuellement.
Exemple
Pour tracer le graphe de la fonction 𝑥 ↦ 𝑥 sur [0,1] avec une subdivision en 100 segments, donc en utilisant
101 points, on peut utiliser le code suivant :
II.3.1 Présentation
Scipy est une bibliothèque numérique d’algorithmes et de fonctions mathématiques, basée sur les tableaux,
complétant ou améliorant (en termes de performance) les fonctionnalités de la bibliothèque numpy.
La librairie Scipy contient de nombreuses boîtes à outils consacrées aux méthodes de calcul scientifique :
- Fonctions spéciales : scipy.special (fonctions de Bessel, erf, gamma, etc.)
- Intégration numérique : scipy.integrate (intégration numérique ou d’équations différentielles)
- Méthodes d’optimisation : scipy.optimize (minimisation, moindres-carrées, zéros d’une fonction)
- Interpolation : scipy.interpolate
- Transformées de Fourier : scipy.fftpack
- Traitement de signal : scipy.signal (convolution, corrélation, filtrage, ondelettes, etc.)
- Algèbre linéaire : scipy.linalg
- Statistiques : scipy.stats (fonctions et distribution statistiques)
- Traitement d’images multidimensionnelles : scipy.ndimage
- Entrées/Sorties : scipy.io
Ce module propose des fonctions qui permettent de déterminer des valeurs approchées des zéros d’une
fonction :
- fsolve : déterminer la racine d’une équation scalaire ou vectorielle.
- bisect : permet d’implémenter la méthode de recherche par dichotomie.
- newton : permet d’implémenter la méthode de recherche newton.
Exemple
L’extension scipy.integrate propose des fonctions pour calculer des intégrales simples, doubles ou
même triples et aussi de résoudre des équations différentielles de premier ou second ordre.
Exemple
import math
import scipy.integrate as spi
h = lambda x:math.cos(x)
y=spi.quad(h,0.0,math.pi/2.0)
>>>y
(0.9999999999999999, 1.1102230246251564e-14)
La fonction odeint résout numériquement des équations différentielles avec des conditions initiales de la
forme : = 𝑓(𝑦(𝑡), 𝑡)
La représentation graphique des solutions de cette résolution peut être donnée par :
Remarque : Sur une image en niveaux de gris, chaque pixel est ou bien noir (0) ou bien blanc (255) ou bien
possède un niveau de gris entre les deux. Cela signifie que les trois composantes R, G, B ont la même valeur.
Dans la suite de cette partie, les traitements ne s’appliquent qu’à des images en niveaux de gris, il est possible
d’opérer sur des images couleurs en appliquant les traitements proposés sur chacune des trois couleurs du
triplet.
>>>import numpy as np
>>>import matplotlib.pyplot as plt
>>>check=np.zeros((8,8,3),dtype='uint8') #exemple pour image couleur
>>>check[:,1:,::2]=255
>>>plt.imshow(check)
>>>plt.show()
Contraste :
Le contraste peut être modifié par l’application de fonctions mathématiques. Par exemple, en remplaçant la
valeur de chaque pixel par sa racine carrée, l’image assombrie alors qu’elle s’éclaircit si la valeur du pixel
est remplacée par son carré. Ces fonctions ont pour effet de diminuer le contraste.
Une autre idée consiste à faire un réajustement linéaire des valeurs des pixels selon :
𝑓: [0,256[ → [0,256[
𝑦 = 𝑥 + 0,4. (𝑥 − 127) 𝑠𝑖 𝑦 ∈ [0,255]
𝑥 ↦ 0 𝑠𝑖 𝑦 < 0
255 𝑠𝑖 𝑦 > 255
Il s’agit d’augmenter l’écart entre la valeur du pixel et la valeur moyenne (127) pour une image dont les
valeurs sont comprises entre 0 et 255. Cette fonction permet d’augmenter le contraste, les "noirs" sont plus
noirs et les "blancs" plus blancs.
2. Ecrire le script de la fonction Python permettant de modifier le contraste d’une image donnée.
5. Ecrire le script de la fonction Python permettant de filtrer une image donnée en utilisant la méthode de
moyennage.
En effectuant cette opération pour chaque pixel, on supprime une partie du bruit, car ce bruit est constitué de
fluctuations aléatoires, qui sont diminuées par un calcul de moyennes.
Le moyennage des pixels est très efficace pour enlever le bruit dans les images, malheureusement il détruit
également une grande partie de l’information de l’image. On peut en effet s’apercevoir que les images
obtenues par moyennage sont floues. Ceci est en particulier visible près des contours, qui ne sont pas nets.
Afin de réduire ce flou, il faut remplacer le moyennage par une opération un peu plus complexe, que l’on
nomme médiane. Etant donné la valeur a d’un pixel, et les valeurs b, c, d, e, f, g, h, i, on commence par les
classer par ordre croissant.
La médiane des neuf valeurs a, b, c, d, e, f, g, h, i est la 5ème valeur de ce classement (c’est-à-dire la valeur
centrale de ce classement).
6. Ecrire le script de la fonction Python permettant de filtrer une image donnée en utilisant la méthode de
médiane.
Détection de contours :
Pour localiser des objets dans les images, il est nécessaire de détecter les bords de ces objets. Ces bords
correspondent à des zones de l’image où les valeurs des pixels changent rapidement.
Afin de savoir si un pixel avec une valeur a est le long d’un bord d’un objet, on prend en compte les valeurs
b, c, d, e de ses quatre voisins (deux horizontalement et deux verticalement), qui sont disposés par rapport à
a. Notons que l’on utilise ici seulement les 4 voisins qui ont un coté commun avec le pixel considéré, ce qui
est différent du calcul de moyennes et de médianes où l’on utilisait 8 voisins. Ceci est important afin de
détecter aussi précisément que possible les bords des objets.
IV Application à la Bio-Informatique
L'ADN, pour Acide DésoxyriboNucléique, est une macromolécule constituée de deux brins qui forme une
double hélice maintenue par des liaisons hydrogène. Ces brins sont formés par un enchainement de maillons
appelés, nucléotides qui contiennent les bases de l'ADN :
A pour Adénine
T pour Thymine
G pour Guanine
C pour Cytosine
Les bases de l'ADN fonctionnent par paire, une sur chaque brin : adénine avec thymine et guanine avec
cytosine.
La transcription est un mécanisme qui permet de "recopier" l'ADN dans le noyau de la cellule pour former un
ARN (acide ribonucléique) qui sera utilisé dans la cellule notamment lors de la traduction. L'ARN présente la
même structure que l'ADN mais lors de la transcription, la thymine (T) est remplacée par l'uracile (U).
La traduction de l'ADN consiste à lire l'ARN issue de la transcription pour synthétiser une protéine avec l'aide
de la machinerie cellulaire. L'ARN est découpé en codons qui sont constitués de 3 bases et correspondent à un
acide aminé, c'est le code génétique. Les codons sont lus les uns à la suite des autres et les protéines sont
assemblées comme une chaîne (peptidique) d’acides aminés.
Le tableau ci-dessous vous donne la correspondance entre un codon, composé de trois bases de l'ARN et un
acide aminé.
1. Écrire une fonction prend en paramètre un brin ADN et réalise la transcription de l'ADN en ARN
2. Écrire une fonction qui traduit l'ARN et renvoie la chaîne d'acides aminés correspondante en se basant sur
le code génétique. Attention, elle doit s'arrêter au codon STOP.
3. Ecrire un script python qui permet de calculer le nombre d'acides aminés
1. Binarisation
import numpy as np
def Binariser(M,s):
n,p=np.shape(M)
M1=np.zeros((n,p))
for i in range(n):
for j in range(p):
if M[i,j]>s:
M1[i,j]=255
return M1
A=plt.imread("source.png")
B=Binariser(A,127)
plt.imshow(B)
plt.show()
plt.imsave("cible.png")
2. Contraste
f=lambda x:x-0.4*(x-127)
def Contraste(M):
n,p=np.shape(M)
M1=np.empty((n,p))
for i in range(n):
for j in range(p):
y=f(M[i,j])
if y>255:
M1[i,j]=255
elif y<0:
M1[i,j]=0
else:
M1[i,j]=y
return M1
def Negatif(M):
n,p=np.shape(M)
M1=np.empty((n,p))
for i in range(n):
for j in range(p):
M1[i,j]=255-M[i,j]
return M1
def Transformer(M):
R,V,B=M[:,:,0], M[:,:,1], M[:,:,2]
M1=0.21*R + 0,71*V + 0.07*B
return M1
def Filtrer_moy(M):
n,p=np.shape(M)
M1=M[:,:]
for i in range(1,n-1):
for j in range(1,p-1):
I=M[i-1:i+2,j-1,j+2]
return M1
def Filtrer_mediane(M):
n,p=np.shape(M)
M1=M[:,:]
for i in range(1,n-1):
for j in range(1,p-1):
I=M[i-1:i+2,j-1,j+2]
L.sort()
M1[i,j]=L[4]
return M1
7. Détection de contours
def Detecter_contours(M):
n,p=np.shape(M)
M1=M[:,:]
for i in range(1,n-1):
for j in range(1,p-1):
I=M[i-1:i+2,j-1,j+2]
l=int(np.sqrt((I[1,0]-I[0,1])**2+(I[1,2]-I[2,1])**2))
if l==0:
M1[i,j]=0
elif l>200:
M1[i,j]=255
return M1
import numpy as np
BASES_ADN=['A','T','C','G']
BASES_ARN=['A','U','C','G']
STOP=['TAA','TAG','TGA']
def gen_brins(nbases):
if nbases%3!=0 or nbases<9:
return('brin invalide')
else:
brin='AUG'
for i in range(nbases-6):
brin=brin+BASES_ADN[np.random.randint(0,4)]
brin=brin+STOP[np.random.randint(0,3)]
return(brin)
brin = gen_brins(18)
print(brin)
print(len(brin))
fragment = gen_brins(99)
print(fragment)
write_file(fragment, ‘adn.dat’)
read_adn(‘adn.dat’)
4. Identifier s'il s'agit d'un brin d'ADN ou d'ARN et si ce brin est valide
def is_valid(fragment, typ):
# type ADN ou ARN
if typ == "ADN":
bases = BASES_ADN
elif typ == "ARN":
bases = BASES_ARN
else:
print("typ doit être 'ARN' ou 'ADN', typ = %s" % typ)
valid=False
return valid
# valeur retournée
valid = True
# test multiple de 3
if len(fragment) % 3 != 0:
valid = False
print("Error number of bases")
return valid
# test des bases :
else:
for base in fragment:
if base not in bases:
valid = False
print("Error : ", base, " is not valid.")
break
return valid
# pour tester:
adn_ok = "TAATCCTAAAACCCT"
adn_bad = "TAATCCTAAAACCT" # erreur nbre de bases
arn_ok = "UAAUCCUAAAACCCU"
arn_bad = "UAAUYCUAAXACCCU" # erreur nom des bases
print("adn_ok : ", is_valid(adn_ok, "ADN"))
print("adn_bad : ", is_valid(adn_bad, "ADN"))
print("arn_ok : ", is_valid(arn_ok, "ARN"))
print("arn_bad : ", is_valid(arn_bad, "ARN"))
if not identify:
raise ValueError("ERREUR : codon %s non identifié" % uncodon)
return acideAmine
#pour tester:
print(codon_to_aa("CAA"))
print(codon_to_aa("AZF"))
Traduction de l’ARN
def traduction(fragment):
"""
Traduit le brin d'ARN en séquence peptidique.
Args:
fragment (str): fragment d'ARN à traduire
Returns:
sequence (str): séquence peptidique.
"""
#nombre de codons dans le fragment
ncodon = len(fragment) // 3
# traduction
sequence = ""
n = 0
while n < ncodon:
aa = codon_to_aa(fragment[3*n : 3*n+3])
if aa != "STOP":
sequence += aa + "-"
n += 1
else:
sequence += aa
break
return sequence
3. Nombres d’acides aminés
adn = gen_brins(21)
print(adn)
arn = transcription(adn)
print(arn)
sequence = traduction(arn)
print(sequence)
# exemple de résultat
AUGTCGCATTATTTCCTATAA
AUGUCGCAUUAUUUCCUAUAA
Met-Ser-His-Tyr-Phe-Leu-STOP
la sequence contient 7 acides aminés
Bibliographie et Netographie
Ouvrages :
Learning Python, Mark Lutz, Edition O’Reilly, Juin 2013, ISBN: 9781449355722.
Informatique pour tous en classes préparatoires aux grandes écoles, Benjamin Wack& al., Edition Eyrolles,
Août 2013, ISBN: 978-2-212-13700-2.
Supports de Cours
Support de Cours de M.Hammami, Simulation numérique, pour 2ème année préparatoire MP-PC-T, IPEIEM,
Année universitaire 2019-2020.
Support de Cours de S.Elloumi, Simulation numérique, pour 2ème année préparatoire BG, IPEIEM, Année
universitaire 2017-2018.
Sites Web :
https://www.python-course.eu/
https://www.ics.uci.edu/~brgallar/index.html
https://www.scipy.org/
https://numpy.org/
https://matplotlib.org/