<jupyter_start><jupyter_text>--- Introduction à Python pour le calcul scientifique :  Utilisation des librairies Numpy et MatplotlibPolytech Sorbonne, Main 3Analyse numérique et EDOAuteur : <NAME>--- Ce tutoriel a pour but de vous faire découvrir le language de programmation Python que nous allons utiliser en TP. Pour le calcul scientifique, deux librairies sont extrêmement utiles : Numpy et Matplotlib. Nous allons les présenter dans ce TP d'introduction.  Table des matières- [Numpy](Numpy)- [Matplotlib](Matplotlib)  Numpy **NumPy** est une librairie très populaire pour le calcul scientifique en Python (voir http://www.numpy.org/). Elle permet de construire des tableaux de dimension $N$ de façon très efficace et fournie, par exemple, des routines d'algèbre linéaire et des générateurs de nombres aléatoires.Dans ce cours d'*Analyse numérique et EDO* nous utiliserons essentiellement **Numpy** pour manipuler des tableaux. Pour les plus curieux d'entre vous, de nombreux exemples peuvent être trouvés sur le web. Ici, nous nous utiliserons des fonctionnalités somme toute assez basiques.Premièrement, il est nécessaire d'importer la librairie **Numpy** :<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>`np` est maintenant un alias qui nous permet d'accéder aux classes et fonctions contenues dans la libraire numpy.  Création de tableaux<jupyter_code># Tableau de dimension 1 (Vecteur)
a = np.array([[0], [1], [2], [3]])
print('a =',a)
print('a.shape =',a.shape)
print('a.size =',a.size)
# Tableau de dimension 2 (Matrice)
L1 = [0, 1, 2, 3]
L2 = [4, 5, 6, 7]
a = np.array([L1, L2])
print('a =', a)
print('a.shape =', a.shape)
print('a.size =', a.size)<jupyter_output>a = [[0 1 2 3]
 [4 5 6 7]]
a.shape = (2, 4)
a.size = 8<jupyter_text>**Remarque :** Dans un notebook, on peut utilise l'autocomplétion avec la touche tabulation. On peut également obtenir de l'aide de façon interactive :<jupyter_code>np.array?<jupyter_output><empty_output><jupyter_text>Il existe plusieurs fonctions numpy pour créer des tableaux.<jupyter_code># En imposant le nombre d'éléments
c = np.linspace(0, 1, 3)   # début, fin, nombre d'éléments
print('c =', c)
# En imposant le pas de discrétisation (l'écart entre deux éléments consécutifs)
a = np.arange(0,10,1) # 0 .. n-1  (!) pas=1
b = np.arange(1, 9, 2) # début, fin (exclusif), pas
c = np.arange(1, 2, 0.1) # début, fin (exclusif), pas
print('a =', a)
print('b =', b)
print('c =', c)
# Tableaux de zéros et de uns
a = np.zeros(2) # 1 dimension, nombre d'éléments
b = np.ones(3) # 1 dimension, nombre d'éléments
c = np.zeros((2, 3)) # 2-dimensions, tuple (nombre de lignes, nombre de colonnes)
print('a =', a)
print('b =', b)
print('c =', c)
# Initialisation aléatoire
a = 4*np.random.rand(3,3) + 1 # uniforme sur [1,5]
b = np.random.randn(4) # gaussien
print('a =', a)
print('b =', b)<jupyter_output>a = [[1.82025683 3.81314671 3.28578275]
 [2.76948466 1.94562143 4.36936415]
 [3.98635492 1.08279734 3.63305393]]
b = [ 1.62242837 -0.64856743 -0.4269511   0.01842231]<jupyter_text>Exercice1. Créer un vecteur nul de taille 10.2. Créer un vecteur contenant tous les entier de 10 à 49 (inclus).3. Créer un vecteur contenant une discrétisation de l'intervalle [0,1] avec 100 points.4. Créer une matrice de taille 3x3 contenant des valeurs aléatoires.Pour chaque question, on affichera la taille (`size`) et la forme (`shape`) du tableau.<jupyter_code>#écrire ici<jupyter_output><empty_output><jupyter_text>Indexation des tableauxEn Python, les indices des tableaux commencent à 0. Il est également possible de parcourir le tableaux à partid de la fin en utilisant des indices négatifs. Le symbole `:` permet d'extraire une plage de valeurs.<jupyter_code># Tableau de dimension 1
a = np.arange(10)
print("a : ",a)
print("Premier élément : ",a[0])
print("Dernier élément : ",a[9], a[-1])
print("Avant avant dernier élément : ", a[-3])
print("Élements 2 à 8 : ", a[1:9:2])
print("Extraire les éléments deux à deux : ",a[::2], a[0:9:2], a[0:-1:2] ) # début, fin, pas
# Tableau de dimension 2
L1 = [3,4,6,2]
L2 = [2,5,7,9]
M = np.array([L1,L2])
print("M :", M)
print("M[1,3]",M[1,3])
print("2e colonne : ", M[:,1])
print("1ere ligne : ", M[0,:])
print("Toutes les lignes et une colonne sur deux :\n",M[:,::2])<jupyter_output>M : [[3 4 6 2]
 [2 5 7 9]]
M[1,3] 9
2e colonne :  [4 5]
1ere ligne :  [3 4 6 2]
Toutes les lignes et une colonne sur deux :
 [[3 6]
 [2 7]]<jupyter_text>Exercice1. Construire une matrice de taille 10x10 qui ne contient que des 1 sur les bords et des zéros à l'intérieur.2. Construire une matrice de taille 8x8 et la remplir en alternant 0 et 1 (comme un damier).<jupyter_code>#écrire ici<jupyter_output><empty_output><jupyter_text>Boucle et tableauxOn peut également utiliser des boucles pour parcourir un tableau.<jupyter_code>a = np.zeros((3,4))
for i in range(a.shape[0]):
    for j in range(a.shape[1]):
        a[i,j] = (i+3)*(j+3)+i*j
print(a)<jupyter_output>[[ 9. 12. 15. 18.]
 [12. 17. 22. 27.]
 [15. 22. 29. 36.]]<jupyter_text>Quand c'est possible, il est préférable d'utiliser directement des opérations sur les tableaux plutôt que des boucles.<jupyter_code># Calcul de 3*a + 1 élément par élément
N = 100
a = np.linspace(0,1,N)
b = np.zeros(a.size)
%timeit for i in range(a.size): b[i] = 3*a[i]+1
# Calcul de 3*a + 1 de façon vectorielle
N = 100
a = np.linspace(0,1,N)
%timeit b = 3*a+1<jupyter_output>2.81 µs ± 316 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)<jupyter_text>D'autant plus que **Numpy** optimise la plupart des fonctions mathématiques usuelles pour le calcul vectoriel.<jupyter_code>def f(x):
    return np.exp(-x*x)*np.log(1 + x*np.sin(x))

print("test 1")
x = np.linspace(0, 1, 10000)
a = np.zeros(x.size)
%timeit for i in range(x.size): a[i] = f(x[i])

print("test 2")
x = np.linspace(0, 1, 10000)
%timeit a = f(x)<jupyter_output>test 1
62.6 ms ± 4.46 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
test 2
265 µs ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)<jupyter_text>Exercice1. Construire une fonction qui étant donné un entier N rend un tableau de taille Nx2 représentant des coordonnées cartésiennes.2. Construire une fonction qui étant donné un tableau de coordonnées cartésiennes rend un tableau de même taille contenant leur équivalent en coordonnées polaires.<jupyter_code>#écrire ici<jupyter_output><empty_output><jupyter_text>Matplotlib**Matplotlib** est une librairie Python pour la représentation graphique en 2D. Il peut être utiliser au sein d'un notebook jupyter directement pour produire des figures.**Matplotlib** is a Python package for 2 dimensional plots. It can be used to produce figures inline in jupyter  notebooks. Lot of documentations about numpy can be found on the web, we give below basic examples that will be usefull in the following.First, we need to import the matplotlib package.<jupyter_code># Nécessaire pour éxecuter matplotlib dans un notebook
%matplotlib inline   

# Charger les librairies
import matplotlib.pyplot as plt # librairie graphique
import numpy as np              # librairie pour le calcul scientifique<jupyter_output><empty_output><jupyter_text>Un premier graphiqueTraçons les graphes des fonctions cosinus et sinus entre $[-\pi,\pi]$.<jupyter_code>X = np.linspace(-np.pi, np.pi, 30)
COS, SIN = np.cos(X), np.sin(X)
plt.plot(X,COS)
plt.plot(X, SIN)
plt.show()<jupyter_output><empty_output><jupyter_text>Modifier les propriétés d'une figureLa plupart des propriétés d'une figure peuvent être modifiées : la couleur et le style des courbes, le titre de la figure, la légende, le axes... Traçons de nouveau les graphes des fonctions cosinus et sinus en spécifiant certaines de ces propriétés.<jupyter_code># Créer une figure de taille 10x5 pouces (1 pouce = 2.54 cm)
fig = plt.figure(figsize=(10, 5))

# On trace la fonction cosinus, ligne bleu continue (style), width=1 (épaisseur du trait), label=cosinus (pour la légende)
plt.plot(X, COS, color="blue", linestyle="-", linewidth=1, label='$cosinus$')

# On trace la fonction sinus, ligne rouge en pointillés (style), width=1 (épaisseur du trait), label=sinus
plt.plot(X, SIN, color="red", linestyle="-", linewidth=1, label='$sinus$')

# On donne les limite de la figure
plt.xlim(-np.pi*1.1, np.pi*1.1)
plt.ylim(-1.1, 1.1)

# On nomme l'axe des abscisses
plt.xlabel('x', fontsize=18)

# On ajoute un titre
plt.title('Les fonctions cosinus et sinus', fontsize=18)

# On ajoute une légende dans le coin supérieur droit
plt.legend()

# On affiche la figure
plt.show()<jupyter_output><empty_output><jupyter_text>Exercice Sur la figure ci-dessus, ajouter les courbes des fonctions $x\to 1- \cos(x)$ et $x \to x - \sin(x)$ pour tout $x$ dans $[0,\pi]$. Choisissez vous-même le style des courbes et ajoutez les à la légende.  Tracer des sous-figuresPour Matplotlib, une "figure" signifie la fenêtre graphique entière. À l'intérieur d'une figure, nous pouvons néanmoins tracer des `subplots`, c'est-à-dire des sous-figures.<jupyter_code># Créer la figure
fig = plt.figure(figsize=(10, 5))

# Création d'un 'subplot' 
# arguments: (nombre lignes, nombre colonnes, numéro du subplot courant)
plt.subplot(1, 2, 1)  # grid 1 x 2, subplot courant =1
plt.plot(X, COS, color="blue", linestyle="-", linewidth=1)
plt.xlim(-np.pi*1.1, np.pi*1.1)
plt.ylim(-1.1, 1.1)
plt.title('Function cosinus', fontsize=18)

# Création du second subplot 
plt.subplot(1, 2, 2)  # grid 1 x 2, subplot courant = 2
plt.plot(X, SIN, color="red", linestyle="-", linewidth=1)
plt.xlim(-np.pi*1.1, np.pi*1.1)
plt.ylim(-1.1, 1.1)
plt.title('Function sinus', fontsize=18)

plt.show()<jupyter_output><empty_output><jupyter_text>Pour imposer la même échelle sur les deux axes<jupyter_code># Création de la figure
fig = plt.figure(figsize=(15, 5))

# Création du premier subplot 
plt.subplot(1, 2, 1)  # grid 1 x 2, current plot =1
plt.plot(COS, SIN, color="blue", linestyle="-", linewidth=1)
plt.title("Sans l'option 'equal'", fontsize=18)

# Création du second subplot 
plt.subplot(1, 2, 2)  # grid 1 x 2, current plot = 2
plt.axis('equal')
plt.plot(COS, SIN, color="red", linestyle="-", linewidth=1)
plt.title("Avec l'option 'equal'", fontsize=18)

plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1295915368792242, 'fraction_numerical': 0.04525418748163385, 'mean_word_length': 4.939499709133217, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '346907', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 4195, 'n_tokens_neox': 3923, 'n_words': 1281, 'path': 'TP_0_Introduction_Python.ipynb', 'repo_name': 'Fvergnet/main3-man-TP0', 'size': '10217'}